diff --git a/resources/profiles/Anker.idx b/resources/profiles/Anker.idx index 4a988bbdff..49e15b3d03 100644 --- a/resources/profiles/Anker.idx +++ b/resources/profiles/Anker.idx @@ -1,2 +1,3 @@ min_slic3r_version = 2.6.0-alpha1 +1.0.1 Disabled thick bridges. 1.0.0 Initial Version diff --git a/resources/profiles/Anker.ini b/resources/profiles/Anker.ini index c7408f6e4d..34592e1e55 100644 --- a/resources/profiles/Anker.ini +++ b/resources/profiles/Anker.ini @@ -6,7 +6,7 @@ name = Anker # Configuration version of this file. Config file will only be installed, if the config_version differs. # This means, the server may force the PrusaSlicer configuration to be downgraded. -config_version = 1.0.0 +config_version = 1.0.1 # Where to get the updates from? config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Anker/ @@ -118,7 +118,7 @@ support_material_synchronize_layers = 0 support_material_threshold = 40 support_material_with_sheath = 0 support_material_xy_spacing = 60% -thick_bridges = 1 +thick_bridges = 0 thin_walls = 0 top_solid_infill_speed = 150 travel_speed = 300 diff --git a/resources/profiles/Geeetech.idx b/resources/profiles/Geeetech.idx new file mode 100644 index 0000000000..dbb458994c --- /dev/null +++ b/resources/profiles/Geeetech.idx @@ -0,0 +1,4 @@ +min_slic3r_version = 2.6.0-alpha1 +0.1.0 Initial Geeetech bundle + + diff --git a/resources/profiles/Geeetech.ini b/resources/profiles/Geeetech.ini new file mode 100644 index 0000000000..0b1ae86c5d --- /dev/null +++ b/resources/profiles/Geeetech.ini @@ -0,0 +1,1913 @@ +# Print profiles for the Geeetech printers. +# Author: Teddy.hu@geeetech.cn (2022.11.23) +# https://github.com/prusa3d/PrusaSlicer/pull/9221 by @alexwoo1900 + +[vendor] +# Vendor name will be shown by the Config Wizard. +name = Geeetech +# Configuration version of this file. Config file will only be installed, if the config_version differs. +# This means, the server may force the PrusaSlicer configuration to be downgraded. +config_version = 0.1.0 +# Where to get the updates from? +config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Geeetech/ + +# The printer models will be shown by the Configuration Wizard in this order, +# also the first model installed & the first nozzle installed will be activated after install. +# Printer model name will be shown by the installation wizard. + +[printer_model:Thunder] +name = Geeetech Thunder +variants = 0.4; 0.2; 0.6; 0.8 +technology = FFF +family = Thunder +bed_model = 250x250.stl +bed_texture = 250x250.svg +default_materials = Thunder HS-PLA @Geeetech; Thunder PLA @Geeetech; Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:ThunderPro] +name = Geeetech Thunder Pro +variants = 0.4; 0.2; 0.6; 0.8 +technology = FFF +family = Thunder +bed_model = 250x250.stl +bed_texture = 250x250.svg +default_materials = Thunder HS-PLA @Geeetech; Thunder PLA @Geeetech; Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:MizarS] +name = Geeetech Mizar S +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = Mizar +bed_model = 255x255.stl +bed_texture = 255x255.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:MizarPro] +name = Geeetech Mizar Pro +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = Mizar +bed_model = 220x220.stl +bed_texture = 220x220.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:Mizar] +name = Geeetech Mizar +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = Mizar +bed_model = 220x220.stl +bed_texture = 220x220.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:MizarMax] +name = Geeetech Mizar Max +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = Mizar +bed_model = 320x320.stl +bed_texture = 320x320.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:MizarM] +name = Geeetech Mizar M +variants = 0.4 +technology = FFF +family = Mizar +bed_model = 255x255.stl +bed_texture = 255x255.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +#[printer_model:MizarT] +#name = Geeetech Mizar T +#variants = 0.4 +#technology = FFF +#family = Mizar +#bed_model = 255x255.stl +#bed_texture = 255x255.svg +#default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:A10Pro] +name = Geeetech A10 Pro +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = A10 +bed_model = 220x220.stl +bed_texture = 220x220.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:A10M] +name = Geeetech A10 M +variants = 0.4 +technology = FFF +family = A10 +bed_model = 220x220.stl +bed_texture = 220x220.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:A10T] +name = Geeetech A10 T +variants = 0.4 +technology = FFF +family = A10 +bed_model = 220x220.stl +bed_texture = 220x220.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:A20] +name = Geeetech A20 +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = A20 +bed_model = 250x250.stl +bed_texture = 250x250.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:A20M] +name = Geeetech A20 M +variants = 0.4 +technology = FFF +family = A20 +bed_model = 250x250.stl +bed_texture = 250x250.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:A20T] +name = Geeetech A20 T +variants = 0.4 +technology = FFF +family = A20 +bed_model = 250x250.stl +bed_texture = 250x250.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:A30Pro] +name = Geeetech A30 Pro +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = A30 +bed_model = 320x320.stl +bed_texture = 320x320.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:A30M] +name = Geeetech A30 M +variants = 0.4 +technology = FFF +family = A30 +bed_model = 320x320.stl +bed_texture = 320x320.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:A30T] +name = Geeetech A30 T +variants = 0.4 +technology = FFF +family = A30 +bed_model = 320x320.stl +bed_texture = 320x320.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:E180] +name = Geeetech E180 +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = E180 +bed_model = 125X130.stl +bed_texture = 125X130.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:MeDucer] +name = Geeetech Me Ducer +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = Me +bed_model = 180X150.stl +bed_texture = 180X150.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:MeCreator] +name = Geeetech Me Creator +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = Me +bed_model = 150x150.stl +bed_texture = 150x150.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:MeCreator2] +name = Geeetech Me Creator2 +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = Me +bed_model = 160x160.stl +bed_texture = 160x160.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:GiantArmD200] +name = Geeetech GiantArmD200 +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = D200 +bed_model = 300x180.stl +bed_texture = 300x180.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:I3ProB] +name = Geeetech I3 ProB +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = I3 +bed_model = 200x200.stl +bed_texture = 200x200.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:I3ProW] +name = Geeetech I3 ProW +variants = 0.4; 0.2; 0.3; 0.5; 0.6; 0.8 +technology = FFF +family = I3 +bed_model = 200x200.stl +bed_texture = 200x200.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +[printer_model:I3ProC] +name = Geeetech I3 ProC +variants = 0.4 +technology = FFF +family = I3 +bed_model = 200x200.stl +bed_texture = 200x200.svg +default_materials = Generic PLA @Geeetech; Generic PETG @Geeetech; Generic ABS @Geeetech; Generic TPU @Geeetech; Geeetech PLA @Geeetech; Geeetech PETG @Geeetech; Geeetech ABS @Geeetech + +# All presets starting with asterisk, for example *common*, are intermediate and they will not make it into the user interface. + +######################################### +####### Start ###print presets ######## +######################################### + +[print:*common*] +# Print presets for common printers +avoid_crossing_perimeters = 0 +bridge_angle = 0 +bridge_flow_ratio = 0.95 +brim_width = 0 +clip_multipart_objects = 1 +compatible_printers = +complete_objects = 0 +default_acceleration = 500 +dont_support_bridges = 1 +elefant_foot_compensation = 0.1 +ensure_vertical_shell_thickness = 1 +external_fill_pattern = rectilinear +external_perimeters_first = 0 +extra_perimeters = 0 +extruder_clearance_height = 34 +extruder_clearance_radius = 47 +fill_angle = 45 +fill_density = 15% +fill_pattern = grid +gcode_comments = 0 +infill_every_layers = 1 +infill_extruder = 1 +infill_first = 0 +infill_only_where_needed = 0 +infill_overlap = 23% +interface_shells = 0 +min_skirt_length = 4 +notes = +overhangs = 0 +only_retract_when_crossing_perimeters = 0 +ooze_prevention = 0 +perimeter_extruder = 1 +post_process = +print_settings_id = +raft_layers = 0 +resolution = 0 +seam_position = aligned +single_extruder_multi_material_priming = 0 +skirts = 1 +skirt_distance = 6 +skirt_height = 1 +solid_infill_below_area = 20 +solid_infill_every_layers = 0 +solid_infill_extruder = 1 +spiral_vase = 0 +standby_temperature_delta = -5 +support_material = 0 +support_material_extruder = 0 +support_material_interface_extruder = 0 +support_material_angle = 0 +support_material_buildplate_only = 0 +support_material_enforce_layers = 0 +support_material_contact_distance = 0.15 +support_material_interface_contact_loops = 0 +support_material_interface_layers = 2 +support_material_interface_spacing = 0.2 +support_material_pattern = rectilinear +support_material_spacing = 2 +support_material_synchronize_layers = 0 +support_material_threshold = 40 +support_material_with_sheath = 0 +support_material_xy_spacing = 60% +thin_walls = 0 +wipe_tower = 0 +xy_size_compensation = 0 +# speed +gap_fill_enabled = 1 +default speed =100 +perimeter_speed = 60 +external_perimeter_speed = 50% +solid_infill_speed = 50% +infill_speed = 80 +top_solid_infill_speed = 25% +support_material_speed = 60 +support_material_interface_speed = 50% +brim_speed = 50% +bridge_speed = 60 +bridge_speed_internal = 100% +overhangs_speed = 100% +gap_fill_speed = 30 +gap_fill_flow_match_perimeter = 0 +thin_walls_speed = 100% +ironing_speed = 50% +travel_speed = 150 +travel_speed_z = 0 +first_layer_min_speed = 0 +first_layer_speed =20 +first_layer_infill_speed = 0 +first_layer_speed_over_raft = 30 +small_perimeter_speed = 25% +small_perimeter_min_length = 6 +small_perimeter_max_length = 20 +max_volumetric_speed = 0 +max_print_speed = 100 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +# extrusion_width +extrusion_width = 0 +extrusion_spacing = +first_layer_extrusion_width = 111% +first_layer_extrusion_spacing = +perimeter_extrusion_width = 111% +perimeter_extrusion_spacing = +external_perimeter_extrusion_width = 105% +external_perimeter_extrusion_spacing = +infill_extrusion_width = 111% +infill_extrusion_spacing = +solid_infill_extrusion_width = 111% +solid_infill_extrusion_spacing = +top_infill_extrusion_width = 105% +top_infill_extrusion_spacing = +support_material_extrusion_width = 0 +skirt_extrusion_width = 130% + +[print:*High-speed*] +# Print presets for high-speed printers. +inherits = *common* +top_solid_layers = 3 +bottom_solid_layers = 3 +gap_fill_enabled = 0 +default_acceleration = 5000 +default speed =250 +perimeter_speed = 230 +external_perimeter_speed = 83% +solid_infill_speed = 80 +infill_speed = 250 +top_solid_infill_speed =100% +support_material_speed = 100 +support_material_interface_speed = 50% +brim_speed = 30% +bridge_speed = 180 +bridge_speed_internal = 120% +overhangs_speed = 120% +gap_fill_speed = 100 +gap_fill_flow_match_perimeter = 0 +thin_walls_speed = 100% +ironing_speed = 75% +travel_speed = 260 +travel_speed_z = 0 +first_layer_min_speed = 0 +first_layer_speed =30 +first_layer_infill_speed = 0 +first_layer_speed_over_raft = 30 +small_perimeter_speed = 65% +max_print_speed = 300 +max_volumetric_extrusion_rate_slope_negative = 0 +max_volumetric_extrusion_rate_slope_positive = 0 +small_perimeter_min_length = 8 +small_perimeter_max_length = 25.1327 +solid_infill_below_area = 0 +#travel_speed = {if 120<=infill_speed<=200}200{elsif infill_speed>200}infill_speed{else}150{endif} +#perimeter_speed = {if infill_speed<60}math.ceil(round(infill_speed*0.8){elsif infill_speed>60}math.ceil(round(infill_speed*0.75)){else}60{endif} +#external_perimeter_speed = {if infill_speed<=60}math.ceil(round(infill_speed*0.5)){else}math.ceil(round(infill_speed*0.75)){endif} +#solid_infill_speed = {if infill_speed<=60}20{else}math.ceil(round(infill_speed*0.3)){endif} +#top_solid_infill_speed = {if infill_speed<=60}20{elsif 6060}math.ceil(round(infill_speed*0.5){else}40{endif} +#bridge_speed = {if infill_speed<=60}math.ceil(round(infill_speed*0.5)){else}math.ceil(round(infill_speed*0.75)){endif} +#bridge_speed_internal = {if infill_speed<=60}math.ceil(round(infill_speed*1.5)){elsif 60=2 + +# Print layer_height(0.08mm,0.10mm,0.12mm,0.16mm,0.20mm,0.24mm,0.28mm,0.36mm,0.44mm) +[print:*0.08mm*] +inherits = *common* +layer_height = 0.08 +first_layer_height = 0.12 +bottom_solid_layers = 9 +top_solid_layers = 11 +bridge_flow_ratio = 0.70 + +[print:*0.10mm*] +inherits = *common* +layer_height = 0.10 +first_layer_height = 0.15 +bottom_solid_layers = 7 +top_solid_layers = 9 +bridge_flow_ratio = 0.70 + +[print:*0.12mm*] +inherits = *common* +layer_height = 0.12 +first_layer_height = 0.18 +bottom_solid_layers = 6 +top_solid_layers = 7 +bridge_flow_ratio = 0.70 + +[print:*0.16mm*] +inherits = *common* +layer_height = 0.16 +first_layer_height = 0.16 +bottom_solid_layers = 5 +top_solid_layers = 7 +bridge_flow_ratio = 0.85 + +[print:*0.20mm*] +inherits = *common* +layer_height = 0.20 +first_layer_height = 0.24 +bottom_solid_layers = 4 +top_solid_layers = 5 + +[print:*0.24mm*] +inherits = *common* +layer_height = 0.24 +first_layer_height = 0.30 +bottom_solid_layers = 3 +top_solid_layers = 4 + +[print:*0.28mm*] +inherits = *common* +layer_height = 0.28 +first_layer_height = 0.30 +bottom_solid_layers = 3 +top_solid_layers = 4 + +[print:*0.36mm*] +inherits = *common* +layer_height = 0.36 +first_layer_height = 0.36 +bottom_solid_layers = 3 +top_solid_layers = 4 + +[print:*0.44mm*] +inherits = *common* +layer_height = 0.44 +first_layer_height = 0.44 +bottom_solid_layers = 3 +top_solid_layers = 4 + +# Nozzle Size(0.2nozzle,0.3nozzle,0.4nozzle,0.5nozzle,0.6nozzle,0.8nozzle) +[print:*0.2nozzle*] +elefant_foot_compensation = 0 +support_material_interface_layers = 0 +support_material_interface_spacing = 0.15 +support_material_spacing = 1 +support_material_xy_spacing = 150% +support_material_contact_distance = 0.1 +output_filename_format = {input_filename_base}_{nozzle_diameter[0]}nozzle_{layer_height}mm_{initial_filament_type}_{printer_model}_{print_time}.gcode +thick_bridges = 0 +bridge_flow_ratio = 1 +bridge_speed = 20 +wipe_tower_bridging = 6 +wall_transition_angle = 10 +wall_transition_filter_deviation = 25% +wall_transition_length = 0.25 +wall_distribution_count = 1 +min_bead_width = 85% + +[print:*0.3nozzle*] +perimeters = 4 +support_material_interface_spacing = 0.15 +support_material_spacing = 1 +output_filename_format = {input_filename_base}_{nozzle_diameter[0]}nozzle_{layer_height}mm_{initial_filament_type}_{printer_model}_{print_time}.gcode + +[print:*0.4nozzle*] +perimeters = 3 +support_material_interface_spacing = 0.2 +support_material_spacing = 1 +output_filename_format = {input_filename_base}_{nozzle_diameter[0]}nozzle_{digits(layer_height,1,2)}mm_{if num_extruders==1}{filament_type[0]}{elsif num_extruders==2}E0{filament_type[0]}_E1{filament_type[1]}{else}E0{filament_type[0]}_E1{filament_type[1]}E2{filament_type[2]}{endif}_{temperature[0]}C_{printer_model}_{print_time}.gcode + +[print:*0.5nozzle*] +perimeters = 2 +support_material_interface_spacing = 0.25 +support_material_spacing = 1.1 +output_filename_format = {input_filename_base}_{nozzle_diameter[0]}nozzle_{layer_height}mm_{initial_filament_type}_{printer_model}_{print_time}.gcode + +[print:*0.6nozzle*] +perimeters = 2 +support_material_contact_distance = 0.15 +support_material_xy_spacing = 80% +support_material_interface_spacing = 0.3 +output_filename_format = {input_filename_base}_{nozzle_diameter[0]}nozzle_{layer_height}mm_{initial_filament_type}_{printer_model}_{print_time}.gcode +infill_anchor_max = 15 +top_solid_min_thickness = 0.9 +bottom_solid_min_thickness = 0.6 +thick_bridges = 0 +bridge_flow_ratio = 0.95 +bridge_speed = 25 +wall_transition_angle = 10 +wall_transition_filter_deviation = 25% +wall_transition_length = 0.6 +wall_distribution_count = 1 +min_bead_width = 85% + +[print:*0.8nozzle*] +support_material_contact_distance = 0.25 +support_material_spacing = 2 +support_material_interface_spacing = 0.4 +support_material_interface_speed = 100% +support_material_xy_spacing = 80% +support_material_threshold = 50 +output_filename_format = {input_filename_base}_{nozzle_diameter[0]}nozzle_{layer_height}mm_{initial_filament_type}_{printer_model}_{print_time}.gcode +fill_pattern = gyroid +fill_density = 15% +infill_anchor_max = 20 +top_solid_layers = 4 +bottom_solid_layers = 3 +skirt_distance = 3 +skirt_height = 2 +infill_overlap = 30% +bridge_speed = 22 +gap_fill_speed = 30 +bridge_flow_ratio = 0.9 +top_solid_min_thickness = 1.2 +bottom_solid_min_thickness = 0.8 +single_extruder_multi_material_priming = 0 +thick_bridges = 1 +overhangs = 0 +wall_transition_angle = 10 +wall_transition_filter_deviation = 25% +wall_transition_length = 0.8 +wall_distribution_count = 1 +min_bead_width = 85% + +# Print quality of Common printers with different nozzle diameters +[print:0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech] +inherits = *0.08mm*; *0.2nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.2 and num_extruders==1 + +[print:0.08 mm SUPERDETAIL (0.3mm nozzle) @Geeetech] +inherits = *0.08mm*; *0.3nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.3 and num_extruders==1 + +[print:0.08 mm SUPERDETAIL @Geeetech] +inherits = *0.08mm*; *0.4nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.08 mm SUPERDETAIL (0.5mm nozzle) @Geeetech] +inherits = *0.08mm*; *0.5nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.5 and num_extruders==1 + +[print:0.08 mm SUPERDETAIL (0.6mm nozzle) @Geeetech] +inherits = *0.08mm*; *0.6nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.10 mm HIGHDETAIL (0.2mm nozzle) @Geeetech] +inherits = *0.10mm*; *0.2nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.2 and num_extruders==1 + +[print:0.10 mm HIGHDETAIL (0.3mm nozzle) @Geeetech] +inherits = *0.10mm*; *0.3nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.3 and num_extruders==1 + +[print:0.10 mm HIGHDETAIL @Geeetech] +inherits = *0.10mm*; *0.4nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.10 mm HIGHDETAIL (0.5mm nozzle) @Geeetech] +inherits = *0.10mm*; *0.5nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.5 and num_extruders==1 + +[print:0.10 mm HIGHDETAIL (0.6mm nozzle) @Geeetech] +inherits = *0.10mm*; *0.6nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.12 mm DETAIL (0.2mm nozzle) @Geeetech] +inherits = *0.12mm*; *0.2nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.2 and num_extruders==1 + +[print:0.12 mm DETAIL (0.3mm nozzle) @Geeetech] +inherits = *0.12mm*; *0.3nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.3 and num_extruders==1 + +[print:0.12 mm DETAIL @Geeetech] +inherits = *0.12mm*; *0.4nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.12 mm DETAIL (0.5mm nozzle) @Geeetech] +inherits = *0.12mm*; *0.5nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.5 and num_extruders==1 + +[print:0.12 mm DETAIL (0.6mm nozzle) @Geeetech] +inherits = *0.12mm*; *0.6nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.16 mm OPTIMAL (0.2mm nozzle) @Geeetech] +inherits = *0.16mm*; *0.2nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.2 and num_extruders==1 + +[print:0.16 mm OPTIMAL (0.3mm nozzle) @Geeetech] +inherits = *0.16mm*; *0.3nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.3 and num_extruders==1 + +[print:0.16 mm OPTIMAL @Geeetech] +inherits = *0.16mm*; *0.4nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.16 mm OPTIMAL (0.5mm nozzle) @Geeetech] +inherits = *0.16mm*; *0.5nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.5 and num_extruders==1 + +[print:0.16 mm OPTIMAL (0.6mm nozzle) @Geeetech] +inherits = *0.16mm*; *0.6nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.20 mm NORMAL (0.3mm nozzle) @Geeetech] +inherits = *0.20mm*; *0.3nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.3 and num_extruders==1 + +[print:0.20 mm NORMAL @Geeetech] +inherits = *0.20mm*; *0.4nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.20 mm NORMAL (0.5mm nozzle) @Geeetech] +inherits = *0.20mm*; *0.5nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.5 and num_extruders==1 + +[print:0.20 mm NORMAL (0.6mm nozzle) @Geeetech] +inherits = *0.20mm*; *0.6nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.24 mm DRAFT @Geeetech] +inherits = *0.24mm*; *0.4nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.24 mm DRAFT (0.5mm nozzle) @Geeetech] +inherits = *0.24mm*; *0.5nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.5 and num_extruders==1 + +[print:0.24 mm DRAFT (0.6mm nozzle) @Geeetech] +inherits = *0.24mm*; *0.6nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.28 mm SUPERDRAFT @Geeetech] +inherits = *0.28mm*; *0.4nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech] +inherits = *0.28mm*; *0.5nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.5 and num_extruders==1 + +[print:0.28 mm SUPERDRAFT (0.6mm nozzle) @Geeetech] +inherits = *0.28mm*; *0.6nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.36 mm CHUNKY (0.5mm nozzle) @Geeetech] +inherits = *0.36mm*; *0.5nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.5 and num_extruders==1 + +[print:0.36 mm CHUNKY (0.6mm nozzle) @Geeetech] +inherits = *0.36mm*; *0.6nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.36 mm CHUNKY (0.8mm nozzle) @Geeetech] +inherits = *0.36mm*; *0.8nozzle* +perimeter_acceleration = 800 +infill_acceleration = 1000 +bridge_acceleration = 1000 +first_layer_acceleration = 800 +default_acceleration = 1000 +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.8 and num_extruders==1 + +[print:0.44 mm SUPERCHUNKY (0.6mm nozzle) @Geeetech] +inherits = *0.44mm*; *0.6nozzle* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech] +inherits = *0.44mm*; *0.8nozzle* +perimeter_acceleration = 800 +infill_acceleration = 1000 +bridge_acceleration = 1000 +first_layer_acceleration = 800 +default_acceleration = 1000 +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.8 and num_extruders==1 + +# Print quality of HighSpeed printers with different nozzle diameters +[print:0.08 mm SUPERDETAIL (0.2mm nozzle) @High-speed] +inherits = *0.08mm*; *0.2nozzle*; *High-speed* +max_volumetric_speed = 15 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.2 and num_extruders==1 + +[print:0.08 mm SUPERDETAIL @High-speed] +inherits = *0.08mm*; *0.4nozzle*; *High-speed* +max_volumetric_speed = 52.8 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.08 mm SUPERDETAIL (0.6mm nozzle) @High-speed] +inherits = *0.08mm*; *0.6nozzle*; *High-speed* +max_volumetric_speed = 117 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.10 mm HIGHDETAIL (0.2mm nozzle) @High-speed] +inherits = *0.10mm*; *0.2nozzle*; *High-speed* +max_volumetric_speed = 15 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.2 and num_extruders==1 + +[print:0.10 mm HIGHDETAIL @High-speed] +inherits = *0.10mm*; *0.4nozzle*; *High-speed* +max_volumetric_speed = 52.8 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.10 mm HIGHDETAIL (0.6mm nozzle) @High-speed] +inherits = *0.10mm*; *0.6nozzle*; *High-speed* +max_volumetric_speed = 117 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.12 mm DETAIL (0.2mm nozzle) @High-speed] +inherits = *0.12mm*; *0.2nozzle*; *High-speed* +max_volumetric_speed = 15 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.2 and num_extruders==1 + +[print:0.12 mm DETAIL @High-speed] +inherits = *0.12mm*; *0.4nozzle*; *High-speed* +max_volumetric_speed = 52.8 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.12 mm DETAIL (0.6mm nozzle) @High-speed] +inherits = *0.12mm*; *0.6nozzle*; *High-speed* +max_volumetric_speed = 117 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.16 mm OPTIMAL (0.2mm nozzle) @High-speed] +inherits = *0.16mm*; *0.2nozzle*; *High-speed* +max_volumetric_speed = 15 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.2 and num_extruders==1 + +[print:0.16 mm OPTIMAL @High-speed] +inherits = *0.16mm*; *0.4nozzle*; *High-speed* +max_volumetric_speed = 52.8 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.16 mm OPTIMAL (0.6mm nozzle) @High-speed] +inherits = *0.16mm*; *0.6nozzle*; *High-speed* +max_volumetric_speed = 117 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.20 mm NORMAL @High-speed] +inherits = *0.20mm*; *0.4nozzle*; *High-speed* +first_layer_height = 0.30 +max_volumetric_speed = 52.8 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.20 mm NORMAL (0.6mm nozzle) @High-speed] +inherits = *0.20mm*; *0.6nozzle*; *High-speed* +max_volumetric_speed = 117 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.24 mm DRAFT @High-speed] +inherits = *0.24mm*; *0.4nozzle*; *High-speed* +max_volumetric_speed = 52.8 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.24 mm DRAFT (0.6mm nozzle) @High-speed] +inherits = *0.24mm*; *0.6nozzle*; *High-speed* +max_volumetric_speed = 117 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.28 mm SUPERDRAFT @High-speed] +inherits = *0.28mm*; *0.4nozzle*; *High-speed* +max_volumetric_speed = 52.8 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.4 and num_extruders==1 + +[print:0.28 mm SUPERDRAFT (0.6mm nozzle) @High-speed] +inherits = *0.28mm*; *0.6nozzle*; *High-speed* +max_volumetric_speed = 117 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.36 mm CHUNKY (0.6mm nozzle) @High-speed] +inherits = *0.36mm*; *0.6nozzle*; *High-speed* +max_volumetric_speed = 117 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.36 mm CHUNKY (0.8mm nozzle) @High-speed] +inherits = *0.36mm*; *0.8nozzle*; *High-speed* +max_volumetric_speed = 216 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.8 and num_extruders==1 + +[print:0.44 mm SUPERCHUNKY (0.6mm nozzle) @High-speed] +inherits = *0.44mm*; *0.6nozzle*; *High-speed* +max_volumetric_speed = 117 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.6 and num_extruders==1 + +[print:0.44 mm SUPERCHUNKY (0.8mm nozzle) @High-speed] +inherits = *0.44mm*; *0.8nozzle*; *High-speed* +max_volumetric_speed = 216 +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ and nozzle_diameter[0]==0.8 and num_extruders==1 + +# Print quality for multi-extruder printers (0.4mm nozzle diameter) +[print:0.08 mm SUPERDETAIL @Multi-extruder] +inherits = *0.08mm*; *0.4nozzle*; *Multi-extruder* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders>=2 + +[print:0.10 mm HIGHDETAIL @Multi-extruder] +inherits = *0.10mm*; *0.4nozzle*; *Multi-extruder* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders>=2 + +[print:0.12 mm DETAIL @Multi-extruder] +inherits = *0.12mm*; *0.4nozzle*; *Multi-extruder* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders>=2 + +[print:0.16 mm OPTIMAL @Multi-extruder] +inherits = *0.16mm*; *0.4nozzle*; *Multi-extruder* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders>=2 + +[print:0.20 mm NORMAL @Multi-extruder] +inherits = *0.20mm*; *0.4nozzle*; *Multi-extruder* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders>=2 + +[print:0.24 mm DETAIL @Multi-extruder] +inherits = *0.24mm*; *0.4nozzle*; *Multi-extruder* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders>=2 + +[print:0.28 mm SUPERDRAFT @Multi-extruder] +inherits = *0.28mm*; *0.4nozzle*; *Multi-extruder* +compatible_printers_condition = printer_model=~/(Mizar|A10|A20|A30|E180|Me|GiantArm|I3).*/ and nozzle_diameter[0]==0.4 and num_extruders>=2 +######################################### +####### End ###print presets ######## +######################################### + + +# When submitting new filaments please print the following temperature tower at 0.1mm layer height: +# https://www.thingiverse.com/thing:2615842 +# Pay particular attention to bridging, overhangs and retractions. +# Also print the following bed adhesion test at 0.1 layer height as well: +# https://www.prusaprinters.org/prints/4634-bed-adhesion-warp-test +# At least for PLA, please keep bed temp at 60℃, as many Geeetech printers do not have any ABL +# So having some leeway to get good bed adhesion is not a luxury for many users + + +######################################### +####### Start ###filament presets ####### +######################################### +[filament:*common*] +# Filament presets for common printers +cooling = 0 +filament_vendor = Generic +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_Geeetech.*/ +extrusion_multiplier = 1 +filament_cost = 0 +filament_density = 0 +filament_diameter = 1.75 +filament_notes = "" +filament_settings_id = "" +filament_soluble = 0 +min_print_speed = 15 +slowdown_below_layer_time = 20 +filament_minimal_purge_on_wipe_tower = 25 + +[filament:*PLA*] +inherits = *common* +fan_below_layer_time = 100 +filament_colour = #DDDDDD +filament_max_volumetric_speed = 0 +filament_type = PLA +filament_density = 1.24 +filament_cost = 20 +first_layer_temperature = 210 +temperature = 205 +first_layer_bed_temperature = 60 +bed_temperature = 60 +fan_always_on = 1 +cooling = 1 +max_fan_speed = 100 +min_fan_speed = 100 +bridge_fan_speed = 100 +disable_fan_first_layers = 2 + +[filament:*PETG*] +inherits = *common* +bed_temperature = 70 +cooling = 1 +disable_fan_first_layers = 3 +fan_below_layer_time = 20 +filament_colour = #DDDDDD +filament_max_volumetric_speed = 0 +filament_type = PETG +filament_density = 1.27 +filament_cost = 30 +first_layer_bed_temperature = 70 +first_layer_temperature = 240 +fan_always_on = 1 +max_fan_speed = 50 +min_fan_speed = 20 +bridge_fan_speed = 100 +temperature = 240 + +[filament:*ABS*] +inherits = *common* +bed_temperature = 100 +cooling = 0 +disable_fan_first_layers = 3 +fan_below_layer_time = 20 +filament_colour = #DDDDDD +filament_max_volumetric_speed = 0 +filament_type = ABS +filament_density = 1.04 +filament_cost = 20 +first_layer_bed_temperature = 100 +first_layer_temperature = 245 +fan_always_on = 0 +max_fan_speed = 0 +min_fan_speed = 0 +bridge_fan_speed = 30 +top_fan_speed = 0 +temperature = 245 + +[filament:*TPU*] +inherits = *common* +bed_temperature = 55 +cooling = 0 +disable_fan_first_layers = 3 +fan_always_on = 0 +fan_below_layer_time = 20 +filament_colour = #CFFFFB +filament_cost = 30 +filament_density = 1.2 +filament_max_volumetric_speed = 0 +filament_retract_before_travel = 4 +filament_retract_length = 2.5 +filament_retract_speed = 30 +filament_type = TPU +first_layer_bed_temperature = 55 +first_layer_temperature = 210 +max_fan_speed = 70 +min_fan_speed = 0 + +[filament:*HS-PLA*] +inherits = *common* +filament_vendor = Geeetech +filament_colour = #F94D0C +filament_max_volumetric_speed = 0 +filament_type = PLA +filament_density = 1.24 +filament_cost = 20 +first_layer_temperature = 210 +temperature = 215 +first_layer_bed_temperature = 60 +bed_temperature = 60 +cooling = 1 +fan_always_on = 1 +min_fan_speed = 100 +bridge_fan_speed = 100 +bridge_internal_fan_speed = -1 +top_fan_speed = -1 +external_perimeter_fan_speed = -1 +support_material_interface_fan_speed = -1 +disable_fan_first_layers = 1 +full_fan_speed_layer = 0 +fan_below_layer_time = 10 +max_fan_speed = 100 +slowdown_below_layer_time = 1 +max_speed_reduction = 15 +min_print_speed = 211 +#"material_print_temperature": {"default_value": 210,"value": "200 if speed_infill <=150 else 205 if speed_infill <= 200 else 215 if speed_infill <= 260 else 220","maximum_value": "250" }, + +[filament:Generic PLA @Geeetech] +inherits = *PLA* +filament_vendor = Generic +filament_cost = 25.4 +filament_density = 1.24 +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_Geeetech.*/ and printer_model=~/(Thunder|ThunderPro|Mizar|A10|A20|A30).*/ + +[filament:Generic PETG @Geeetech] +inherits = *PETG* +filament_vendor = Generic +filament_cost = 27.82 +filament_density = 1.27 + +[filament:Generic ABS @Geeetech] +inherits = *ABS* +filament_vendor = Generic +filament_cost = 27.82 +filament_density = 1.04 + +[filament:Generic TPU @Geeetech] +inherits = *TPU* +filament_vendor = Geeetech + +[filament:Geeetech PLA @Geeetech] +inherits = *PLA* +filament_vendor = Geeetech +temperature = 200 +bed_temperature = 60 +first_layer_temperature = 205 +first_layer_bed_temperature = 60 +filament_colour = #42BDD8 + +[filament:Geeetech PETG @Geeetech] +inherits = *PETG* +filament_vendor = Geeetech +temperature = 240 +bed_temperature = 70 +first_layer_temperature = 240 +first_layer_bed_temperature = 70 +max_fan_speed = 40 +min_fan_speed = 20 +filament_colour = #42BDD8 + +[filament:Geeetech ABS @Geeetech] +inherits = *ABS* +filament_vendor = Geeetech +temperature = 240 +bed_temperature = 100 +first_layer_temperature = 240 +first_layer_bed_temperature = 100 +filament_colour = #42BDD8 + +[filament:Thunder HS-PLA @Geeetech] +inherits = *HS-PLA* +filament_vendor = Geeetech +filament_colour = #F5DC1E +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ +compatible_prints_condition = infill_speed >= 150 +filament_notes = "HS-PLA is Geeetech's latest high-speed printing filament. By adjusting the melting point, melting index, glass transition temperature of raw materials and optimizing the production process, Geeetech enables HS-PLA to have stronger fluidity, smoother discharge, faster curing and forming speed and is not easy to deform under the melting condition. Compared with ordinary PLA, HS-pla has the advantages of faster printing speed, higher printing quality and more delicate model surface, which can better meet the high performance requirements of high-speed 3D printers for filament.\n\nhttps://www.geeetech.com/wiki/index.php/Geeetech_Thunder_3D_printer#HS-PLA_Series_Filament_.22Speed-Temperature.22_Parameter_Settings_for_Reference" + +[filament:Thunder PLA @Geeetech] +inherits = *HS-PLA* +filament_vendor = Geeetech +filament_colour = #C8CF0A +compatible_printers_condition = printer_model=~/(Thunder|ThunderPro).*/ +compatible_prints_condition = infill_speed >= 150 +filament_notes = "common PLA filament setting for high-speed printing" + +######################################### +####### end ###filament presets ######## +######################################### + + + + + +######################################### +########## begin ###printer presets ##### +######################################### +[printer:*common*] +# Presets for common printers +printer_technology = FFF +before_layer_gcode = \nG92 E0\n +between_objects_gcode = +pause_print_gcode = +deretract_speed = 40 +extruder_offset = 0x0 +gcode_flavor = marlin +silent_mode = 0 +remaining_times = 0 +machine_max_feedrate_x = 500 +machine_max_feedrate_y = 500 +machine_max_feedrate_z = 5 +machine_max_feedrate_e = 25 +machine_max_acceleration_x = 500 +machine_max_acceleration_y = 500 +machine_max_acceleration_z = 100 +machine_max_acceleration_e = 1000 +machine_max_acceleration_extruding = 500 +machine_max_acceleration_retracting = 1000 +machine_max_jerk_x = 10 +machine_max_jerk_y = 10 +machine_max_jerk_z = 0.3 +machine_max_jerk_e = 5 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 0 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩AFTER_LAYER_CHANGE# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +max_print_height = 260 +printer_notes = +printer_settings_id = +retract_before_travel = 2 +retract_before_wipe = 70% +retract_layer_change = 1 +retract_length_toolchange = 1 +retract_lift = 0 +retract_lift_above = 0 +retract_lift_below = 0 +retract_restart_extra = 0 +retract_restart_extra_toolchange = 0 +retract_speed = 45 +single_extruder_multi_material = 0 +toolchange_gcode = +use_firmware_retraction = 0 +use_relative_e_distances = 1 +use_volumetric_e = 0 +variable_layer_height = 1 +z_offset = 0 +printer_model = +default_filament_profile = Generic PLA @Geeetech +start_gcode = ;Custom Start G-code\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\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 ;Off Fan\nG1 Z5.0 F3000 ;Move Z Axis up little to prevent scratching of Heat Bed\nG1 X0.1 Y20 Z0.8 F5000 ; Move to start position\nG1 X0.1 Y200.0 Z1.2 F1500 E30 ; Draw the first line\nG92 E0 ; Reset Extruder\nG1 X0.4 Y200.0 Z1.2 F3000 ; Move to side a little\nG1 X0.4 Y20 Z1.2 F1500 E25 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 Z2.0 F3000 ; Move Z Axis up little to prevent scratching of Heat Bed\nG1 X5 Y20 Z0.4 F3000.0 ; Move over to prevent blob squish\n\nM221 S{if layer_height<0.2}110{else}100{endif}\nG92 E0 +end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600 ; Move print head up{endif}\nG1 X5 Y{print_bed_max[1]*0.8} F{travel_speed*60} ; present print\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+min(max_layer_z+70, max_print_height-10)} F600 ; Move print head further up{endif}\n{if max_layer_z < max_print_height*0.6}G1 Z{max_print_height*0.6} F600 ; Move print head further up{endif}\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors + +[printer:*HighSpeedPrinter*] +# Presets for high-speed printers +inherits = *common* +machine_max_feedrate_x = 300 +machine_max_feedrate_y = 500 +machine_max_feedrate_z = 10 +machine_max_feedrate_e = 60 +machine_max_acceleration_x = 5000 +machine_max_acceleration_y = 4000 +machine_max_acceleration_z = 50 +machine_max_acceleration_e = 3500 +machine_max_acceleration_extruding = 3500 +machine_max_acceleration_retracting = 3500 +machine_max_jerk_x = 45 +machine_max_jerk_y = 45 +machine_max_jerk_z = 0.8 +machine_max_jerk_e = 8 +machine_min_extruding_rate = 0 +machine_min_travel_rate = 5 +extruder_colour = #F5DC1E +default_filament_profile = Thunder HS-PLA @Geeetech; Thunder PLA @Geeetech +start_gcode = ;Custom Start G-code for High-speed Printer\n\nM104 S[first_layer_temperature] ; Set Hotend 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 Hotend Temp.\nG92 E0 ; Reset Extruder\nG28 ; Home all axes\nM107 P0 ;Off Main Fan\nM107 P1 ;Off Aux Fan\nM2012 P8 S1 F100 ; ON Light\n;M106 P0 S383 ; ON MainFan 150% if need\n;M106 P1 S255 ; ON Aux Fan 100% if need\nG1 Z5.0 F3000 ;Move the Z-axis slightly up to prevent scratching the heatbed\nG1 X0.1 Y20 Z0.8 F5000 ; Move to start position\nG1 X0.1 Y200.0 Z1.2 F1500 E30 ; Draw the first line\nG92 E0 ; Reset Extruder\nG1 X0.4 Y200.0 Z1.2 F3000 ; Move to side a little\nG1 X0.4 Y20 Z1.2 F1500 E25 ; Draw the second line\nG92 E0 ; Reset Extruder\nG1 Z2.0 F3000 ; Move the Z-axis slightly up to prevent scratching the heatbed\nG1 X5 Y20 Z0.4 F3000.0 ; Scrape off nozzle residue\n\nM221 S{if layer_height<0.2}110{else}100{endif}\nG92 E0 +printer_notes = Do not 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_Geeetech\nPRINTER_MODEL_Thunder series + +[printer:*DualExtruderPrinter*] +# Presets for Dual-Extruder printers +inherits = *common* +deretract_speed = 30,30 +extruder_offset = 0x0,0x0 +max_layer_height = 0.3,0.3 +min_layer_height = 0.05,0.05 +printer_notes = Do not 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_Geeetech\nPRINTER_MODEL_MizarM&A10M&A20M&A30M +retract_before_travel = 3,3 +retract_before_wipe = 15%,15% +retract_layer_change = 0,0 +retract_length = 6,6 +retract_length_toolchange = 0,0 +retract_lift = 0,0 +retract_restart_extra = 0,0 +retract_restart_extra_toolchange = 0,0 +retract_speed = 35,35 +use_relative_e_distances = 1 +wipe = 0,0 +z_offset = 0 +default_print_profile = 0.20 mm NORMAL @Multi-extruder +default_filament_profile = Generic PLA @Geeetech + +[printer:*MultiExtruderPrinter*] +# Presets for Multi-Extruder printers +inherits = *common* +deretract_speed = 30,30,30 +extruder_offset = 0x0,0x0,0x0 +max_layer_height = 0.3,0.3 +min_layer_height = 0.05,0.05 +printer_notes = Do not 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_Geeetech\nPRINTER_MODEL_MizarT&A10T&A20T&A30T +retract_before_travel = 3,3,3 +retract_before_wipe = 15%,15%,15% +retract_layer_change = 0,0,0 +retract_length = 6,6,6 +retract_length_toolchange = 0,0,0 +retract_lift = 0,0,0 +retract_restart_extra = 0,0,0 +retract_restart_extra_toolchange = 0,0,0 +retract_speed = 35,35,35 +use_relative_e_distances = 1 +wipe = 0,0,0 +z_offset = 0 +default_print_profile = 0.20 mm NORMAL @Multi-extruder +default_filament_profile = Generic PLA @Geeetech + +# Intended for printers where the Z-axis lowers the print bed during printing, like the GTC10 series +#[printer:*descendingz*] +#end_gcode = {if max_layer_z < max_print_height}G1 Z{z_offset+min(max_layer_z+2, max_print_height)} F600{endif} ; Move print bed down\nG1 X50 Y50 F{travel_speed*60} ; move print head out of the way\n{if max_layer_z < max_print_height-10}G1 Z{z_offset+max_print_height-10} F600{endif} ; Move print bed close to the bottom\nM140 S0 ; turn off heatbed\nM104 S0 ; turn off temperature\nM107 ; turn off fan\nM84 X Y E ; disable motors + +[printer:*PausePrint*] +# Intended for printers with vendor official firmware verified to support M25 +pause_print_gcode = M25 ; pause print + +# Presets retract length +[printer:*Retract_1mm*] +retract_length = 1 +[printer:*Retract_2mm*] +retract_length = 2 +[printer:*Retract_3mm*] +retract_length = 3 +[printer:*Retract_4mm*] +retract_length = 4 +[printer:*Retract_5mm*] +retract_length = 5 +[printer:*Retract_6mm*] +retract_length = 6 + +[printer:*Retract_6.5mm*] +retract_length = 6.5 + +[printer:*Retract_7mm*] +retract_length = 7 + +[printer:*Retract_8mm*] +retract_length = 8 + +[printer:*0.2nozzle*] +nozzle_diameter = 0.2 +printer_variant = 0.2 +min_layer_height = 0.08 +max_layer_height = 0.16 +retract_lift_above = 0.2 + +[printer:*0.3nozzle*] +nozzle_diameter = 0.3 +printer_variant = 0.3 +min_layer_height = 0.08 +max_layer_height = 0.24 +retract_lift_above = 0.2 + +[printer:*0.4nozzle*] +nozzle_diameter = 0.4 +printer_variant = 0.4 +min_layer_height = 0.08 +max_layer_height = 0.32 +retract_lift_above = 0.2 + +[printer:*0.5nozzle*] +nozzle_diameter = 0.5 +printer_variant = 0.5 +min_layer_height = 0.08 +max_layer_height = 0.40 +retract_lift_above = 0.2 + +[printer:*0.6nozzle*] +nozzle_diameter = 0.6 +printer_variant = 0.6 +min_layer_height = 0.08 +max_layer_height = 0.48 +retract_lift_above = 0.3 + +[printer:*0.8nozzle*] +nozzle_diameter = 0.8 +printer_variant = 0.8 +min_layer_height = 0.08 +max_layer_height = 0.48 +retract_lift_above = 0.3 + +######################################### +###############Printer inherits########## +######################################### + +[printer:*Thunder*] +inherits = *common*; *HighSpeedPrinter*; *Retract_6.5mm*; *PausePrint* +printer_model = Thunder +bed_shape = 0x0,250x0,250x250,0x250 +max_print_height = 260 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【Thunder】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_Thunder\nPRINTER_HAS_BOWDEN + +[printer:*ThunderPro*] +inherits = *common*; *HighSpeedPrinter*; *Retract_6.5mm*; *PausePrint* +printer_model = ThunderPro +bed_shape = 0x0,250x0,250x250,0x250 +max_print_height = 260 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【ThunderPro】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_ThunderPro\nPRINTER_HAS_DirectDriveExtruder + +[printer:*MizarS*] +inherits = *common*; *Retract_6.5mm*; *PausePrint* +printer_model = MizarS +bed_shape = 0x0,255x0,255x255,0x255 +max_print_height = 260 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【MizarS】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_MizarS\nPRINTER_HAS_BOWDEN + +[printer:*MizarPro*] +inherits = *common*; *Retract_6.5mm*; *PausePrint* +printer_model = MizarPro +bed_shape = 0x0,220x0,220x220,0x220 +max_print_height = 260 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【Mizar Pro】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_MizarPro\nPRINTER_HAS_BOWDEN + +[printer:*Mizar*] +inherits = *common*; *Retract_6.5mm*; *PausePrint* +printer_model = Mizar +bed_shape = 0x0,220x0,220x220,0x220 +max_print_height = 260 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【Mizar】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_Mizar\nPRINTER_HAS_BOWDEN + +[printer:*MizarMax*] +inherits = *common*; *Retract_6.5mm*; *PausePrint* +printer_model = MizarMax +bed_shape = 0x0,320x0,320x320,0x320 +max_print_height = 400 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【MizarMax】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_MizarMax\nPRINTER_HAS_BOWDEN + +[printer:*A10Pro*] +inherits = *common*; *Retract_6.5mm*; *PausePrint* +printer_model = A10Pro +bed_shape = 0x0,220x0,220x220,0x220 +max_print_height = 260 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【A10 Pro】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_A10Pro\nPRINTER_HAS_BOWDEN + +[printer:*A20*] +inherits = *common*; *Retract_6.5mm*; *PausePrint* +printer_model = A20 +bed_shape = 0x0,250x0,250x250,0x250 +max_print_height = 250 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【A20】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_A20\nPRINTER_HAS_BOWDEN + +[printer:*A30Pro*] +inherits = *common*; *Retract_6.5mm*; *PausePrint* +printer_model = A30Pro +bed_shape = 0x0,320x0,320x320,0x320 +max_print_height = 420 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【A30Pro】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_A30Pro\nPRINTER_HAS_BOWDEN + +[printer:*E180*] +inherits = *common*; *Retract_6mm*; *PausePrint* +printer_model = E180 +bed_shape = 0x0,125x0,125x130,0x130 +max_print_height = 126 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【E180】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_E180\nPRINTER_HAS_BOWDEN + +[printer:*MeDucer*] +inherits = *common*; *Retract_2mm*; *PausePrint* +printer_model = MeDucer +bed_shape = 0x0,180x0,180x150,0x150 +max_print_height = 150 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【MeDucer】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_MeDucer\nPRINTER_HAS_DirectDriveExtruder + +[printer:*MeCreator*] +inherits = *common*; *Retract_2mm*; *PausePrint* +printer_model = MeCreator +bed_shape = 0x0,150x0,150x150,0x150 +max_print_height = 125 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【MeCreator】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_MeCreator\nPRINTER_HAS_DirectDriveExtruder + +[printer:*MeCreator2*] +inherits = *common*; *Retract_2mm*; *PausePrint* +printer_model = MeCreator2 +bed_shape = 0x0,160x0,160x160,0x160 +max_print_height = 160 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【MeCreator2】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_MeCreator2\nPRINTER_HAS_DirectDriveExtruder + +[printer:*GiantArmD200*] +inherits = *common*; *Retract_2mm*; *PausePrint* +printer_model = GiantArmD200 +bed_shape = 0x0,300x0,300x180,0x180 +max_print_height = 180 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【GiantArmD200】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_GiantArmD200\nPRINTER_HAS_DirectDriveExtruder + +[printer:*I3ProB*] +inherits = *common*; *Retract_2mm*; *PausePrint* +printer_model = I3ProB +bed_shape = 0x0,200x0,200x200,0x200 +max_print_height = 180 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【I3ProB】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_I3ProB\nPRINTER_HAS_DirectDriveExtruder + +[printer:*I3ProW*] +inherits = *common*; *Retract_2mm*; *PausePrint* +printer_model = I3ProW +bed_shape = 0x0,200x0,200x200,0x200 +max_print_height = 180 +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【I3ProW】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_I3ProW\nPRINTER_HAS_DirectDriveExtruder + + + +[printer:Geeetech Thunder (0.2 mm nozzle)] +inherits = *Thunder*; *0.2nozzle* +default_print_profile = 0.10 mm HIGHDETAIL (0.2mm nozzle) @High-speed +default_filament_profile =Thunder HS-PLA @Geeetech +[printer:Geeetech Thunder] +inherits = *Thunder*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @High-speed +default_filament_profile =Thunder HS-PLA @Geeetech +[printer:Geeetech Thunder (0.6 mm nozzle)] +inherits = *Thunder*; *0.6nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.6mm nozzle) @High-speed +default_filament_profile =Thunder HS-PLA @Geeetech +[printer:Geeetech Thunder (0.8 mm nozzle)] +inherits = *Thunder*; *0.8nozzle* +default_print_profile = 0.36 mm CHUNKY (0.8mm nozzle) @High-speed +default_filament_profile =Thunder HS-PLA @Geeetech + +[printer:Geeetech ThunderPro (0.2 mm nozzle)] +inherits = *ThunderPro*; *0.2nozzle* +default_print_profile = 0.10 mm HIGHDETAIL (0.2mm nozzle) @High-speed +default_filament_profile =Thunder HS-PLA @Geeetech +[printer:Geeetech ThunderPro] +inherits = *ThunderPro*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @High-speed +default_filament_profile =Thunder HS-PLA @Geeetech +[printer:Geeetech ThunderPro (0.6 mm nozzle)] +inherits = *ThunderPro*; *0.6nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.6mm nozzle) @High-speed +default_filament_profile =Thunder HS-PLA @Geeetech +[printer:Geeetech ThunderPro (0.8 mm nozzle)] +inherits = *ThunderPro*; *0.8nozzle* +default_print_profile = 0.36 mm CHUNKY (0.8mm nozzle) @High-speed +default_filament_profile =Thunder HS-PLA @Geeetech + +[printer:Geeetech MizarS (0.2 mm nozzle)] +inherits = *MizarS*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarS (0.3 mm nozzle)] +inherits = *MizarS*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarS] +inherits = *MizarS*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarS (0.5 mm nozzle)] +inherits = *MizarS*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarS (0.6 mm nozzle)] +inherits = *MizarS*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarS (0.8 mm nozzle)] +inherits = *MizarS*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech MizarPro (0.2 mm nozzle)] +inherits = *MizarPro*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarPro (0.3 mm nozzle)] +inherits = *MizarPro*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarPro] +inherits = *MizarPro*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarPro (0.5 mm nozzle)] +inherits = *MizarPro*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarPro (0.6 mm nozzle)] +inherits = *MizarPro*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarPro (0.8 mm nozzle)] +inherits = *MizarPro*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech Mizar (0.2 mm nozzle)] +inherits = *Mizar*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech Mizar (0.3 mm nozzle)] +inherits = *Mizar*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech Mizar] +inherits = *Mizar*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech Mizar (0.5 mm nozzle)] +inherits = *Mizar*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech Mizar (0.6 mm nozzle)] +inherits = *Mizar*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech Mizar (0.8 mm nozzle)] +inherits = *Mizar*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech MizarMax (0.2 mm nozzle)] +inherits = *MizarMax*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarMax (0.3 mm nozzle)] +inherits = *MizarMax*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarMax] +inherits = *MizarMax*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarMax (0.5 mm nozzle)] +inherits = *MizarMax*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarMax (0.6 mm nozzle)] +inherits = *MizarMax*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MizarMax (0.8 mm nozzle)] +inherits = *MizarMax*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech MizarM] +inherits = *common*; *DualExtruderPrinter*; *0.4nozzle*; *Retract_6mm*; *PausePrint* +printer_model = MizarM +bed_shape = 0x0,255x0,255x255,0x255 +max_print_height = 260 +nozzle_diameter = 0.4,0.4 +extruder_colour = #FF8000;#DB5182 +default_print_profile = 0.20 mm NORMAL @Multi-extruder +default_filament_profile = Generic PLA @Geeetech +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【MizarM】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_MizarM\nPRINTER_HAS_BOWDEN + +## [printer:Geeetech MizarT] +## inherits = *common*; *MultiExtruderPrinter*; *0.4nozzle*; *Retract_6mm*; *PausePrint* +## printer_model = MizarT +## bed_shape = 0x0,255x0,255x255,0x255 +## max_print_height = 260 +## nozzle_diameter = 0.4,0.4,0.4 +## extruder_colour = #FF0000;#00FF00;#0000FF +## default_print_profile = 0.20 mm NORMAL @Multi-extruder +## default_filament_profile = Generic PLA @Geeetech +## layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【MizarT】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +## 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_Geeetech\nPRINTER_MODEL_MizarT\nPRINTER_HAS_BOWDEN + +[printer:Geeetech A10Pro (0.2 mm nozzle)] +inherits = *A10Pro*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A10Pro (0.3 mm nozzle)] +inherits = *A10Pro*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A10Pro] +inherits = *A10Pro*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A10Pro (0.5 mm nozzle)] +inherits = *A10Pro*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A10Pro (0.6 mm nozzle)] +inherits = *A10Pro*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A10Pro (0.8 mm nozzle)] +inherits = *A10Pro*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech A10M] +inherits = *common*; *DualExtruderPrinter*; *0.4nozzle*; *Retract_6mm*; *PausePrint* +printer_model = A10M +bed_shape = 0x0,220x0,220x220,0x220 +max_print_height = 260 +nozzle_diameter = 0.4,0.4 +extruder_colour = #FF8000;#DB5182 +default_print_profile = 0.20 mm NORMAL @Multi-extruder +default_filament_profile = Generic PLA @Geeetech +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【A10M】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_A10M\nPRINTER_HAS_BOWDEN + +[printer:Geeetech A10T] +inherits = *common*; *MultiExtruderPrinter*; *0.4nozzle*; *Retract_6mm*; *PausePrint* +printer_model = A10T +bed_shape = 0x0,220x0,220x220,0x220 +max_print_height = 260 +nozzle_diameter = 0.4,0.4,0.4 +extruder_colour = #FF0000;#00FF00;#0000FF +default_print_profile = 0.20 mm NORMAL @Multi-extruder +default_filament_profile = Generic PLA @Geeetech +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【A10T】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_A10T\nPRINTER_HAS_BOWDEN + +[printer:Geeetech A20 (0.2 mm nozzle)] +inherits = *A20*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A20 (0.3 mm nozzle)] +inherits = *A20*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A20] +inherits = *A20*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A20 (0.5 mm nozzle)] +inherits = *A20*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A20 (0.6 mm nozzle)] +inherits = *A20*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A20 (0.8 mm nozzle)] +inherits = *A20*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech A20M] +inherits = *common*; *DualExtruderPrinter*; *0.4nozzle*; *Retract_6mm*; *PausePrint* +printer_model = A20M +bed_shape = 0x0,250x0,250x250,0x250 +max_print_height = 250 +nozzle_diameter = 0.4,0.4 +extruder_colour = #FF8000;#DB5182 +default_print_profile = 0.20 mm NORMAL @Multi-extruder +default_filament_profile = Generic PLA @Geeetech +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【A20M】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_A20M\nPRINTER_HAS_BOWDEN + +[printer:Geeetech A20T] +inherits = *common*; *MultiExtruderPrinter*; *0.4nozzle*; *Retract_6mm*; *PausePrint* +printer_model = A20T +bed_shape = 0x0,250x0,250x250,0x250 +max_print_height = 250 +nozzle_diameter = 0.4,0.4,0.4 +extruder_colour = #FF0000;#00FF00;#0000FF +default_print_profile = 0.20 mm NORMAL @Multi-extruder +default_filament_profile = Generic PLA @Geeetech +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【A20T】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_A20T\nPRINTER_HAS_BOWDEN + +[printer:Geeetech A30Pro (0.2 mm nozzle)] +inherits = *A30Pro*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A30Pro (0.3 mm nozzle)] +inherits = *A30Pro*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A30Pro] +inherits = *A30Pro*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A30Pro (0.5 mm nozzle)] +inherits = *A30Pro*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A30Pro (0.6 mm nozzle)] +inherits = *A30Pro*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech A30Pro (0.8 mm nozzle)] +inherits = *A30Pro*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech A30M] +inherits = *common*; *DualExtruderPrinter*; *0.4nozzle*; *Retract_6mm*; *PausePrint* +printer_model = A30M +bed_shape = 0x0,320x0,320x320,0x320 +max_print_height = 420 +nozzle_diameter = 0.4,0.4 +extruder_colour = #FF8000;#DB5182 +default_print_profile = 0.20 mm NORMAL @Multi-extruder +default_filament_profile = Generic PLA @Geeetech +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【A30M】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_A30M\nPRINTER_HAS_BOWDEN + +[printer:Geeetech A30T] +inherits = *common*; *MultiExtruderPrinter*; *0.4nozzle*; *Retract_6mm*; *PausePrint* +printer_model = A30T +bed_shape = 0x0,320x0,320x320,0x320 +max_print_height = 420 +nozzle_diameter = 0.4,0.4,0.4 +extruder_colour = #FF0000;#00FF00;#0000FF +default_print_profile = 0.20 mm NORMAL @Multi-extruder +default_filament_profile = Generic PLA @Geeetech +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【A30T】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_A30T\nPRINTER_HAS_BOWDEN + +[printer:Geeetech E180 (0.2 mm nozzle)] +inherits = *E180*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech E180 (0.3 mm nozzle)] +inherits = *E180*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech E180] +inherits = *E180*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech E180 (0.5 mm nozzle)] +inherits = *E180*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech E180 (0.6 mm nozzle)] +inherits = *E180*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech E180 (0.8 mm nozzle)] +inherits = *E180*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech MeDucer (0.2 mm nozzle)] +inherits = *MeDucer*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeDucer (0.3 mm nozzle)] +inherits = *MeDucer*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeDucer] +inherits = *MeDucer*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeDucer (0.5 mm nozzle)] +inherits = *MeDucer*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeDucer (0.6 mm nozzle)] +inherits = *MeDucer*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeDucer (0.8 mm nozzle)] +inherits = *MeDucer*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech MeCreator (0.2 mm nozzle)] +inherits = *MeCreator*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeCreator (0.3 mm nozzle)] +inherits = *MeCreator*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeCreator] +inherits = *MeCreator*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeCreator (0.5 mm nozzle)] +inherits = *MeCreator*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeCreator (0.6 mm nozzle)] +inherits = *MeCreator*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeCreator (0.8 mm nozzle)] +inherits = *MeCreator*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech MeCreator2 (0.2 mm nozzle)] +inherits = *MeCreator2*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeCreator2 (0.3 mm nozzle)] +inherits = *MeCreator2*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeCreator2] +inherits = *MeCreator2*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeCreator2 (0.5 mm nozzle)] +inherits = *MeCreator2*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeCreator2 (0.6 mm nozzle)] +inherits = *MeCreator2*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech MeCreator2 (0.8 mm nozzle)] +inherits = *MeCreator2*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech GiantArmD200 (0.2 mm nozzle)] +inherits = *GiantArmD200*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech GiantArmD200 (0.3 mm nozzle)] +inherits = *GiantArmD200*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech GiantArmD200] +inherits = *GiantArmD200*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech GiantArmD200 (0.5 mm nozzle)] +inherits = *GiantArmD200*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech GiantArmD200 (0.6 mm nozzle)] +inherits = *GiantArmD200*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech GiantArmD200 (0.8 mm nozzle)] +inherits = *GiantArmD200*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech I3ProB (0.2 mm nozzle)] +inherits = *I3ProB*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech I3ProB (0.3 mm nozzle)] +inherits = *I3ProB*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech I3ProB] +inherits = *I3ProB*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech I3ProB (0.5 mm nozzle)] +inherits = *I3ProB*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech I3ProB (0.6 mm nozzle)] +inherits = *I3ProB*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech I3ProB (0.8 mm nozzle)] +inherits = *I3ProB*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech I3ProW (0.2 mm nozzle)] +inherits = *I3ProW*; *0.2nozzle* +default_print_profile = 0.08 mm SUPERDETAIL (0.2mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech I3ProW (0.3 mm nozzle)] +inherits = *I3ProW*; *0.3nozzle* +default_print_profile = 0.12 mm DETAIL (0.3mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech I3ProW] +inherits = *I3ProW*; *0.4nozzle* +default_print_profile = 0.20 mm NORMAL @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech I3ProW (0.5 mm nozzle)] +inherits = *I3ProW*; *0.5nozzle* +default_print_profile = 0.28 mm SUPERDRAFT (0.5mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech I3ProW (0.6 mm nozzle)] +inherits = *I3ProW*; *0.6nozzle* +default_print_profile = 0.36 mm CHUNKY (0.6mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech +[printer:Geeetech I3ProW (0.8 mm nozzle)] +inherits = *I3ProW*; *0.8nozzle* +default_print_profile = 0.44 mm SUPERCHUNKY (0.8mm nozzle) @Geeetech +default_filament_profile = Generic PLA @Geeetech + +[printer:Geeetech I3ProC] +inherits = *common*; *DualExtruderPrinter*; *0.4nozzle*; *Retract_1mm*; *PausePrint* +printer_model = I3ProC +bed_shape = 0x0,200x0,200x200,0x200 +max_print_height = 180 +nozzle_diameter = 0.4,0.4 +extruder_colour = #FF8000;#DB5182 +default_print_profile = 0.20 mm NORMAL @Multi-extruder +default_filament_profile = Generic PLA @Geeetech +layer_gcode = ;▩▩▩▩▩▩▩▩▩▩【I3ProC】# layer No:[layer_num] ———>Print Height:[layer_z] mm ▩▩▩▩▩▩▩▩▩▩ +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_Geeetech\nPRINTER_MODEL_I3ProC\nPRINTER_HAS_DirectDriveExtruder +######################################### +########## End ###printer presets ##### +######################################### \ No newline at end of file diff --git a/resources/profiles/Geeetech/125X130.stl b/resources/profiles/Geeetech/125X130.stl new file mode 100644 index 0000000000..968daa2ef7 Binary files /dev/null and b/resources/profiles/Geeetech/125X130.stl differ diff --git a/resources/profiles/Geeetech/125x130.svg b/resources/profiles/Geeetech/125x130.svg new file mode 100644 index 0000000000..53d866593a --- /dev/null +++ b/resources/profiles/Geeetech/125x130.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/profiles/Geeetech/150x150.stl b/resources/profiles/Geeetech/150x150.stl new file mode 100644 index 0000000000..41f7363250 Binary files /dev/null and b/resources/profiles/Geeetech/150x150.stl differ diff --git a/resources/profiles/Geeetech/150x150.svg b/resources/profiles/Geeetech/150x150.svg new file mode 100644 index 0000000000..ca38110040 --- /dev/null +++ b/resources/profiles/Geeetech/150x150.svg @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/profiles/Geeetech/160x160.stl b/resources/profiles/Geeetech/160x160.stl new file mode 100644 index 0000000000..615b54f4a7 Binary files /dev/null and b/resources/profiles/Geeetech/160x160.stl differ diff --git a/resources/profiles/Geeetech/160x160.svg b/resources/profiles/Geeetech/160x160.svg new file mode 100644 index 0000000000..34f83e4fae --- /dev/null +++ b/resources/profiles/Geeetech/160x160.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/profiles/Geeetech/180X150.stl b/resources/profiles/Geeetech/180X150.stl new file mode 100644 index 0000000000..740e7a5db7 Binary files /dev/null and b/resources/profiles/Geeetech/180X150.stl differ diff --git a/resources/profiles/Geeetech/180x150.svg b/resources/profiles/Geeetech/180x150.svg new file mode 100644 index 0000000000..d21c613891 --- /dev/null +++ b/resources/profiles/Geeetech/180x150.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/profiles/Geeetech/200x200.stl b/resources/profiles/Geeetech/200x200.stl new file mode 100644 index 0000000000..c5dcfe68fb Binary files /dev/null and b/resources/profiles/Geeetech/200x200.stl differ diff --git a/resources/profiles/Geeetech/200x200.svg b/resources/profiles/Geeetech/200x200.svg new file mode 100644 index 0000000000..44c5a5415f --- /dev/null +++ b/resources/profiles/Geeetech/200x200.svg @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/profiles/Geeetech/220x220.stl b/resources/profiles/Geeetech/220x220.stl new file mode 100644 index 0000000000..6519746e8a Binary files /dev/null and b/resources/profiles/Geeetech/220x220.stl differ diff --git a/resources/profiles/Geeetech/220x220.svg b/resources/profiles/Geeetech/220x220.svg new file mode 100644 index 0000000000..20b4b8a0ca --- /dev/null +++ b/resources/profiles/Geeetech/220x220.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/profiles/Geeetech/250x250.stl b/resources/profiles/Geeetech/250x250.stl new file mode 100644 index 0000000000..b95a5e66e1 Binary files /dev/null and b/resources/profiles/Geeetech/250x250.stl differ diff --git a/resources/profiles/Geeetech/250x250.svg b/resources/profiles/Geeetech/250x250.svg new file mode 100644 index 0000000000..c981427130 --- /dev/null +++ b/resources/profiles/Geeetech/250x250.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/profiles/Geeetech/255x255.stl b/resources/profiles/Geeetech/255x255.stl new file mode 100644 index 0000000000..a60b4a405a Binary files /dev/null and b/resources/profiles/Geeetech/255x255.stl differ diff --git a/resources/profiles/Geeetech/255x255.svg b/resources/profiles/Geeetech/255x255.svg new file mode 100644 index 0000000000..ff0373ac61 --- /dev/null +++ b/resources/profiles/Geeetech/255x255.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/profiles/Geeetech/300x180.stl b/resources/profiles/Geeetech/300x180.stl new file mode 100644 index 0000000000..ee1d486747 Binary files /dev/null and b/resources/profiles/Geeetech/300x180.stl differ diff --git a/resources/profiles/Geeetech/300x180.svg b/resources/profiles/Geeetech/300x180.svg new file mode 100644 index 0000000000..4cba3065e9 --- /dev/null +++ b/resources/profiles/Geeetech/300x180.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/profiles/Geeetech/320x320.stl b/resources/profiles/Geeetech/320x320.stl new file mode 100644 index 0000000000..086d5064a6 Binary files /dev/null and b/resources/profiles/Geeetech/320x320.stl differ diff --git a/resources/profiles/Geeetech/320x320.svg b/resources/profiles/Geeetech/320x320.svg new file mode 100644 index 0000000000..202c7c0542 --- /dev/null +++ b/resources/profiles/Geeetech/320x320.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/profiles/Geeetech/A10M_thumbnail.png b/resources/profiles/Geeetech/A10M_thumbnail.png new file mode 100644 index 0000000000..e487b34126 Binary files /dev/null and b/resources/profiles/Geeetech/A10M_thumbnail.png differ diff --git a/resources/profiles/Geeetech/A10Pro_thumbnail.png b/resources/profiles/Geeetech/A10Pro_thumbnail.png new file mode 100644 index 0000000000..530ac131cc Binary files /dev/null and b/resources/profiles/Geeetech/A10Pro_thumbnail.png differ diff --git a/resources/profiles/Geeetech/A10T_thumbnail.png b/resources/profiles/Geeetech/A10T_thumbnail.png new file mode 100644 index 0000000000..ba7d32702f Binary files /dev/null and b/resources/profiles/Geeetech/A10T_thumbnail.png differ diff --git a/resources/profiles/Geeetech/A20M_thumbnail.png b/resources/profiles/Geeetech/A20M_thumbnail.png new file mode 100644 index 0000000000..ab48da911f Binary files /dev/null and b/resources/profiles/Geeetech/A20M_thumbnail.png differ diff --git a/resources/profiles/Geeetech/A20T_thumbnail.png b/resources/profiles/Geeetech/A20T_thumbnail.png new file mode 100644 index 0000000000..a184f30777 Binary files /dev/null and b/resources/profiles/Geeetech/A20T_thumbnail.png differ diff --git a/resources/profiles/Geeetech/A20_thumbnail.png b/resources/profiles/Geeetech/A20_thumbnail.png new file mode 100644 index 0000000000..bf8681167d Binary files /dev/null and b/resources/profiles/Geeetech/A20_thumbnail.png differ diff --git a/resources/profiles/Geeetech/A30M_thumbnail.png b/resources/profiles/Geeetech/A30M_thumbnail.png new file mode 100644 index 0000000000..5d907fbc74 Binary files /dev/null and b/resources/profiles/Geeetech/A30M_thumbnail.png differ diff --git a/resources/profiles/Geeetech/A30Pro_thumbnail.png b/resources/profiles/Geeetech/A30Pro_thumbnail.png new file mode 100644 index 0000000000..bbb41b80cc Binary files /dev/null and b/resources/profiles/Geeetech/A30Pro_thumbnail.png differ diff --git a/resources/profiles/Geeetech/A30T_thumbnail.png b/resources/profiles/Geeetech/A30T_thumbnail.png new file mode 100644 index 0000000000..1fd33db1bb Binary files /dev/null and b/resources/profiles/Geeetech/A30T_thumbnail.png differ diff --git a/resources/profiles/Geeetech/E180_thumbnail.png b/resources/profiles/Geeetech/E180_thumbnail.png new file mode 100644 index 0000000000..4c3ffa4540 Binary files /dev/null and b/resources/profiles/Geeetech/E180_thumbnail.png differ diff --git a/resources/profiles/Geeetech/GiantArmD200_thumbnail.png b/resources/profiles/Geeetech/GiantArmD200_thumbnail.png new file mode 100644 index 0000000000..6f45bf004b Binary files /dev/null and b/resources/profiles/Geeetech/GiantArmD200_thumbnail.png differ diff --git a/resources/profiles/Geeetech/I3ProB_thumbnail.png b/resources/profiles/Geeetech/I3ProB_thumbnail.png new file mode 100644 index 0000000000..f4f86aaf42 Binary files /dev/null and b/resources/profiles/Geeetech/I3ProB_thumbnail.png differ diff --git a/resources/profiles/Geeetech/I3ProC_thumbnail.png b/resources/profiles/Geeetech/I3ProC_thumbnail.png new file mode 100644 index 0000000000..32ab8fcdca Binary files /dev/null and b/resources/profiles/Geeetech/I3ProC_thumbnail.png differ diff --git a/resources/profiles/Geeetech/I3ProW_thumbnail.png b/resources/profiles/Geeetech/I3ProW_thumbnail.png new file mode 100644 index 0000000000..585784f112 Binary files /dev/null and b/resources/profiles/Geeetech/I3ProW_thumbnail.png differ diff --git a/resources/profiles/Geeetech/MeCreator2_thumbnail.png b/resources/profiles/Geeetech/MeCreator2_thumbnail.png new file mode 100644 index 0000000000..d2566e4f08 Binary files /dev/null and b/resources/profiles/Geeetech/MeCreator2_thumbnail.png differ diff --git a/resources/profiles/Geeetech/MeCreator_thumbnail.png b/resources/profiles/Geeetech/MeCreator_thumbnail.png new file mode 100644 index 0000000000..aafb6ed5b7 Binary files /dev/null and b/resources/profiles/Geeetech/MeCreator_thumbnail.png differ diff --git a/resources/profiles/Geeetech/MeDucer_thumbnail.png b/resources/profiles/Geeetech/MeDucer_thumbnail.png new file mode 100644 index 0000000000..306ff12bee Binary files /dev/null and b/resources/profiles/Geeetech/MeDucer_thumbnail.png differ diff --git a/resources/profiles/Geeetech/MizarM_thumbnail.png b/resources/profiles/Geeetech/MizarM_thumbnail.png new file mode 100644 index 0000000000..b0bce4653e Binary files /dev/null and b/resources/profiles/Geeetech/MizarM_thumbnail.png differ diff --git a/resources/profiles/Geeetech/MizarMax_thumbnail.png b/resources/profiles/Geeetech/MizarMax_thumbnail.png new file mode 100644 index 0000000000..0b444bd83e Binary files /dev/null and b/resources/profiles/Geeetech/MizarMax_thumbnail.png differ diff --git a/resources/profiles/Geeetech/MizarPro_thumbnail.png b/resources/profiles/Geeetech/MizarPro_thumbnail.png new file mode 100644 index 0000000000..96099c88f4 Binary files /dev/null and b/resources/profiles/Geeetech/MizarPro_thumbnail.png differ diff --git a/resources/profiles/Geeetech/MizarS_thumbnail.png b/resources/profiles/Geeetech/MizarS_thumbnail.png new file mode 100644 index 0000000000..9c0d388857 Binary files /dev/null and b/resources/profiles/Geeetech/MizarS_thumbnail.png differ diff --git a/resources/profiles/Geeetech/Mizar_thumbnail.png b/resources/profiles/Geeetech/Mizar_thumbnail.png new file mode 100644 index 0000000000..46481ee07f Binary files /dev/null and b/resources/profiles/Geeetech/Mizar_thumbnail.png differ diff --git a/resources/profiles/Geeetech/ThunderPro_thumbnail.png b/resources/profiles/Geeetech/ThunderPro_thumbnail.png new file mode 100644 index 0000000000..e22ca209a2 Binary files /dev/null and b/resources/profiles/Geeetech/ThunderPro_thumbnail.png differ diff --git a/resources/profiles/Geeetech/Thunder_thumbnail.png b/resources/profiles/Geeetech/Thunder_thumbnail.png new file mode 100644 index 0000000000..73b5b9bbd4 Binary files /dev/null and b/resources/profiles/Geeetech/Thunder_thumbnail.png differ diff --git a/resources/profiles/RatRig.idx b/resources/profiles/RatRig.idx index f0c1174647..b8811aa5e8 100644 --- a/resources/profiles/RatRig.idx +++ b/resources/profiles/RatRig.idx @@ -1,3 +1,4 @@ min_slic3r_version = 2.4.1-alpha0 +1.0.2 Updated start g-code. 1.0.1 Various fixes and improvements. Commented filament sensor initialisation for v-Minion (optional HW). 1.0.0 Initial RatRig bundle \ No newline at end of file diff --git a/resources/profiles/RatRig.ini b/resources/profiles/RatRig.ini index 5558cf6989..56fab6e0df 100644 --- a/resources/profiles/RatRig.ini +++ b/resources/profiles/RatRig.ini @@ -9,7 +9,7 @@ name = RatRig # 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 = 1.0.1 +config_version = 1.0.2 # Where to get the updates from? config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/RatRig/ # The printer models will be shown by the Configuration Wizard in this order, @@ -433,7 +433,7 @@ retract_restart_extra_toolchange = 0 retract_speed = 40 silent_mode = 0 single_extruder_multi_material = 0 -start_gcode = M190 S0 ; Prevents prusaslicer from prepending m190 to the gcode interfering with the macro\nM109 S0 ; Prevents prusaslicer from prepending m109 to the gcode interfering with the macro\nSTART_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature]\n;enable this if you have a BTT Smart Filament Sensor\nSET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=0\n +start_gcode = M190 S0 ; Prevents prusaslicer from prepending m190 to the gcode interfering with the macro\nM109 S0 ; Prevents prusaslicer from prepending m109 to the gcode interfering with the macro\nSET_GCODE_VARIABLE MACRO=RatOS VARIABLE=relative_extrusion VALUE=True\nSTART_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature]\n;enable this if you have a BTT Smart Filament Sensor\nSET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=0\n thumbnails = 64x64,400x300 toolchange_gcode = use_firmware_retraction = 0 @@ -496,7 +496,7 @@ retract_restart_extra_toolchange = 0 retract_speed = 40 silent_mode = 0 single_extruder_multi_material = 0 -start_gcode = M190 S0 ; Prevents prusaslicer from prepending m190 to the gcode interfering with the macro\nM109 S0 ; Prevents prusaslicer from prepending m109 to the gcode interfering with the macro\nSTART_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature]\n;enable this if you have a BTT Smart Filament Sensor\n; SET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=0\n +start_gcode = M190 S0 ; Prevents prusaslicer from prepending m190 to the gcode interfering with the macro\nM109 S0 ; Prevents prusaslicer from prepending m109 to the gcode interfering with the macro\nSET_GCODE_VARIABLE MACRO=RatOS VARIABLE=relative_extrusion VALUE=True\nSTART_PRINT EXTRUDER_TEMP=[first_layer_temperature] BED_TEMP=[first_layer_bed_temperature]\n;enable this if you have a BTT Smart Filament Sensor\nSET_FILAMENT_SENSOR SENSOR=my_sensor ENABLE=0\n start_gcode_manual = 0 template_custom_gcode = thumbnails = 64x64,400x300 diff --git a/resources/shapes/universal wall mount hole.png b/resources/shapes/universal wall mount hole.png new file mode 100644 index 0000000000..3bf7b99576 Binary files /dev/null and b/resources/shapes/universal wall mount hole.png differ diff --git a/resources/shapes/universal wall mount hole.stl b/resources/shapes/universal wall mount hole.stl new file mode 100644 index 0000000000..358a42d95f Binary files /dev/null and b/resources/shapes/universal wall mount hole.stl differ diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index badb3b2c5f..6368f30f57 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -14,21 +14,44 @@ namespace Measure { constexpr double feature_hover_limit = 0.5; // how close to a feature the mouse must be to highlight it -static std::pair get_center_and_radius(const std::vector& border, int start_idx, int end_idx, const Transform3d& trafo) +static std::pair get_center_and_radius(const std::vector& points, const Transform3d& trafo) { - Vec2ds pts; + Vec2ds out; double z = 0.; - for (int i=start_idx; i<=end_idx; ++i) { - Vec3d pt_transformed = trafo * border[i]; + for (const Vec3d& pt : points) { + Vec3d pt_transformed = trafo * pt; z = pt_transformed.z(); - pts.emplace_back(pt_transformed.x(), pt_transformed.y()); + out.emplace_back(pt_transformed.x(), pt_transformed.y()); } - auto circle = Geometry::circle_ransac(pts, 20); // FIXME: iterations? + auto circle = Geometry::circle_ransac(out, 20); // FIXME: iterations? return std::make_pair(trafo.inverse() * Vec3d(circle.center.x(), circle.center.y(), z), circle.radius); } +static bool circle_fit_is_ok(const std::vector& pts, const Vec3d& center, double radius) +{ + for (const Vec3d& pt : pts) + if (std::abs((pt - center).norm() - radius) > 0.05) + return false; + return true; +} + +static std::array orthonormal_basis(const Vec3d& v) +{ + std::array ret; + ret[2] = v.normalized(); + int index; + ret[2].cwiseAbs().maxCoeff(&index); + switch (index) + { + case 0: { ret[0] = Vec3d(ret[2].y(), -ret[2].x(), 0.0).normalized(); break; } + case 1: { ret[0] = Vec3d(0.0, ret[2].z(), -ret[2].y()).normalized(); break; } + case 2: { ret[0] = Vec3d(-ret[2].z(), 0.0, ret[2].x()).normalized(); break; } + } + ret[1] = ret[2].cross(ret[0]).normalized(); + return ret; +} @@ -47,6 +70,7 @@ public: std::optional get_feature(size_t face_idx, const Vec3d& point) const; std::vector> get_planes_triangle_indices() const; const std::vector& get_plane_features(unsigned int plane_id) const; + const TriangleMesh& get_mesh() const; private: void update_planes(); @@ -54,7 +78,7 @@ private: std::vector m_planes; std::vector m_face_to_plane; - const indexed_triangle_set& m_its; + TriangleMesh m_mesh; }; @@ -63,7 +87,7 @@ private: MeasuringImpl::MeasuringImpl(const indexed_triangle_set& its) -: m_its{its} +: m_mesh(its) { update_planes(); extract_features(); @@ -76,10 +100,10 @@ void MeasuringImpl::update_planes() // 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 size_t num_of_facets = m_its.indices.size(); + const size_t num_of_facets = m_mesh.its.indices.size(); m_face_to_plane.resize(num_of_facets, size_t(-1)); - const std::vector face_normals = its_face_normals(m_its); - const std::vector face_neighbors = its_face_neighbors(m_its); + const std::vector face_normals = its_face_normals(m_mesh.its); + const std::vector face_neighbors = its_face_neighbors(m_mesh.its); std::vector facet_queue(num_of_facets, 0); int facet_queue_cnt = 0; const stl_normal* normal_ptr = nullptr; @@ -128,7 +152,7 @@ void MeasuringImpl::update_planes() assert(std::none_of(m_face_to_plane.begin(), m_face_to_plane.end(), [](size_t val) { return val == size_t(-1); })); // Now we will walk around each of the planes and save vertices which form the border. - SurfaceMesh sm(m_its); + SurfaceMesh sm(m_mesh.its); for (int plane_id=0; plane_id < int(m_planes.size()); ++plane_id) { const auto& facets = m_planes[plane_id].facets; m_planes[plane_id].borders.clear(); @@ -173,10 +197,16 @@ void MeasuringImpl::update_planes() he = sm.next_around_target(he); if (he.is_invalid()) goto PLANE_FAILURE; + + // For broken meshes, the iteration might never get back to he_orig. + // Remember all halfedges we saw to break out of such infinite loops. + boost::container::small_vector he_seen; + while ( (int)m_face_to_plane[sm.face(he)] == plane_id && he != he_orig) { + he_seen.emplace_back(he); he = sm.next_around_target(he); - if (he.is_invalid()) - goto PLANE_FAILURE; + if (he.is_invalid() || std::find(he_seen.begin(), he_seen.end(), he) != he_seen.end()) + goto PLANE_FAILURE; } he = sm.opposite(he); if (he.is_invalid()) @@ -194,12 +224,19 @@ void MeasuringImpl::update_planes() visited[face_it - facets.begin()][he.side()] = true; last_border.emplace_back(sm.point(sm.source(he)).cast()); + + // In case of broken meshes, this loop might be infinite. Break + // out in case it is clearly going bad. + if (last_border.size() > 3*facets.size()+1) + goto PLANE_FAILURE; + } while (he != he_start); if (last_border.size() == 1) m_planes[plane_id].borders.pop_back(); else { assert(last_border.front() == last_border.back()); + last_border.pop_back(); } } } @@ -217,7 +254,7 @@ void MeasuringImpl::update_planes() void MeasuringImpl::extract_features() { - std::vector angles; + std::vector angles; // placed in outer scope to prevent reallocations std::vector lengths; @@ -230,180 +267,201 @@ void MeasuringImpl::extract_features() q.setFromTwoVectors(plane.normal, Vec3d::UnitZ()); Transform3d trafo = Transform3d::Identity(); trafo.rotate(q); - + for (const std::vector& border : plane.borders) { if (border.size() <= 1) continue; - assert(border.front() == border.back()); - int start_idx = -1; - std::vector edges; + bool done = false; - // First calculate angles at all the vertices. - angles.clear(); - lengths.clear(); - for (int i=0; i M_PI) - angle = 2*M_PI - angle; + if (const auto& [center, radius] = get_center_and_radius(border, trafo); + (border.size()>4) && circle_fit_is_ok(border, center, radius)) { + // The whole border is one circle. Just add it into the list of features + // and we are done. - angles.push_back(angle); - lengths.push_back(v2.norm()); - } - assert(border.size() == angles.size()); - assert(border.size() == lengths.size()); + bool is_polygon = border.size()>4 && border.size()<=8; + bool lengths_match = std::all_of(border.begin()+2, border.end(), [is_polygon](const Vec3d& pt) { + return Slic3r::is_approx((pt - *((&pt)-1)).squaredNorm(), (*((&pt)-1) - *((&pt)-2)).squaredNorm(), is_polygon ? 0.01 : 0.01); + }); - - // First go around the border and pick what might be circular segments. - // Save pair of indices to where such potential segments start and end. - // Also remember the length of these segments. - bool circle = false; - std::vector circles; - std::vector> circles_idxs; - std::vector circles_lengths; - for (int i=1; i<(int)angles.size(); ++i) { - if (Slic3r::is_approx(lengths[i], lengths[i-1]) - && Slic3r::is_approx(angles[i], angles[i-1]) - && i != (int)angles.size()-1 ) { - // circle - if (! circle) { - circle = true; - start_idx = std::max(0, i-2); + if (lengths_match && (is_polygon || border.size() > 8)) { + if (is_polygon) { + // This is a polygon, add the separate edges with the center. + for (int j=0; j int { + assert(std::abs(offset) < border_size); + int out = idx+offset; + if (out >= border_size) + out = out - border_size; + else if (out < 0) + out = border_size + out; + + return out; + }; + + // First calculate angles at all the vertices. + angles.clear(); + lengths.clear(); + int first_different_angle_idx = 0; + for (int i=0; i M_PI) + angle = 2*M_PI - angle; + + angles.push_back(angle); + lengths.push_back(v2.norm()); + if (first_different_angle_idx == 0 && angles.size() > 1) { + if (! are_angles_same(angles.back(), angles[angles.size()-2])) + first_different_angle_idx = angles.size()-1; + } + } + assert(border.size() == angles.size()); + assert(border.size() == lengths.size()); + + // First go around the border and pick what might be circular segments. + // Save pair of indices to where such potential segments start and end. + // Also remember the length of these segments. + int start_idx = -1; + bool circle = false; + bool first_iter = true; + std::vector circles; + std::vector edges; + std::vector> circles_idxs; + //std::vector circles_lengths; + std::vector single_circle; // could be in loop-scope, but reallocations + double single_circle_length = 0.; + int first_pt_idx = offset_to_index(first_different_angle_idx, 1); + int i = first_pt_idx; + while (i != first_pt_idx || first_iter) { + if (are_angles_same(angles[i], angles[offset_to_index(i,-1)]) + && i != offset_to_index(first_pt_idx, -1) // not the last point + && i != start_idx ) { + // circle + if (! circle) { + circle = true; + single_circle.clear(); + single_circle_length = 0.; + start_idx = offset_to_index(i, -2); + single_circle = { border[start_idx], border[offset_to_index(start_idx,1)] }; + single_circle_length += lengths[offset_to_index(i, -1)]; + } + single_circle.emplace_back(border[i]); + single_circle_length += lengths[i]; + } else { + if (circle && single_circle.size() >= 5) { // Less than 5 vertices? Not a circle. + single_circle.emplace_back(border[i]); + single_circle_length += lengths[i]; + + bool accept_circle = true; + { + // Check that lengths of internal (!!!) edges match. + int j = offset_to_index(start_idx, 3); + while (j != i) { + if (! are_lengths_same(lengths[offset_to_index(j,-1)], lengths[j])) { + accept_circle = false; + break; + } + j = offset_to_index(j, 1); + } + } + + if (accept_circle) { + const auto& [center, radius] = get_center_and_radius(single_circle, trafo); + + // Check that the fit went well. The tolerance is high, only to + // reject complete failures. + accept_circle &= circle_fit_is_ok(single_circle, center, radius); + + // If the segment subtends less than 90 degrees, throw it away. + accept_circle &= single_circle_length / radius > 0.9*M_PI/2.; + + if (accept_circle) { + // Add the circle and remember indices into borders. + circles_idxs.emplace_back(start_idx, i); + circles.emplace_back(SurfaceFeature(SurfaceFeatureType::Circle, center, plane.normal, std::nullopt, radius)); + } + } + } circle = false; } + // Take care of the wrap around. + first_iter = false; + i = offset_to_index(i, 1); } - } - // At this point we might need to merge the first and last segment, if the starting - // point happened to be inside the segment. The discrimination of too small segments - // will follow, so we need a complete picture before that. - if (circles_idxs.size() > 1 - && circles_idxs.back().second == angles.size()-1 - && circles_idxs.front().first == 0) { - // Possibly the same circle. Check that the angle and length criterion holds along the combined segment. - bool same = true; - double last_len = -1.; - double last_angle = 0.; - for (int i=circles_idxs.back().first + 1; i != circles_idxs.front().second; ++i) { - if (i == angles.size()) - i = 1; - if (last_len == -1.) { - last_len = lengths[i]; - last_angle = angles[i]; - } else { - if (! Slic3r::is_approx(lengths[i], last_len) || ! Slic3r::is_approx(angles[i], last_angle)) { - same = false; - break; + // We have the circles. Now go around again and pick edges, while jumping over circles. + if (circles_idxs.empty()) { + // Just add all edges. + for (int i=1; i 1 || circles_idxs.front().first != circles_idxs.front().second) { + // There is at least one circular segment. Start at its end and add edges until the start of the next one. + int i = circles_idxs.front().second; + int circle_idx = 1; + while (true) { + i = offset_to_index(i, 1); + edges.emplace_back(SurfaceFeature(SurfaceFeatureType::Edge, border[offset_to_index(i,-1)], border[i])); + if (circle_idx < int(circles_idxs.size()) && i == circles_idxs[circle_idx].first) { + i = circles_idxs[circle_idx].second; + ++circle_idx; } + if (i == circles_idxs.front().first) + break; } } - if (same) { - // This seems to really be the same circle. Better apply ransac again. The parts can be small and inexact. - std::vector points(border.begin() + circles_idxs.back().first, border.end()); - points.insert(points.end(), border.begin(), border.begin() + circles_idxs.front().second+1); - auto [c, radius] = get_center_and_radius(points, 0, points.size()-1, trafo); - // Now replace the first circle with the combined one, remove the last circle. - // First index of the first circle is saved negative - we are going to pick edges - // from the border later, we will need to know where the merged in segment was. - // The sign simplifies the algorithm that picks the remaining edges - see below. - circles.front() = SurfaceFeature(SurfaceFeatureType::Circle, c, plane.normal, std::nullopt, radius); - circles_idxs.front().first = - circles_idxs.back().first; - circles_lengths.front() += circles_lengths.back(); - circles.pop_back(); - circles_idxs.pop_back(); - circles_lengths.pop_back(); + // Merge adjacent edges where needed. + assert(std::all_of(edges.begin(), edges.end(), + [](const SurfaceFeature& f) { return f.get_type() == SurfaceFeatureType::Edge; })); + for (int i=edges.size()-1; i>=0; --i) { + const auto& [first_start, first_end] = edges[i==0 ? edges.size()-1 : i-1].get_edge(); + const auto& [second_start, second_end] = edges[i].get_edge(); + + if (Slic3r::is_approx(first_end, second_start) + && Slic3r::is_approx((first_end-first_start).normalized().dot((second_end-second_start).normalized()), 1.)) { + // The edges have the same direction and share a point. Merge them. + edges[i==0 ? edges.size()-1 : i-1] = SurfaceFeature(SurfaceFeatureType::Edge, first_start, second_end); + edges.erase(edges.begin() + i); + } } - } - // Now throw away all circles that subtend less than 90 deg. - assert(circles.size() == circles_lengths.size()); - for (int i=0; i(circles[i].get_circle()); - if (circles_lengths[i] / r < 0.9*M_PI/2.) { - circles_lengths.erase(circles_lengths.begin() + i); - circles.erase(circles.begin() + i); - circles_idxs.erase(circles_idxs.begin() + i); - --i; - } + // Now move the circles and edges into the feature list for the plane. + assert(std::all_of(circles.begin(), circles.end(), [](const SurfaceFeature& f) { + return f.get_type() == SurfaceFeatureType::Circle; + })); + assert(std::all_of(edges.begin(), edges.end(), [](const SurfaceFeature& f) { + return f.get_type() == SurfaceFeatureType::Edge; + })); + plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(circles.begin()), + std::make_move_iterator(circles.end())); + plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(edges.begin()), + std::make_move_iterator(edges.end())); } - circles_lengths.clear(); // no longer needed, make it obvious - - // Anything under 5 vertices shall not be considered a circle. - assert(circles_idxs.size() == circles.size()); - for (int i=int(circles_idxs.size())-1; i>=0; --i) { - const auto& [start, end] = circles_idxs[i]; - int N = start >= 0 - ? end - start + (start == 0 && end == border.size()-1 ? 0 : 1) // last point is the same as first - : end + (border.size() + start); - if (N < 5) { - circles.erase(circles.begin() + i); - circles_idxs.erase(circles_idxs.begin() + i); - } else if (N <= 8 && start == 0 && end == border.size()-1) { - // This is a regular 5-8 polygon. Add the edges as edges with a special - // point and remove the circle. Leave the indices in circles_idxs, so - // the edges are not picked up again later. - const Vec3d center = std::get<0>(circles[i].get_circle()); - for (int j=1; j<=end; ++j) - edges.emplace_back(SurfaceFeature(SurfaceFeatureType::Edge, - border[j - 1], border[j], std::make_optional(center))); - circles.erase(circles.begin() + i); - } - } - - - // We have the circles. Now go around again and pick edges, while jumping over circles. - // If the first index of the first circle is negative, it means that it was merged - // with a segment that was originally at the back and is no longer there. Ressurect - // its pair of indices so that edges are not picked again. - if (! circles_idxs.empty() && circles_idxs.front().first < 0) - circles_idxs.emplace_back(-circles_idxs.front().first, int(border.size())); - int cidx = 0; // index of next circle to jump over - for (int i=1; i (int)circles_idxs[cidx].first) - i = circles_idxs[cidx++].second; - else - edges.emplace_back(SurfaceFeature(SurfaceFeatureType::Edge, border[i - 1], border[i])); - } - - // Merge adjacent edges where needed. - assert(std::all_of(edges.begin(), edges.end(), - [](const SurfaceFeature& f) { return f.get_type() == SurfaceFeatureType::Edge; })); - for (int i=edges.size()-1; i>=0; --i) { - const auto& [first_start, first_end] = edges[i==0 ? edges.size()-1 : i-1].get_edge(); - const auto& [second_start, second_end] = edges[i].get_edge(); - - if (Slic3r::is_approx(first_end, second_start) - && Slic3r::is_approx((first_end-first_start).normalized().dot((second_end-second_start).normalized()), 1.)) { - // The edges have the same direction and share a point. Merge them. - edges[i==0 ? edges.size()-1 : i-1] = SurfaceFeature(SurfaceFeatureType::Edge, first_start, second_end); - edges.erase(edges.begin() + i); - } - } - - // Now move the circles and edges into the feature list for the plane. - assert(std::all_of(circles.begin(), circles.end(), [](const SurfaceFeature& f) { - return f.get_type() == SurfaceFeatureType::Circle; - })); - assert(std::all_of(edges.begin(), edges.end(), [](const SurfaceFeature& f) { - return f.get_type() == SurfaceFeatureType::Edge; - })); - plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(circles.begin()), - std::make_move_iterator(circles.end())); - plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(edges.begin()), - std::make_move_iterator(edges.end())); } // The last surface feature is the plane itself. @@ -510,6 +568,10 @@ const std::vector& MeasuringImpl::get_plane_features(unsigned in return m_planes[plane_id].surface_features; } +const TriangleMesh& MeasuringImpl::get_mesh() const +{ + return this->m_mesh; +} @@ -551,6 +613,11 @@ const std::vector& Measuring::get_plane_features(unsigned int pl return priv->get_plane_features(plane_id); } +const TriangleMesh& Measuring::get_mesh() const +{ + return priv->get_mesh(); +} + const AngleAndEdges AngleAndEdges::Dummy = { 0.0, Vec3d::Zero(), { Vec3d::Zero(), Vec3d::Zero() }, { Vec3d::Zero(), Vec3d::Zero() }, 0.0, true }; static AngleAndEdges angle_edge_edge(const std::pair& e1, const std::pair& e2) @@ -620,8 +687,8 @@ static AngleAndEdges angle_edge_edge(const std::pair& e1, const st static AngleAndEdges angle_edge_plane(const std::pair& e, const std::tuple& p) { const auto& [idx, normal, origin] = p; - const Vec3d e1e2_unit = edge_direction(e); - if (are_parallel(e1e2_unit, normal) || are_perpendicular(e1e2_unit, normal)) + Vec3d e1e2_unit = edge_direction(e); + if (are_perpendicular(e1e2_unit, normal)) return AngleAndEdges::Dummy; // ensure the edge is pointing away from the intersection @@ -633,8 +700,22 @@ static AngleAndEdges angle_edge_plane(const std::pair& e, const st // then verify edge direction and revert it, if needed Vec3d e1 = e.first; Vec3d e2 = e.second; - if ((e1 - inters).squaredNorm() > (e2 - inters).squaredNorm()) + if ((e1 - inters).squaredNorm() > (e2 - inters).squaredNorm()) { std::swap(e1, e2); + e1e2_unit = -e1e2_unit; + } + + if (are_parallel(e1e2_unit, normal)) { + const std::array basis = orthonormal_basis(e1e2_unit); + const double radius = (0.5 * (e1 + e2) - inters).norm(); + const Vec3d edge_on_plane_dir = (basis[1].dot(origin - inters) >= 0.0) ? basis[1] : -basis[1]; + std::pair edge_on_plane = std::make_pair(inters, inters + radius * edge_on_plane_dir); + if (!inters.isApprox(e1)) { + edge_on_plane.first += radius * edge_on_plane_dir; + edge_on_plane.second += radius * edge_on_plane_dir; + } + return AngleAndEdges(0.5 * double(PI), inters, std::make_pair(e1, e2), edge_on_plane, radius, inters.isApprox(e1)); + } const Vec3d e1e2 = e2 - e1; const double e1e2_len = e1e2.norm(); @@ -763,7 +844,8 @@ MeasurementResult get_measurement(const SurfaceFeature& a, const SurfaceFeature& /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// - } else if (f1.get_type() == SurfaceFeatureType::Edge) { + } + else if (f1.get_type() == SurfaceFeatureType::Edge) { if (f2.get_type() == SurfaceFeatureType::Edge) { std::vector distances; @@ -890,21 +972,6 @@ MeasurementResult get_measurement(const SurfaceFeature& a, const SurfaceFeature& const Vec3d D = c1 - c0; if (!are_parallel(n0, n1)) { - auto orthonormal_basis = [](const Vec3d& v) { - std::array ret; - ret[2] = v.normalized(); - int index; - ret[2].maxCoeff(&index); - switch (index) - { - case 0: { ret[0] = Vec3d(ret[2].y(), -ret[2].x(), 0.0).normalized(); break; } - case 1: { ret[0] = Vec3d(0.0, ret[2].z(), -ret[2].y()).normalized(); break; } - case 2: { ret[0] = Vec3d(-ret[2].z(), 0.0, ret[2].x()).normalized(); break; } - } - ret[1] = ret[2].cross(ret[0]).normalized(); - return ret; - }; - // Get parameters for constructing the degree-8 polynomial phi. const double one = 1.0; const double two = 2.0; @@ -1149,27 +1216,6 @@ MeasurementResult get_measurement(const SurfaceFeature& a, const SurfaceFeature& return result; } -void DistAndPoints::transform(const Transform3d& trafo) { - from = trafo * from; - to = trafo * to; - dist = (to - from).norm(); -} - -void AngleAndEdges::transform(const Transform3d& trafo) { - const Vec3d old_e1 = e1.second - e1.first; - const Vec3d old_e2 = e2.second - e2.first; - center = trafo * center; - e1.first = trafo * e1.first; - e1.second = trafo * e1.second; - e2.first = trafo * e2.first; - e2.second = trafo * e2.second; - angle = std::acos(std::clamp(Measure::edge_direction(e1).dot(Measure::edge_direction(e2)), -1.0, 1.0)); - const Vec3d new_e1 = e1.second - e1.first; - const Vec3d new_e2 = e2.second - e2.first; - const double average_scale = 0.5 * (new_e1.norm() / old_e1.norm() + new_e2.norm() / old_e2.norm()); - radius = average_scale * radius; -} - diff --git a/src/libslic3r/Measure.hpp b/src/libslic3r/Measure.hpp index ede8c634ee..3a1a4b89d9 100644 --- a/src/libslic3r/Measure.hpp +++ b/src/libslic3r/Measure.hpp @@ -12,6 +12,9 @@ struct indexed_triangle_set; namespace Slic3r { + +class TriangleMesh; + namespace Measure { @@ -87,8 +90,7 @@ class MeasuringImpl; class Measuring { public: - // Construct the measurement object on a given its. The its must remain - // valid and unchanged during the whole lifetime of the object. + // Construct the measurement object on a given its. explicit Measuring(const indexed_triangle_set& its); ~Measuring(); @@ -108,6 +110,9 @@ public: // Returns the surface features of the plane with the given index const std::vector& get_plane_features(unsigned int plane_id) const; + // Returns the mesh used for measuring + const TriangleMesh& get_mesh() const; + private: std::unique_ptr priv; }; @@ -118,8 +123,6 @@ struct DistAndPoints { double dist; Vec3d from; Vec3d to; - - void transform(const Transform3d& trafo); }; struct AngleAndEdges { @@ -132,8 +135,6 @@ struct AngleAndEdges { double radius; bool coplanar; - void transform(const Transform3d& trafo); - static const AngleAndEdges Dummy; }; @@ -150,17 +151,6 @@ struct MeasurementResult { bool has_any_data() const { return angle.has_value() || distance_infinite.has_value() || distance_strict.has_value() || distance_xyz.has_value(); } - - void transform(const Transform3d& trafo) { - if (angle.has_value()) - angle->transform(trafo); - if (distance_infinite.has_value()) - distance_infinite->transform(trafo); - if (distance_strict.has_value()) { - distance_strict->transform(trafo); - distance_xyz = (distance_strict->to - distance_strict->from).cwiseAbs(); - } - } }; // Returns distance/angle between two SurfaceFeatures. diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index b328dbf28b..76668d0d2b 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1279,6 +1279,14 @@ void ModelObject::invalidate_cut() volume->invalidate_cut_info(); } +void ModelObject::delete_connectors() +{ + for (int id = int(this->volumes.size()) - 1; id >= 0; id--) { + if (volumes[id]->is_cut_connector()) + this->delete_volume(size_t(id)); + } +} + void ModelObject::synchronize_model_after_cut() { for (ModelObject* obj : m_model->objects) { @@ -1994,6 +2002,14 @@ int ModelObject::get_repaired_errors_count(const int vol_idx /*= -1*/) const stats.facets_reversed + stats.backwards_edges; } +bool ModelObject::has_solid_mesh() const +{ + for (const ModelVolume* volume : volumes) + if (volume->is_model_part()) + return true; + return false; +} + void ModelVolume::set_material_id(t_model_material_id material_id) { m_material_id = material_id; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index d514171f17..1cd6c34143 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -449,6 +449,8 @@ public: void apply_cut_connectors(const std::string& name); // invalidate cut state for this object and its connectors/volumes void invalidate_cut(); + // delete volumes which are marked as connector for this object + void delete_connectors(); void synchronize_model_after_cut(); void apply_cut_attributes(ModelObjectCutAttributes attributes); void clone_for_cut(ModelObject **obj); @@ -482,6 +484,8 @@ public: // Get count of errors in the mesh( or all object's meshes, if volume index isn't defined) int get_repaired_errors_count(const int vol_idx = -1) const; + // Detect if object has at least one solid mash + bool has_solid_mesh() const; bool is_cut() const { return cut_id.id().valid(); } bool has_connectors() const; @@ -758,9 +762,7 @@ public: // The triangular model. const TriangleMesh& mesh() const { return *m_mesh.get(); } -#if ENABLE_RAYCAST_PICKING std::shared_ptr mesh_ptr() const { return m_mesh; } -#endif // ENABLE_RAYCAST_PICKING void set_mesh(const TriangleMesh &mesh) { m_mesh = std::make_shared(mesh); } void set_mesh(TriangleMesh &&mesh) { m_mesh = std::make_shared(std::move(mesh)); } void set_mesh(const indexed_triangle_set &mesh) { m_mesh = std::make_shared(mesh); } diff --git a/src/libslic3r/SurfaceMesh.hpp b/src/libslic3r/SurfaceMesh.hpp index 9e547eec49..93eb9fdaa6 100644 --- a/src/libslic3r/SurfaceMesh.hpp +++ b/src/libslic3r/SurfaceMesh.hpp @@ -4,6 +4,8 @@ #include #include +#include "boost/container/small_vector.hpp" + namespace Slic3r { class TriangleMesh; @@ -115,11 +117,18 @@ public: size_t degree(Vertex_index v) const { + // In case the mesh is broken badly, the loop might end up to be infinite, + // never getting back to the first halfedge. Remember list of all half-edges + // and trip if any is encountered for the second time. Halfedge_index h_first = halfedge(v); + boost::container::small_vector he_visited; Halfedge_index h = next_around_target(h_first); size_t degree = 2; while (! h.is_invalid() && h != h_first) { + he_visited.emplace_back(h); h = next_around_target(h); + if (std::find(he_visited.begin(), he_visited.end(), h) == he_visited.end()) + return 0; ++degree; } return h.is_invalid() ? 0 : degree - 1; diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index c80689f48b..4e6d2106b1 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -28,6 +28,8 @@ #define DISABLE_GCODEVIEWER_INSTANCED_MODELS 1 // Enable Measure Gizmo debug window #define ENABLE_MEASURE_GIZMO_DEBUG 0 +// Enable scene raycast picking debug window +#define ENABLE_RAYCAST_PICKING_DEBUG 0 // Enable rendering of objects using environment map @@ -37,12 +39,12 @@ //==================== -// 2.5.0.alpha1 techs +// 2.6.0.alpha1 techs //==================== -#define ENABLE_2_5_0_ALPHA1 1 +#define ENABLE_2_6_0_ALPHA1 1 // Enable removal of legacy OpenGL calls -#define ENABLE_LEGACY_OPENGL_REMOVAL (1 && ENABLE_2_5_0_ALPHA1) +#define ENABLE_LEGACY_OPENGL_REMOVAL (1 && ENABLE_2_6_0_ALPHA1) // Enable OpenGL ES #define ENABLE_OPENGL_ES (0 && ENABLE_LEGACY_OPENGL_REMOVAL) // Enable OpenGL core profile context (tested against Mesa 20.1.8 on Windows) @@ -52,18 +54,15 @@ // Shows an imgui dialog with GLModel statistics data #define ENABLE_GLMODEL_STATISTICS (0 && ENABLE_LEGACY_OPENGL_REMOVAL) // Enable rework of Reload from disk command -#define ENABLE_RELOAD_FROM_DISK_REWORK (1 && ENABLE_2_5_0_ALPHA1) +#define ENABLE_RELOAD_FROM_DISK_REWORK (1 && ENABLE_2_6_0_ALPHA1) // Enable editing volumes transformation in world coordinates and instances in local coordinates -#define ENABLE_WORLD_COORDINATE (1 && ENABLE_2_5_0_ALPHA1) +#define ENABLE_WORLD_COORDINATE (1 && ENABLE_2_6_0_ALPHA1) // Enable alternative version of file_wildcards() -#define ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR (1 && ENABLE_2_5_0_ALPHA1) +#define ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR (1 && ENABLE_2_6_0_ALPHA1) // Enable processing of gcode G2 and G3 lines -#define ENABLE_PROCESS_G2_G3_LINES (1 && ENABLE_2_5_0_ALPHA1) +#define ENABLE_PROCESS_G2_G3_LINES (1 && ENABLE_2_6_0_ALPHA1) // Enable fix of used filament data exported to gcode file -#define ENABLE_USED_FILAMENT_POST_PROCESS (1 && ENABLE_2_5_0_ALPHA1) -// Enable picking using raytracing -#define ENABLE_RAYCAST_PICKING (1 && ENABLE_LEGACY_OPENGL_REMOVAL) -#define ENABLE_RAYCAST_PICKING_DEBUG (0 && ENABLE_RAYCAST_PICKING) +#define ENABLE_USED_FILAMENT_POST_PROCESS (1 && ENABLE_2_6_0_ALPHA1) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 1402584028..a7e70bc430 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -252,10 +252,8 @@ bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, c m_axes.set_origin({ 0.0, 0.0, static_cast(GROUND_Z) }); m_axes.set_stem_length(0.1f * static_cast(m_build_volume.bounding_volume().max_size())); -#if ENABLE_RAYCAST_PICKING // unregister from picking wxGetApp().plater()->canvas3D()->remove_raycasters_for_picking(SceneRaycaster::EType::Bed); -#endif // ENABLE_RAYCAST_PICKING // Let the calee to update the UI. return true; @@ -309,11 +307,7 @@ void Bed3D::render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor, glsafe(::glEnable(GL_DEPTH_TEST)); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING m_model.model.set_color(picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR); -#else - m_model.set_color(picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR); -#endif // ENABLE_RAYCAST_PICKING #else m_model.set_color(-1, picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR); #endif // ENABLE_LEGACY_OPENGL_REMOVAL @@ -355,11 +349,7 @@ BoundingBoxf3 Bed3D::calc_extended_bounding_box() const out.merge(out.min + Vec3d(-Axes::DefaultTipRadius, -Axes::DefaultTipRadius, out.max.z())); #endif // ENABLE_WORLD_COORDINATE // extend to contain model, if any -#if ENABLE_RAYCAST_PICKING BoundingBoxf3 model_bb = m_model.model.get_bounding_box(); -#else - BoundingBoxf3 model_bb = m_model.get_bounding_box(); -#endif // ENABLE_RAYCAST_PICKING if (model_bb.defined) { model_bb.translate(m_model_offset); out.merge(model_bb); @@ -409,16 +399,12 @@ void Bed3D::init_triangles() init_data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1); } -#if ENABLE_RAYCAST_PICKING if (m_model.model.get_filename().empty() && m_model.mesh_raycaster == nullptr) // register for picking register_raycasters_for_picking(init_data, Transform3d::Identity()); -#endif // ENABLE_RAYCAST_PICKING m_triangles.init_from(std::move(init_data)); -#if ENABLE_RAYCAST_PICKING m_triangles.set_color(DEFAULT_MODEL_COLOR); -#endif // ENABLE_RAYCAST_PICKING } void Bed3D::init_gridlines() @@ -798,17 +784,9 @@ void Bed3D::render_model() if (m_model_filename.empty()) return; -#if ENABLE_RAYCAST_PICKING if (m_model.model.get_filename() != m_model_filename && m_model.model.init_from_file(m_model_filename)) { -#else - if (m_model.get_filename() != m_model_filename && m_model.init_from_file(m_model_filename)) { -#endif // ENABLE_RAYCAST_PICKING #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING m_model.model.set_color(DEFAULT_MODEL_COLOR); -#else - m_model.set_color(DEFAULT_MODEL_COLOR); -#endif // ENABLE_RAYCAST_PICKING #else m_model.set_color(-1, DEFAULT_MODEL_COLOR); #endif // ENABLE_LEGACY_OPENGL_REMOVAL @@ -816,20 +794,14 @@ void Bed3D::render_model() // move the model so that its origin (0.0, 0.0, 0.0) goes into the bed shape center and a bit down to avoid z-fighting with the texture quad m_model_offset = to_3d(m_build_volume.bounding_volume2d().center(), -0.03); -#if ENABLE_RAYCAST_PICKING // register for picking register_raycasters_for_picking(m_model.model.get_geometry(), Geometry::translation_transform(m_model_offset)); -#endif // ENABLE_RAYCAST_PICKING // update extended bounding box m_extended_bounding_box = this->calc_extended_bounding_box(); } -#if ENABLE_RAYCAST_PICKING if (!m_model.model.get_filename().empty()) { -#else - if (!m_model.get_filename().empty()) { -#endif // ENABLE_RAYCAST_PICKING GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader != nullptr) { shader->start_using(); @@ -844,11 +816,7 @@ void Bed3D::render_model() glsafe(::glPushMatrix()); glsafe(::glTranslated(m_model_offset.x(), m_model_offset.y(), m_model_offset.z())); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING m_model.model.render(); -#else - m_model.render(); -#endif // ENABLE_RAYCAST_PICKING #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL @@ -914,23 +882,14 @@ void Bed3D::render_default(bool bottom, bool picking, bool show_texture) glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); -#if ENABLE_RAYCAST_PICKING const bool has_model = !m_model.model.get_filename().empty(); -#else - const bool has_model = !m_model.get_filename().empty(); -#endif // ENABLE_RAYCAST_PICKING - if (!has_model && !bottom) { // draw background glsafe(::glDepthMask(GL_FALSE)); -#if !ENABLE_RAYCAST_PICKING - m_triangles.set_color(picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR); -#endif // !ENABLE_RAYCAST_PICKING m_triangles.render(); glsafe(::glDepthMask(GL_TRUE)); } -#if ENABLE_RAYCAST_PICKING if (show_texture) { // draw grid #if ENABLE_GL_CORE_PROFILE @@ -942,19 +901,6 @@ void Bed3D::render_default(bool bottom, bool picking, bool show_texture) } else render_contour(view_matrix, projection_matrix); -#else - if (!picking && show_texture) { - // draw grid -#if ENABLE_GL_CORE_PROFILE - if (!OpenGLManager::get_gl_info().is_core_profile()) -#endif // ENABLE_GL_CORE_PROFILE - glsafe(::glLineWidth(1.5f * m_scale_factor)); - m_gridlines.set_color(has_model && !bottom ? DEFAULT_SOLID_GRID_COLOR : DEFAULT_TRANSPARENT_GRID_COLOR); - m_gridlines.render(); - } - else if (!show_texture) - render_contour(view_matrix, projection_matrix); -#endif // ENABLE_RAYCAST_PICKING glsafe(::glDisable(GL_BLEND)); @@ -1047,7 +993,6 @@ void Bed3D::release_VBOs() } #endif // !ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING void Bed3D::register_raycasters_for_picking(const GLModel::Geometry& geometry, const Transform3d& trafo) { assert(m_model.mesh_raycaster == nullptr); @@ -1066,7 +1011,6 @@ void Bed3D::register_raycasters_for_picking(const GLModel::Geometry& geometry, c m_model.mesh_raycaster = std::make_unique(std::make_shared(std::move(its))); wxGetApp().plater()->canvas3D()->add_raycaster_for_picking(SceneRaycaster::EType::Bed, 0, *m_model.mesh_raycaster, trafo); } -#endif // ENABLE_RAYCAST_PICKING } // GUI } // Slic3r diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp index 7f0dff19d0..c12674b4a7 100644 --- a/src/slic3r/GUI/3DBed.hpp +++ b/src/slic3r/GUI/3DBed.hpp @@ -8,9 +8,7 @@ #else #include "GLModel.hpp" #endif // ENABLE_WORLD_COORDINATE -#if ENABLE_RAYCAST_PICKING #include "MeshUtils.hpp" -#endif // ENABLE_RAYCAST_PICKING #include "libslic3r/BuildVolume.hpp" #if ENABLE_LEGACY_OPENGL_REMOVAL @@ -111,11 +109,7 @@ private: GLTexture m_texture; // temporary texture shown until the main texture has still no levels compressed GLTexture m_temp_texture; -#if ENABLE_RAYCAST_PICKING PickingModel m_model; -#else - GLModel m_model; -#endif // ENABLE_RAYCAST_PICKING Vec3d m_model_offset{ Vec3d::Zero() }; #if !ENABLE_LEGACY_OPENGL_REMOVAL unsigned int m_vbo_id{ 0 }; @@ -205,9 +199,7 @@ private: void release_VBOs(); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING void register_raycasters_for_picking(const GLModel::Geometry& geometry, const Transform3d& trafo); -#endif // ENABLE_RAYCAST_PICKING }; } // GUI diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index c6ef2d13b1..fd2dba9c27 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -807,27 +807,17 @@ int GLVolumeCollection::load_object_volume( const ModelVolume *model_volume = model_object->volumes[volume_idx]; const int extruder_id = model_volume->extruder_id(); const ModelInstance *instance = model_object->instances[instance_idx]; -#if ENABLE_RAYCAST_PICKING std::shared_ptr mesh = model_volume->mesh_ptr(); -#else - const TriangleMesh &mesh = model_volume->mesh(); -#endif // ENABLE_RAYCAST_PICKING this->volumes.emplace_back(new GLVolume()); GLVolume& v = *this->volumes.back(); v.set_color(color_from_model_volume(*model_volume)); #if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_SMOOTH_NORMALS v.model.init_from(*mesh, true); -#if ENABLE_RAYCAST_PICKING v.mesh_raycaster = std::make_unique(mesh); -#endif // ENABLE_RAYCAST_PICKING #else -#if ENABLE_RAYCAST_PICKING v.model.init_from(*mesh); v.mesh_raycaster = std::make_unique(mesh); -#else - v.model.init_from(mesh); -#endif // ENABLE_RAYCAST_PICKING #endif // ENABLE_SMOOTH_NORMALS #else #if ENABLE_SMOOTH_NORMALS @@ -886,13 +876,10 @@ int GLVolumeCollection::load_wipe_tower_preview( depth = std::max(depth, 10.f); float min_width = 30.f; -#if ENABLE_RAYCAST_PICKING const float scaled_brim_height = 0.2f / height; -#endif // ENABLE_RAYCAST_PICKING // We'll now create the box with jagged edge. y-coordinates of the pre-generated model // are shifted so that the front edge has y=0 and centerline of the back edge has y=depth: -#if ENABLE_RAYCAST_PICKING // We split the box in three main pieces, // the two laterals are identical and the central is the one containing the jagged geometry @@ -993,22 +980,6 @@ int GLVolumeCollection::load_wipe_tower_preview( tooth_mesh.merge(TriangleMesh(std::move(data))); data = generate_lateral(61.547f, 100.0f); tooth_mesh.merge(TriangleMesh(std::move(data))); -#else - float out_points_idx[][3] = { { 0, -depth, 0 }, { 0, 0, 0 }, { 38.453f, 0, 0 }, { 61.547f, 0, 0 }, { 100.0f, 0, 0 }, { 100.0f, -depth, 0 }, { 55.7735f, -10.0f, 0 }, { 44.2265f, 10.0f, 0 }, - { 38.453f, 0, 1 }, { 0, 0, 1 }, { 0, -depth, 1 }, { 100.0f, -depth, 1 }, { 100.0f, 0, 1 }, { 61.547f, 0, 1 }, { 55.7735f, -10.0f, 1 }, { 44.2265f, 10.0f, 1 } }; - static constexpr const int out_facets_idx[][3] = { - { 0, 1, 2 }, { 3, 4, 5 }, { 6, 5, 0 }, { 3, 5, 6 }, { 6, 2, 7 }, { 6, 0, 2 }, { 8, 9, 10 }, { 11, 12, 13 }, { 10, 11, 14 }, { 14, 11, 13 }, { 15, 8, 14 }, - { 8, 10, 14 }, { 3, 12, 4 }, { 3, 13, 12 }, { 6, 13, 3 }, { 6, 14, 13 }, { 7, 14, 6 }, { 7, 15, 14 }, { 2, 15, 7 }, { 2, 8, 15 }, { 1, 8, 2 }, { 1, 9, 8 }, - { 0, 9, 1 }, { 0, 10, 9 }, { 5, 10, 0 }, { 5, 11, 10 }, { 4, 11, 5 }, { 4, 12, 11 } }; - indexed_triangle_set its; - for (int i = 0; i < 16; ++i) - its.vertices.emplace_back(out_points_idx[i][0] / (100.f / min_width), - out_points_idx[i][1] + depth, out_points_idx[i][2]); - its.indices.reserve(28); - for (const int *face : out_facets_idx) - its.indices.emplace_back(face); - TriangleMesh tooth_mesh(std::move(its)); -#endif // ENABLE_RAYCAST_PICKING // We have the mesh ready. It has one tooth and width of min_width. We will now // append several of these together until we are close to the required width @@ -1016,14 +987,9 @@ int GLVolumeCollection::load_wipe_tower_preview( size_t n = std::max(1, int(width / min_width)); // How many shall be merged? for (size_t i = 0; i < n; ++i) { mesh.merge(tooth_mesh); -#if ENABLE_RAYCAST_PICKING tooth_mesh.translate(100.0f, 0.0f, 0.0f); -#else - tooth_mesh.translate(min_width, 0.f, 0.f); -#endif // ENABLE_RAYCAST_PICKING } -#if ENABLE_RAYCAST_PICKING // Now we add the caps along the X axis const float scaled_brim_width_x = brim_width * n * width / min_width; auto generate_negx_cap = [&]() { @@ -1098,20 +1064,10 @@ int GLVolumeCollection::load_wipe_tower_preview( data = generate_posx_cap(); mesh.merge(TriangleMesh(std::move(data))); mesh.scale(Vec3f(width / (n * 100.0f), 1.0f, height)); // Scaling to proper width -#else - mesh.scale(Vec3f(width / (n * min_width), 1.f, height)); // Scaling to proper width -#endif // ENABLE_RAYCAST_PICKING } else mesh = make_cube(width, depth, height); -#if !ENABLE_RAYCAST_PICKING - // We'll make another mesh to show the brim (fixed layer height): - TriangleMesh brim_mesh = make_cube(width + 2.f * brim_width, depth + 2.f * brim_width, 0.2f); - brim_mesh.translate(-brim_width, -brim_width, 0.f); - mesh.merge(brim_mesh); -#endif // !ENABLE_RAYCAST_PICKING - volumes.emplace_back(new GLVolume(color)); GLVolume& v = *volumes.back(); #if ENABLE_LEGACY_OPENGL_REMOVAL @@ -1121,9 +1077,7 @@ int GLVolumeCollection::load_wipe_tower_preview( #endif // ENABLE_OPENGL_ES v.model.init_from(mesh); v.model.set_color(color); -#if ENABLE_RAYCAST_PICKING v.mesh_raycaster = std::make_unique(std::make_shared(mesh)); -#endif // ENABLE_RAYCAST_PICKING #else v.indexed_vertex_array.load_mesh(mesh); #endif // ENABLE_LEGACY_OPENGL_REMOVAL @@ -1232,15 +1186,10 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab #endif // ENABLE_GL_CORE_PROFILE #endif // ENABLE_LEGACY_OPENGL_REMOVAL - ScopeGuard transparent_sg; if (type == ERenderType::Transparent) { glsafe(::glEnable(GL_BLEND)); glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); glsafe(::glDepthMask(false)); - transparent_sg = ScopeGuard([]() { - glsafe(::glDisable(GL_BLEND)); - glsafe(::glDepthMask(true)); - }); } glsafe(::glCullFace(GL_BACK)); @@ -1368,6 +1317,11 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab if (disable_cullface) glsafe(::glEnable(GL_CULL_FACE)); + + if (type == ERenderType::Transparent) { + glsafe(::glDisable(GL_BLEND)); + glsafe(::glDepthMask(true)); + } } bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state) const diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index d1c16290f1..93cb32dc4d 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -10,9 +10,7 @@ #include "libslic3r/Color.hpp" #include "GLModel.hpp" -#if ENABLE_RAYCAST_PICKING #include "MeshUtils.hpp" -#endif // ENABLE_RAYCAST_PICKING #include #include @@ -393,10 +391,8 @@ public: #if ENABLE_LEGACY_OPENGL_REMOVAL GUI::GLModel model; -#if ENABLE_RAYCAST_PICKING // raycaster used for picking std::unique_ptr mesh_raycaster; -#endif // ENABLE_RAYCAST_PICKING #else // Interleaved triangles & normals with indexed triangles & quads. GLIndexedVertexArray indexed_vertex_array; diff --git a/src/slic3r/GUI/Camera.cpp b/src/slic3r/GUI/Camera.cpp index 56980c43a5..a549d87da8 100644 --- a/src/slic3r/GUI/Camera.cpp +++ b/src/slic3r/GUI/Camera.cpp @@ -91,7 +91,6 @@ void Camera::select_view(const std::string& direction) look_at(m_target + m_distance * Vec3d::UnitY(), m_target, Vec3d::UnitZ()); } -#if ENABLE_RAYCAST_PICKING double Camera::get_near_left() const { switch (m_type) @@ -163,7 +162,6 @@ double Camera::get_near_height() const return 2.0 / m_projection_matrix.matrix()(1, 1); } } -#endif // ENABLE_RAYCAST_PICKING double Camera::get_fov() const { @@ -177,7 +175,6 @@ double Camera::get_fov() const }; } -#if ENABLE_RAYCAST_PICKING void Camera::set_viewport(int x, int y, unsigned int w, unsigned int h) { #if ENABLE_LEGACY_OPENGL_REMOVAL @@ -191,17 +188,6 @@ void Camera::apply_viewport() const { glsafe(::glViewport(m_viewport[0], m_viewport[1], m_viewport[2], m_viewport[3])); } -#else -void Camera::apply_viewport(int x, int y, unsigned int w, unsigned int h) -{ - glsafe(::glViewport(0, 0, w, h)); -#if ENABLE_LEGACY_OPENGL_REMOVAL - m_viewport = { 0, 0, int(w), int(h) }; -#else - glsafe(::glGetIntegerv(GL_VIEWPORT, m_viewport.data())); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL -} -#endif // ENABLE_RAYCAST_PICKING #if !ENABLE_LEGACY_OPENGL_REMOVAL void Camera::apply_view_matrix() @@ -260,37 +246,7 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa } #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING apply_projection(-w, w, -h, h, m_frustrum_zs.first, m_frustrum_zs.second); -#else - switch (m_type) - { - default: - case EType::Ortho: - { - const double dz = m_frustrum_zs.second - m_frustrum_zs.first; - const double zz = m_frustrum_zs.first + m_frustrum_zs.second; - m_projection_matrix.matrix() << 1.0 / w, 0.0, 0.0, 0.0, - 0.0, 1.0 / h, 0.0, 0.0, - 0.0, 0.0, -2.0 / dz, -zz / dz, - 0.0, 0.0, 0.0, 1.0; - break; - } - case EType::Perspective: - { - const double n = m_frustrum_zs.first; - const double f = m_frustrum_zs.second; - const double dz = f - n; - const double zz = n + f; - const double fn = n * f; - m_projection_matrix.matrix() << n / w, 0.0, 0.0, 0.0, - 0.0, n / h, 0.0, 0.0, - 0.0, 0.0, -zz / dz, -2.0 * fn / dz, - 0.0, 0.0, -1.0, 0.0; - break; - } - } -#endif // ENABLE_RAYCAST_PICKING #else glsafe(::glMatrixMode(GL_PROJECTION)); glsafe(::glLoadIdentity()); @@ -315,7 +271,6 @@ void Camera::apply_projection(const BoundingBoxf3& box, double near_z, double fa #endif // ENABLE_LEGACY_OPENGL_REMOVAL } -#if ENABLE_RAYCAST_PICKING void Camera::apply_projection(double left, double right, double bottom, double top, double near_z, double far_z) { assert(left != right && bottom != top && near_z != far_z); @@ -344,7 +299,6 @@ void Camera::apply_projection(double left, double right, double bottom, double t } } } -#endif // ENABLE_RAYCAST_PICKING void Camera::zoom_to_box(const BoundingBoxf3& box, double margin_factor) { diff --git a/src/slic3r/GUI/Camera.hpp b/src/slic3r/GUI/Camera.hpp index b2672e14e5..dca7ba642e 100644 --- a/src/slic3r/GUI/Camera.hpp +++ b/src/slic3r/GUI/Camera.hpp @@ -89,33 +89,24 @@ public: double get_far_z() const { return m_frustrum_zs.second; } const std::pair& get_z_range() const { return m_frustrum_zs; } -#if ENABLE_RAYCAST_PICKING double get_near_left() const; double get_near_right() const; double get_near_top() const; double get_near_bottom() const; double get_near_width() const; double get_near_height() const; -#endif // ENABLE_RAYCAST_PICKING double get_fov() const; -#if ENABLE_RAYCAST_PICKING void set_viewport(int x, int y, unsigned int w, unsigned int h); void apply_viewport() const; -#else - void apply_viewport(int x, int y, unsigned int w, unsigned int h); -#endif // ENABLE_RAYCAST_PICKING #if !ENABLE_LEGACY_OPENGL_REMOVAL void apply_view_matrix(); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL // Calculates and applies the projection matrix tighting the frustrum z range around the given box. // If larger z span is needed, pass the desired values of near and far z (negative values are ignored) void apply_projection(const BoundingBoxf3& box, double near_z = -1.0, double far_z = -1.0); - -#if ENABLE_RAYCAST_PICKING void apply_projection(double left, double right, double bottom, double top, double near_z, double far_z); -#endif // ENABLE_RAYCAST_PICKING void zoom_to_box(const BoundingBoxf3& box, double margin_factor = DefaultZoomToBoxMarginFactor); void zoom_to_volumes(const GLVolumePtrs& volumes, double margin_factor = DefaultZoomToVolumesMarginFactor); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 636080db79..51f01c94e6 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1346,19 +1346,23 @@ void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObje m_render_sla_auxiliaries = visible; + std::vector>* raycasters = get_raycasters_for_picking(SceneRaycaster::EType::Volume); + for (GLVolume* vol : m_volumes.volumes) { - if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo) - && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx) - && vol->composite_id.volume_id < 0) + if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo) + && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx) + && vol->composite_id.volume_id < 0) { vol->is_active = visible; + auto it = std::find_if(raycasters->begin(), raycasters->end(), [vol](std::shared_ptr item) { return item->get_raycaster() == vol->mesh_raycaster.get(); }); + if (it != raycasters->end()) + (*it)->set_active(vol->is_active); + } } } void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject* mo, int instance_idx, const ModelVolume* mv) { -#if ENABLE_RAYCAST_PICKING std::vector>* raycasters = get_raycasters_for_picking(SceneRaycaster::EType::Volume); -#endif // ENABLE_RAYCAST_PICKING for (GLVolume* vol : m_volumes.volumes) { if (vol->is_wipe_tower) vol->is_active = (visible && mo == nullptr); @@ -1376,13 +1380,11 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject } else { const GLGizmosManager& gm = get_gizmos_manager(); auto gizmo_type = gm.get_current_type(); - if ( (gizmo_type == GLGizmosManager::FdmSupports + if ( (gizmo_type == GLGizmosManager::FdmSupports || gizmo_type == GLGizmosManager::Seam || gizmo_type == GLGizmosManager::Cut) && !vol->is_modifier) { vol->force_neutral_color = true; - if (gizmo_type == GLGizmosManager::Cut) - vol->color.a(0.95f); } else if (gizmo_type == GLGizmosManager::MmuSegmentation) vol->is_active = false; @@ -1391,11 +1393,10 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject } } } -#if ENABLE_RAYCAST_PICKING + auto it = std::find_if(raycasters->begin(), raycasters->end(), [vol](std::shared_ptr item) { return item->get_raycaster() == vol->mesh_raycaster.get(); }); if (it != raycasters->end()) (*it)->set_active(vol->is_active); -#endif // ENABLE_RAYCAST_PICKING } if (visible && !mo) @@ -1653,12 +1654,8 @@ void GLCanvas3D::render() // and the viewport was set incorrectly, leading to tripping glAsserts further down // the road (in apply_projection). That's why the minimum size is forced to 10. Camera& camera = wxGetApp().plater()->get_camera(); -#if ENABLE_RAYCAST_PICKING camera.set_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height())); camera.apply_viewport(); -#else - camera.apply_viewport(0, 0, std::max(10u, (unsigned int)cnv_size.get_width()), std::max(10u, (unsigned int)cnv_size.get_height())); -#endif // ENABLE_RAYCAST_PICKING if (camera.requires_zoom_to_bed) { zoom_to_bed(); @@ -2270,7 +2267,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re manip->set_dirty(); } -#if ENABLE_RAYCAST_PICKING // refresh volume raycasters for picking m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::Volume); for (size_t i = 0; i < m_volumes.volumes.size(); ++i) { @@ -2287,7 +2283,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::Gizmo); if (curr_gizmo != nullptr && !m_selection.is_empty()) curr_gizmo->register_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING // and force this canvas to be redrawn. m_dirty = true; @@ -2833,11 +2828,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) // set_cursor(Standard); } else if (keyCode == WXK_CONTROL) { -#if ENABLE_RAYCAST_PICKING - if (m_mouse.dragging && !m_moving) { -#else - if (m_mouse.dragging) { -#endif // ENABLE_RAYCAST_PICKING + if (m_mouse.dragging && !m_moving) { // if the user releases CTRL while rotating the 3D scene // prevent from moving the selected volume m_mouse.drag.move_volume_idx = -1; @@ -3353,9 +3344,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (!evt.CmdDown()) m_mouse.drag.start_position_3D = m_mouse.scene_position; m_sequential_print_clearance_first_displacement = true; -#if !ENABLE_RAYCAST_PICKING - m_moving = true; -#endif // !ENABLE_RAYCAST_PICKING } } } @@ -3399,9 +3387,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } #if ENABLE_WORLD_COORDINATE -#if ENABLE_RAYCAST_PICKING m_moving = true; -#endif // ENABLE_RAYCAST_PICKING TransformationType trafo_type; trafo_type.set_relative(); m_selection.translate(cur_pos - m_mouse.drag.start_position_3D, trafo_type); @@ -3432,9 +3418,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // do not process the dragging if the left mouse was set down in another canvas else if (evt.LeftIsDown()) { // if dragging over blank area with left button, rotate -#if ENABLE_RAYCAST_PICKING if (!m_moving) { -#endif // ENABLE_RAYCAST_PICKING if ((any_gizmo_active || evt.CmdDown() || m_hover_volume_idxs.empty()) && m_mouse.is_start_position_3D_defined()) { const Vec3d rot = (Vec3d(pos.x(), pos.y(), 0.0) - m_mouse.drag.start_position_3D) * (PI * TRACKBALLSIZE / 180.0); if (wxGetApp().app_config->get("use_free_camera") == "1") @@ -3453,9 +3437,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_dirty = true; } m_mouse.drag.start_position_3D = Vec3d((double)pos.x(), (double)pos.y(), 0.0); -#if ENABLE_RAYCAST_PICKING } -#endif // ENABLE_RAYCAST_PICKING } else if (evt.MiddleIsDown() || evt.RightIsDown()) { // If dragging over blank area with right/middle button, pan. @@ -3480,9 +3462,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) } } else if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) { -#if ENABLE_RAYCAST_PICKING m_mouse.position = pos.cast(); -#endif // ENABLE_RAYCAST_PICKING if (m_layers_editing.state != LayersEditing::Unknown) { m_layers_editing.state = LayersEditing::Unknown; @@ -3508,9 +3488,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) deselect_all(); } else if (evt.RightUp()) { -#if !ENABLE_RAYCAST_PICKING - m_mouse.position = pos.cast(); -#endif // !ENABLE_RAYCAST_PICKING // forces a frame render to ensure that m_hover_volume_idxs is updated even when the user right clicks while // the context menu is already shown render(); @@ -4501,12 +4478,8 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const Camera camera; camera.set_type(camera_type); camera.set_scene_box(scene_bounding_box()); -#if ENABLE_RAYCAST_PICKING camera.set_viewport(0, 0, thumbnail_data.width, thumbnail_data.height); camera.apply_viewport(); -#else - camera.apply_viewport(0, 0, thumbnail_data.width, thumbnail_data.height); -#endif // ENABLE_RAYCAST_PICKING camera.zoom_to_box(volumes_box); #if ENABLE_LEGACY_OPENGL_REMOVAL @@ -4808,11 +4781,7 @@ void GLCanvas3D::_render_thumbnail_legacy(ThumbnailData& thumbnail_data, unsigne #endif // ENABLE_THUMBNAIL_GENERATOR_DEBUG_OUTPUT // restore the default framebuffer size to avoid flickering on the 3D scene -#if ENABLE_RAYCAST_PICKING wxGetApp().plater()->get_camera().apply_viewport(); -#else - wxGetApp().plater()->get_camera().apply_viewport(0, 0, cnv_size.get_width(), cnv_size.get_height()); -#endif // ENABLE_RAYCAST_PICKING } bool GLCanvas3D::_init_toolbars() @@ -5279,7 +5248,6 @@ void GLCanvas3D::_refresh_if_shown_on_screen() } } -#if ENABLE_RAYCAST_PICKING void GLCanvas3D::_picking_pass() { if (!m_picking_enabled || m_mouse.dragging || m_mouse.position == Vec2d(DBL_MAX, DBL_MAX) || m_gizmos.is_dragging()) { @@ -5365,12 +5333,17 @@ void GLCanvas3D::_picking_pass() default: { break; } } - auto add_strings_row_to_table = [&imgui](const std::string& col_1, const ImVec4& col_1_color, const std::string& col_2, const ImVec4& col_2_color) { + auto add_strings_row_to_table = [&imgui](const std::string& col_1, const ImVec4& col_1_color, const std::string& col_2, const ImVec4& col_2_color, + const std::string& col_3 = "", const ImVec4& col_3_color = ImGui::GetStyleColorVec4(ImGuiCol_Text)) { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); imgui.text_colored(col_1_color, col_1.c_str()); ImGui::TableSetColumnIndex(1); imgui.text_colored(col_2_color, col_2.c_str()); + if (!col_3.empty()) { + ImGui::TableSetColumnIndex(2); + imgui.text_colored(col_3_color, col_3.c_str()); + } }; char buf[1024]; @@ -5399,85 +5372,24 @@ void GLCanvas3D::_picking_pass() add_strings_row_to_table("Gizmo elements", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text)); ImGui::EndTable(); } + + std::vector>* gizmo_raycasters = m_scene_raycaster.get_raycasters(SceneRaycaster::EType::Gizmo); + if (gizmo_raycasters != nullptr && !gizmo_raycasters->empty()) { + ImGui::Separator(); + imgui.text("Gizmo raycasters IDs:"); + if (ImGui::BeginTable("GizmoRaycasters", 3)) { + for (size_t i = 0; i < gizmo_raycasters->size(); ++i) { + add_strings_row_to_table(std::to_string(i), ImGuiWrapper::COL_ORANGE_LIGHT, + std::to_string(SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, (*gizmo_raycasters)[i]->get_id())), ImGui::GetStyleColorVec4(ImGuiCol_Text), + to_string(Geometry::Transformation((*gizmo_raycasters)[i]->get_transform()).get_offset()), ImGui::GetStyleColorVec4(ImGuiCol_Text)); + } + ImGui::EndTable(); + } + } + imgui.end(); #endif // ENABLE_RAYCAST_PICKING_DEBUG } -#else -void GLCanvas3D::_picking_pass() -{ - if (m_picking_enabled && !m_mouse.dragging && m_mouse.position != Vec2d(DBL_MAX, DBL_MAX) && !m_gizmos.is_dragging()) { - m_hover_volume_idxs.clear(); - - // Render the object for picking. - // FIXME This cannot possibly work in a multi - sampled context as the color gets mangled by the anti - aliasing. - // Better to use software ray - casting on a bounding - box hierarchy. - - if (m_multisample_allowed) - // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. - glsafe(::glDisable(GL_MULTISAMPLE)); - - glsafe(::glDisable(GL_BLEND)); - glsafe(::glEnable(GL_DEPTH_TEST)); - - glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); - -#if !ENABLE_LEGACY_OPENGL_REMOVAL - m_camera_clipping_plane = m_gizmos.get_clipping_plane(); - if (m_camera_clipping_plane.is_active()) { - ::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_camera_clipping_plane.get_data().data()); - ::glEnable(GL_CLIP_PLANE0); - } -#endif // !ENABLE_LEGACY_OPENGL_REMOVAL - _render_volumes_for_picking(); -#if !ENABLE_LEGACY_OPENGL_REMOVAL - if (m_camera_clipping_plane.is_active()) - ::glDisable(GL_CLIP_PLANE0); -#endif // !ENABLE_LEGACY_OPENGL_REMOVAL - -#if ENABLE_LEGACY_OPENGL_REMOVAL - const Camera& camera = wxGetApp().plater()->get_camera(); - _render_bed_for_picking(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward()); -#else - _render_bed_for_picking(!wxGetApp().plater()->get_camera().is_looking_downward()); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL - - m_gizmos.render_current_gizmo_for_picking_pass(); - - if (m_multisample_allowed) - glsafe(::glEnable(GL_MULTISAMPLE)); - - int volume_id = -1; - int gizmo_id = -1; - - std::array color = { 0, 0, 0, 0 }; - const Size& cnv_size = get_canvas_size(); - bool inside = 0 <= m_mouse.position(0) && m_mouse.position(0) < cnv_size.get_width() && 0 <= m_mouse.position(1) && m_mouse.position(1) < cnv_size.get_height(); - if (inside) { - glsafe(::glReadPixels(m_mouse.position(0), cnv_size.get_height() - m_mouse.position.y() - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color.data())); - if (picking_checksum_alpha_channel(color[0], color[1], color[2]) == color[3]) { - // Only non-interpolated colors are valid, those have their lowest three bits zeroed. - // we reserve color = (0,0,0) for occluders (as the printbed) - // volumes' id are shifted by 1 - // see: _render_volumes_for_picking() - unsigned int id = picking_encode(color[0], color[1], color[2]); - volume_id = id - 1; - // gizmos' id are instead properly encoded by the color - gizmo_id = id; - } - } - if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) { - // do not add the volume id if any gizmo is active and CTRL is pressed - if (m_gizmos.get_current_type() == GLGizmosManager::EType::Undefined || !wxGetKeyState(WXK_CONTROL)) - m_hover_volume_idxs.emplace_back(volume_id); - m_gizmos.set_hover_id(-1); - } - else - m_gizmos.set_hover_id(inside && (unsigned int)gizmo_id <= GLGizmoBase::BASE_ID ? ((int)GLGizmoBase::BASE_ID - gizmo_id) : -1); - - _update_volumes_hover_state(); - } -} -#endif // ENABLE_RAYCAST_PICKING void GLCanvas3D::_rectangular_selection_picking_pass() { @@ -5486,7 +5398,6 @@ void GLCanvas3D::_rectangular_selection_picking_pass() std::set idxs; if (m_picking_enabled) { -#if ENABLE_RAYCAST_PICKING const size_t width = std::max(m_rectangle_selection.get_width(), 1); const size_t height = std::max(m_rectangle_selection.get_height(), 1); @@ -5540,7 +5451,6 @@ void GLCanvas3D::_rectangular_selection_picking_pass() use_framebuffer = false; } } -#endif // ENABLE_RAYCAST_PICKING if (m_multisample_allowed) // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. @@ -5551,7 +5461,6 @@ void GLCanvas3D::_rectangular_selection_picking_pass() glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); -#if ENABLE_RAYCAST_PICKING const Camera& main_camera = wxGetApp().plater()->get_camera(); Camera framebuffer_camera; framebuffer_camera.set_type(main_camera.get_type()); @@ -5585,16 +5494,8 @@ void GLCanvas3D::_rectangular_selection_picking_pass() } _render_volumes_for_picking(*camera); -#else - _render_volumes_for_picking(); -#endif // ENABLE_RAYCAST_PICKING #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING _render_bed_for_picking(camera->get_view_matrix(), camera->get_projection_matrix(), !camera->is_looking_downward()); -#else - const Camera& camera = wxGetApp().plater()->get_camera(); - _render_bed_for_picking(camera.get_view_matrix(), camera.get_projection_matrix(), !camera.is_looking_downward()); -#endif // ENABLE_RAYCAST_PICKING #else _render_bed_for_picking(!wxGetApp().plater()->get_camera().is_looking_downward()); #endif // ENABLE_LEGACY_OPENGL_REMOVAL @@ -5602,20 +5503,10 @@ void GLCanvas3D::_rectangular_selection_picking_pass() if (m_multisample_allowed) glsafe(::glEnable(GL_MULTISAMPLE)); -#if ENABLE_RAYCAST_PICKING const size_t px_count = width * height; const size_t left = use_framebuffer ? 0 : (size_t)m_rectangle_selection.get_left(); const size_t top = use_framebuffer ? 0 : (size_t)get_canvas_size().get_height() - (size_t)m_rectangle_selection.get_top(); -#else - int width = std::max((int)m_rectangle_selection.get_width(), 1); - int height = std::max((int)m_rectangle_selection.get_height(), 1); - int px_count = width * height; - - int left = (int)m_rectangle_selection.get_left(); - int top = get_canvas_size().get_height() - (int)m_rectangle_selection.get_top(); - if (left >= 0 && top >= 0) { -#endif // ENABLE_RAYCAST_PICKING #define USE_PARALLEL 1 #if USE_PARALLEL struct Pixel @@ -5649,15 +5540,13 @@ void GLCanvas3D::_rectangular_selection_picking_pass() std::vector frame(4 * px_count); glsafe(::glReadPixels(left, top, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void*)frame.data())); - for (int i = 0; i < px_count; ++i) - { + for (int i = 0; i < px_count; ++i) { int px_id = 4 * i; int volume_id = frame[px_id] + (frame[px_id + 1] << 8) + (frame[px_id + 2] << 16); if (0 <= volume_id && volume_id < (int)m_volumes.volumes.size()) idxs.insert(volume_id); } #endif // USE_PARALLEL -#if ENABLE_RAYCAST_PICKING if (camera != &main_camera) main_camera.apply_viewport(); @@ -5678,9 +5567,6 @@ void GLCanvas3D::_rectangular_selection_picking_pass() if (render_tex != 0) glsafe(::glDeleteTextures(1, &render_tex)); -#else - } -#endif // ENABLE_RAYCAST_PICKING } m_hover_volume_idxs.assign(idxs.begin(), idxs.end()); @@ -6083,11 +5969,7 @@ void GLCanvas3D::_render_overlays() #endif // !ENABLE_LEGACY_OPENGL_REMOVAL } -#if ENABLE_RAYCAST_PICKING void GLCanvas3D::_render_volumes_for_picking(const Camera& camera) const -#else -void GLCanvas3D::_render_volumes_for_picking() const -#endif // ENABLE_RAYCAST_PICKING { #if ENABLE_LEGACY_OPENGL_REMOVAL GLShaderProgram* shader = wxGetApp().get_shader("flat_clip"); @@ -6103,11 +5985,7 @@ void GLCanvas3D::_render_volumes_for_picking() const glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING const Transform3d& view_matrix = camera.get_view_matrix(); -#else - const Transform3d& view_matrix = wxGetApp().plater()->get_camera().get_view_matrix(); -#endif // ENABLE_RAYCAST_PICKING for (size_t type = 0; type < 2; ++ type) { GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::ERenderType::Opaque : GLVolumeCollection::ERenderType::Transparent, view_matrix); for (const GLVolumeWithIdAndZ& volume : to_render) @@ -6119,12 +5997,7 @@ void GLCanvas3D::_render_volumes_for_picking() const #if ENABLE_LEGACY_OPENGL_REMOVAL volume.first->model.set_color(picking_decode(id)); shader->start_using(); -#if ENABLE_RAYCAST_PICKING shader->set_uniform("view_model_matrix", view_matrix * volume.first->world_matrix()); -#else - const Camera& camera = wxGetApp().plater()->get_camera(); - shader->set_uniform("view_model_matrix", camera.get_view_matrix() * volume.first->world_matrix()); -#endif // ENABLE_RAYCAST_PICKING shader->set_uniform("projection_matrix", camera.get_projection_matrix()); shader->set_uniform("volume_world_matrix", volume.first->world_matrix()); shader->set_uniform("z_range", m_volumes.get_z_range()); @@ -6692,7 +6565,6 @@ Vec3d GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) if (m_canvas == nullptr) return Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); -#if ENABLE_RAYCAST_PICKING if (z == nullptr) { const SceneRaycaster::HitResult hit = m_scene_raycaster.hit(mouse_pos.cast(), wxGetApp().plater()->get_camera(), nullptr); return hit.is_valid() ? hit.position.cast() : _mouse_to_bed_3d(mouse_pos); @@ -6704,23 +6576,6 @@ Vec3d GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z) igl::unproject(Vec3d(mouse_pos.x(), viewport[3] - mouse_pos.y(), *z), camera.get_view_matrix().matrix(), camera.get_projection_matrix().matrix(), viewport, out); return out; } -#else - const Camera& camera = wxGetApp().plater()->get_camera(); - const Matrix4d modelview = camera.get_view_matrix().matrix(); - const Matrix4d projection = camera.get_projection_matrix().matrix(); - const Vec4i viewport(camera.get_viewport().data()); - - const int y = viewport[3] - mouse_pos.y(); - float mouse_z; - if (z == nullptr) - glsafe(::glReadPixels(mouse_pos.x(), y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, (void*)&mouse_z)); - else - mouse_z = *z; - - Vec3d out; - igl::unproject(Vec3d(mouse_pos.x(), y, mouse_z), modelview, projection, viewport, out); - return out; -#endif // ENABLE_RAYCAST_PICKING } Vec3d GLCanvas3D::_mouse_to_bed_3d(const Point& mouse_pos) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index a519a26a19..b24a15bbef 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -16,9 +16,7 @@ #include "libslic3r/GCode/GCodeProcessor.hpp" #include "GCodeViewer.hpp" #include "Camera.hpp" -#if ENABLE_RAYCAST_PICKING #include "SceneRaycaster.hpp" -#endif // ENABLE_RAYCAST_PICKING #include "GUI_Utils.hpp" #include "libslic3r/Slicing.hpp" @@ -483,9 +481,7 @@ public: private: wxGLCanvas* m_canvas; wxGLContext* m_context; -#if ENABLE_RAYCAST_PICKING SceneRaycaster m_scene_raycaster; -#endif // ENABLE_RAYCAST_PICKING Bed3D &m_bed; #if ENABLE_RETINA_GL std::unique_ptr m_retina_helper; @@ -669,7 +665,6 @@ public: bool init(); void post_event(wxEvent &&event); -#if ENABLE_RAYCAST_PICKING std::shared_ptr add_raycaster_for_picking(SceneRaycaster::EType type, int id, const MeshRaycaster& raycaster, const Transform3d& trafo = Transform3d::Identity(), bool use_back_faces = false) { return m_scene_raycaster.add_raycaster(type, id, raycaster, trafo, use_back_faces); @@ -688,7 +683,6 @@ public: void set_raycaster_gizmos_on_top(bool value) { m_scene_raycaster.set_gizmos_on_top(value); } -#endif // ENABLE_RAYCAST_PICKING void set_as_dirty(); void requires_check_outside_state() { m_requires_check_outside_state = true; } @@ -1008,11 +1002,7 @@ private: #endif // ENABLE_RENDER_SELECTION_CENTER void _check_and_update_toolbar_icon_scale(); void _render_overlays(); -#if ENABLE_RAYCAST_PICKING void _render_volumes_for_picking(const Camera& camera) const; -#else - void _render_volumes_for_picking() const; -#endif // ENABLE_RAYCAST_PICKING void _render_current_gizmo() const; void _render_gizmos_overlay(); void _render_main_toolbar(); diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp index a2c93184b8..d4b4741175 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.cpp +++ b/src/slic3r/GUI/GLSelectionRectangle.cpp @@ -30,21 +30,10 @@ namespace GUI { m_end_corner = mouse_position; } -#if ENABLE_RAYCAST_PICKING std::vector GLSelectionRectangle::contains(const std::vector& points) const -#else - std::vector GLSelectionRectangle::stop_dragging(const GLCanvas3D& canvas, const std::vector& points) -#endif // ENABLE_RAYCAST_PICKING { std::vector out; -#if !ENABLE_RAYCAST_PICKING - if (!is_dragging()) - return out; - - m_state = EState::Off; -#endif // !ENABLE_RAYCAST_PICKING - // bounding box created from the rectangle corners - will take care of order of the corners const BoundingBox rectangle(Points{ Point(m_start_corner.cast()), Point(m_end_corner.cast()) }); diff --git a/src/slic3r/GUI/GLSelectionRectangle.hpp b/src/slic3r/GUI/GLSelectionRectangle.hpp index 16eab222ae..ac8abb6aae 100644 --- a/src/slic3r/GUI/GLSelectionRectangle.hpp +++ b/src/slic3r/GUI/GLSelectionRectangle.hpp @@ -26,15 +26,9 @@ public: // To be called on mouse move. void dragging(const Vec2d& mouse_position); -#if ENABLE_RAYCAST_PICKING // Given a vector of points in world coordinates, the function returns indices of those // that are in the rectangle. std::vector contains(const std::vector& points) const; -#else - // Given a vector of points in world coordinates, the function returns indices of those - // that are in the rectangle. It then disables the rectangle. - std::vector stop_dragging(const GLCanvas3D& canvas, const std::vector& points); -#endif // ENABLE_RAYCAST_PICKING // Disables the rectangle. void stop_dragging(); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 127d97caa2..8c15464100 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1880,6 +1880,7 @@ bool ObjectList::del_subobject_item(wxDataViewItem& item) wxDataViewItem parent = m_objects_model->GetParent(item); + InfoItemType item_info_type = m_objects_model->GetInfoItemType(item); if (type & itSettings) del_settings_from_config(parent); else if (type & itInstanceRoot && obj_idx != -1) @@ -1889,7 +1890,7 @@ bool ObjectList::del_subobject_item(wxDataViewItem& item) else if (type & itLayer && obj_idx != -1) del_layer_from_object(obj_idx, m_objects_model->GetLayerRangeByItem(item)); else if (type & itInfo && obj_idx != -1) - del_info_item(obj_idx, m_objects_model->GetInfoItemType(item)); + del_info_item(obj_idx, item_info_type); else if (idx == -1 || !del_subobject_from_object(obj_idx, idx, type)) return false; @@ -1898,9 +1899,12 @@ bool ObjectList::del_subobject_item(wxDataViewItem& item) const std::string& icon_name = get_warning_icon_name(object(obj_idx)->get_object_stl_stats()); m_objects_model->UpdateWarningIcon(parent, icon_name); } - m_objects_model->Delete(item); - update_info_items(obj_idx); + if (!(type & itInfo) || item_info_type != InfoItemType::CutConnectors) { + // Connectors Item is already updated/deleted inside the del_info_item() + m_objects_model->Delete(item); + update_info_items(obj_idx); + } return true; } @@ -1926,7 +1930,10 @@ void ObjectList::del_info_item(const int obj_idx, InfoItemType type) break; case InfoItemType::CutConnectors: - show_error(nullptr, _L("Connectors cannot be deleted from cut object.")); + if (!del_from_cut_object(true)) { + // there is no need to post EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS if nothing was changed + return; + } break; case InfoItemType::MmuSegmentation: @@ -2018,6 +2025,38 @@ void ObjectList::del_layers_from_object(const int obj_idx) changed_object(obj_idx); } +bool ObjectList::del_from_cut_object(bool is_cut_connector, bool is_model_part/* = false*/, bool is_negative_volume/* = false*/) +{ + const long buttons_style = is_cut_connector ? (wxYES | wxNO | wxCANCEL) : (wxYES | wxCANCEL); + + const wxString title = is_cut_connector ? _L("Delete connector from object which is a part of cut") : + is_model_part ? _L("Delete solid part from object which is a part of cut") : + is_negative_volume ? _L("Delete negative volume from object which is a part of cut") : ""; + + const wxString msg_end = is_cut_connector ? ("\n" + _L("To save cut correspondence you can delete all connectors from all related objects.")) : ""; + + InfoDialog dialog(wxGetApp().plater(), title, + _L("This action will break a cut correspondence.\n" + "After that PrusaSlicer can't guarantee model consistency.\n" + "\n" + "To manipulate with solid parts or negative volumes you have to invalidate cut infornation first." + msg_end ), + false, buttons_style | wxCANCEL_DEFAULT | wxICON_WARNING); + + dialog.SetButtonLabel(wxID_YES, _L("Invalidate cut info")); + if (is_cut_connector) + dialog.SetButtonLabel(wxID_NO, _L("Delete all connectors")); + + const int answer = dialog.ShowModal(); + if (answer == wxID_CANCEL) + return false; + + if (answer == wxID_YES) + invalidate_cut_info_for_selection(); + else if (answer == wxID_NO) + delete_all_connectors_for_selection(); + return true; +} + bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, const int type) { assert(idx >= 0); @@ -2039,15 +2078,10 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con Slic3r::GUI::show_error(nullptr, _L("From Object List You can't delete the last solid part from object.")); return false; } - if (object->is_cut()) { - if (volume->is_model_part()) { - Slic3r::GUI::show_error(nullptr, _L("Solid part cannot be deleted from cut object.")); - return false; - } - if (volume->is_negative_volume()) { - Slic3r::GUI::show_error(nullptr, _L("Negative volume cannot be deleted from cut object.")); - return false; - } + if (object->is_cut() && (volume->is_model_part() || volume->is_negative_volume())) { + del_from_cut_object(volume->is_cut_connector(), volume->is_model_part(), volume->is_negative_volume()); + // in any case return false to break the deletion + return false; } take_snapshot(_L("Delete Subobject")); @@ -2489,6 +2523,7 @@ bool ObjectList::has_selected_cut_object() const return false; } + void ObjectList::invalidate_cut_info_for_selection() { const wxDataViewItem item = GetSelection(); @@ -2499,27 +2534,61 @@ void ObjectList::invalidate_cut_info_for_selection() } } -void ObjectList::invalidate_cut_info_for_object(size_t obj_idx) +void ObjectList::invalidate_cut_info_for_object(int obj_idx) { - ModelObject* init_obj = object(int(obj_idx)); + ModelObject* init_obj = object(obj_idx); if (!init_obj->is_cut()) return; take_snapshot(_L("Invalidate cut info")); - auto invalidate_cut = [this](size_t obj_idx) { - object(int(obj_idx))->invalidate_cut(); - update_info_items(obj_idx); - add_volumes_to_object_in_list(obj_idx); - }; - + const CutObjectBase cut_id = init_obj->cut_id; // invalidate cut for related objects (which have the same cut_id) for (size_t idx = 0; idx < m_objects->size(); idx++) - if (ModelObject* obj = object(idx); obj != init_obj && obj->cut_id.is_equal(init_obj->cut_id)) - invalidate_cut(idx); + if (ModelObject* obj = object(int(idx)); obj->cut_id.is_equal(cut_id)) { + obj->invalidate_cut(); + update_info_items(idx); + add_volumes_to_object_in_list(idx); + } - // invalidate own cut information - invalidate_cut(size_t(obj_idx)); + update_lock_icons_for_model(); +} + +void ObjectList::delete_all_connectors_for_selection() +{ + const wxDataViewItem item = GetSelection(); + if (item) { + const int obj_idx = m_objects_model->GetObjectIdByItem(item); + if (obj_idx >= 0) + delete_all_connectors_for_object(size_t(obj_idx)); + } +} + +void ObjectList::delete_all_connectors_for_object(int obj_idx) +{ + ModelObject* init_obj = object(obj_idx); + if (!init_obj->is_cut()) + return; + + take_snapshot(_L("Delete all connectors")); + + const CutObjectBase cut_id = init_obj->cut_id; + // Delete all connectors for related objects (which have the same cut_id) + Model& model = wxGetApp().plater()->model(); + for (int idx = int(m_objects->size())-1; idx >= 0; idx--) + if (ModelObject* obj = object(idx); obj->cut_id.is_equal(cut_id)) { + obj->delete_connectors(); + + if (obj->volumes.empty() || !obj->has_solid_mesh()) { + model.delete_object(idx); + m_objects_model->Delete(m_objects_model->GetItemById(idx)); + continue; + } + + update_info_items(idx); + add_volumes_to_object_in_list(idx); + changed_object(int(idx)); + } update_lock_icons_for_model(); } @@ -3044,6 +3113,7 @@ bool ObjectList::delete_from_model_and_list(const std::vector& it return false; m_prevent_list_events = true; + ScopeGuard sg_prevent_list_events = ScopeGuard([this]() { m_prevent_list_events = false; }); std::set modified_objects_ids; for (std::vector::const_reverse_iterator item = items_for_delete.rbegin(); item != items_for_delete.rend(); ++item) { @@ -3059,7 +3129,7 @@ bool ObjectList::delete_from_model_and_list(const std::vector& it } else { if (!del_subobject_from_object(item->obj_idx, item->sub_obj_idx, item->type)) - continue; + return false;// continue; if (item->type&itVolume) { m_objects_model->Delete(m_objects_model->GetItemByVolumeId(item->obj_idx, item->sub_obj_idx)); ModelObject* obj = object(item->obj_idx); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 9cd3dc8e17..d2965c77e3 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -266,6 +266,7 @@ public: void del_instances_from_object(const int obj_idx); void del_layer_from_object(const int obj_idx, const t_layer_height_range& layer_range); void del_layers_from_object(const int obj_idx); + bool del_from_cut_object(bool is_connector, bool is_model_part = false, bool is_negative_volume = false); bool del_subobject_from_object(const int obj_idx, const int idx, const int type); void del_info_item(const int obj_idx, InfoItemType type); void split(); @@ -282,7 +283,9 @@ public: bool can_split_instances(); bool has_selected_cut_object() const; void invalidate_cut_info_for_selection(); - void invalidate_cut_info_for_object(size_t obj_idx); + void invalidate_cut_info_for_object(int obj_idx); + void delete_all_connectors_for_selection(); + void delete_all_connectors_for_object(int obj_idx); bool can_merge_to_multipart_object() const; bool can_merge_to_single_object() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index f4200f8343..a3829fc219 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -18,29 +18,16 @@ const float GLGizmoBase::Grabber::SizeFactor = 0.05f; const float GLGizmoBase::Grabber::MinHalfSize = 1.5f; const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; -#if ENABLE_RAYCAST_PICKING PickingModel GLGizmoBase::Grabber::s_cube; PickingModel GLGizmoBase::Grabber::s_cone; -#else -GLModel GLGizmoBase::Grabber::s_cube; -GLModel GLGizmoBase::Grabber::s_cone; -#endif // ENABLE_RAYCAST_PICKING GLGizmoBase::Grabber::~Grabber() { -#if ENABLE_RAYCAST_PICKING if (s_cube.model.is_initialized()) s_cube.model.reset(); if (s_cone.model.is_initialized()) s_cone.model.reset(); -#else - if (s_cube.is_initialized()) - s_cube.reset(); - - if (s_cone.is_initialized()) - s_cone.reset(); -#endif // ENABLE_RAYCAST_PICKING } float GLGizmoBase::Grabber::get_half_size(float size) const @@ -53,7 +40,6 @@ float GLGizmoBase::Grabber::get_dragging_half_size(float size) const return get_half_size(size) * DraggingScaleFactor; } -#if ENABLE_RAYCAST_PICKING void GLGizmoBase::Grabber::register_raycasters_for_picking(int id) { picking_id = id; @@ -66,13 +52,8 @@ void GLGizmoBase::Grabber::unregister_raycasters_for_picking() picking_id = -1; raycasters = { nullptr }; } -#endif // ENABLE_RAYCAST_PICKING -#if ENABLE_RAYCAST_PICKING void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color) -#else -void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking) -#endif // ENABLE_RAYCAST_PICKING { #if ENABLE_LEGACY_OPENGL_REMOVAL GLShaderProgram* shader = wxGetApp().get_current_shader(); @@ -80,69 +61,41 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo return; #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING if (!s_cube.model.is_initialized()) { -#else - if (!s_cube.is_initialized()) { -#endif // ENABLE_RAYCAST_PICKING // This cannot be done in constructor, OpenGL is not yet // initialized at that point (on Linux at least). indexed_triangle_set its = its_make_cube(1.0, 1.0, 1.0); its_translate(its, -0.5f * Vec3f::Ones()); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING s_cube.model.init_from(its); s_cube.mesh_raycaster = std::make_unique(std::make_shared(std::move(its))); -#else - s_cube.init_from(its); -#endif // ENABLE_RAYCAST_PICKING #else s_cube.init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } }); #endif // ENABLE_LEGACY_OPENGL_REMOVAL } -#if ENABLE_RAYCAST_PICKING if (!s_cone.model.is_initialized()) { indexed_triangle_set its = its_make_cone(0.375, 1.5, double(PI) / 18.0); s_cone.model.init_from(its); s_cone.mesh_raycaster = std::make_unique(std::make_shared(std::move(its))); } -#else - if (!s_cone.is_initialized()) - s_cone.init_from(its_make_cone(0.375, 1.5, double(PI) / 18.0)); -#endif // ENABLE_RAYCAST_PICKING const float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING s_cube.model.set_color(render_color); s_cone.model.set_color(render_color); -#else - s_cube.set_color(render_color); - s_cone.set_color(render_color); -#endif // ENABLE_RAYCAST_PICKING const Camera& camera = wxGetApp().plater()->get_camera(); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); -#if ENABLE_RAYCAST_PICKING const Transform3d& view_matrix = camera.get_view_matrix(); const Matrix3d view_matrix_no_offset = view_matrix.matrix().block(0, 0, 3, 3); std::vector elements_matrices(GRABBER_ELEMENTS_MAX_COUNT, Transform3d::Identity()); elements_matrices[0] = matrix * Geometry::translation_transform(center) * Geometry::rotation_transform(angles) * Geometry::scale_transform(2.0 * half_size); Transform3d view_model_matrix = view_matrix * elements_matrices[0]; -#else - const Transform3d& view_matrix = camera.get_view_matrix(); - const Transform3d model_matrix = matrix * Geometry::translation_transform(center) * Geometry::rotation_transform(angles) * Geometry::scale_transform(2.0 * half_size); - const Transform3d view_model_matrix = view_matrix * model_matrix; -#endif // ENABLE_RAYCAST_PICKING shader->set_uniform("view_model_matrix", view_model_matrix); -#if ENABLE_RAYCAST_PICKING Matrix3d view_normal_matrix = view_matrix_no_offset * elements_matrices[0].matrix().block(0, 0, 3, 3).inverse().transpose(); -#else - const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); -#endif // ENABLE_RAYCAST_PICKING shader->set_uniform("view_normal_matrix", view_normal_matrix); #else s_cube.set_color(-1, render_color); @@ -154,7 +107,6 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0)); glsafe(::glScaled(2.0 * half_size, 2.0 * half_size, 2.0 * half_size)); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING s_cube.model.render(); auto render_extension = [&view_matrix, &view_matrix_no_offset, shader](const Transform3d& matrix) { @@ -164,64 +116,31 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo shader->set_uniform("view_normal_matrix", view_normal_matrix); s_cone.model.render(); }; -#else - s_cube.render(); -#endif // ENABLE_RAYCAST_PICKING #if ENABLE_LEGACY_OPENGL_REMOVAL if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) { -#if ENABLE_RAYCAST_PICKING elements_matrices[1] = elements_matrices[0] * Geometry::translation_transform(Vec3d::UnitX()) * Geometry::rotation_transform({ 0.0, 0.5 * double(PI), 0.0 }); render_extension(elements_matrices[1]); -#else - shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::translation_transform(Vec3d::UnitX()) * Geometry::rotation_transform({ 0.0, 0.5 * double(PI), 0.0 })); - s_cone.render(); -#endif // ENABLE_RAYCAST_PICKING } if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegX)) != 0) { -#if ENABLE_RAYCAST_PICKING elements_matrices[2] = elements_matrices[0] * Geometry::translation_transform(-Vec3d::UnitX()) * Geometry::rotation_transform({ 0.0, -0.5 * double(PI), 0.0 }); render_extension(elements_matrices[2]); -#else - shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::translation_transform(-Vec3d::UnitX()) * Geometry::rotation_transform({ 0.0, -0.5 * double(PI), 0.0 })); - s_cone.render(); -#endif // ENABLE_RAYCAST_PICKING } if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosY)) != 0) { -#if ENABLE_RAYCAST_PICKING elements_matrices[3] = elements_matrices[0] * Geometry::translation_transform(Vec3d::UnitY()) * Geometry::rotation_transform({ -0.5 * double(PI), 0.0, 0.0 }); render_extension(elements_matrices[3]); -#else - shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::translation_transform(Vec3d::UnitY()) * Geometry::rotation_transform({ -0.5 * double(PI), 0.0, 0.0 })); - s_cone.render(); -#endif // ENABLE_RAYCAST_PICKING } if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegY)) != 0) { -#if ENABLE_RAYCAST_PICKING elements_matrices[4] = elements_matrices[0] * Geometry::translation_transform(-Vec3d::UnitY()) * Geometry::rotation_transform({ 0.5 * double(PI), 0.0, 0.0 }); render_extension(elements_matrices[4]); -#else - shader->set_uniform("view_model_matrix", view_model_matrix* Geometry::translation_transform(-Vec3d::UnitY())* Geometry::rotation_transform({ 0.5 * double(PI), 0.0, 0.0 })); - s_cone.render(); -#endif // ENABLE_RAYCAST_PICKING } if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosZ)) != 0) { -#if ENABLE_RAYCAST_PICKING elements_matrices[5] = elements_matrices[0] * Geometry::translation_transform(Vec3d::UnitZ()); render_extension(elements_matrices[5]); -#else - shader->set_uniform("view_model_matrix", view_model_matrix* Geometry::translation_transform(Vec3d::UnitZ())); - s_cone.render(); -#endif // ENABLE_RAYCAST_PICKING } if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegZ)) != 0) { -#if ENABLE_RAYCAST_PICKING elements_matrices[6] = elements_matrices[0] * Geometry::translation_transform(-Vec3d::UnitZ()) * Geometry::rotation_transform({ double(PI), 0.0, 0.0 }); - render_extension(elements_matrices[6]); -#else - shader->set_uniform("view_model_matrix", view_model_matrix* Geometry::translation_transform(-Vec3d::UnitZ())* Geometry::rotation_transform({ double(PI), 0.0, 0.0 })); - s_cone.render(); -#endif // ENABLE_RAYCAST_PICKING + render_extension(elements_matrices[6]); } #else if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) { @@ -270,7 +189,6 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo glsafe(::glPopMatrix()); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING if (raycasters[0] == nullptr) { GLCanvas3D& canvas = *wxGetApp().plater()->canvas3D(); raycasters[0] = canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cube.mesh_raycaster, elements_matrices[0]); @@ -293,7 +211,6 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo raycasters[i]->set_transform(elements_matrices[i]); } } -#endif // ENABLE_RAYCAST_PICKING } GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) @@ -327,7 +244,6 @@ bool GLGizmoBase::update_items_state() return res; } -#if ENABLE_RAYCAST_PICKING void GLGizmoBase::register_grabbers_for_picking() { for (size_t i = 0; i < m_grabbers.size(); ++i) { @@ -341,16 +257,6 @@ void GLGizmoBase::unregister_grabbers_for_picking() m_grabbers[i].unregister_raycasters_for_picking(); } } -#else -ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const -{ - id = BASE_ID - id; - if (m_group_id > -1) - id -= m_group_id; - - return picking_decode(id); -} -#endif // ENABLE_RAYCAST_PICKING void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const { @@ -371,29 +277,6 @@ void GLGizmoBase::render_grabbers(float size) const shader->stop_using(); } -#if !ENABLE_RAYCAST_PICKING -void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const -{ -#if ENABLE_LEGACY_OPENGL_REMOVAL - GLShaderProgram* shader = wxGetApp().get_shader("flat"); - if (shader != nullptr) { - shader->start_using(); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL - const float mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0); - - for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) { - if (m_grabbers[i].enabled) { - m_grabbers[i].color = picking_color_component(i); - m_grabbers[i].render_for_picking(mean_size); - } - } -#if ENABLE_LEGACY_OPENGL_REMOVAL - shader->stop_using(); - } -#endif // ENABLE_LEGACY_OPENGL_REMOVAL -} -#endif // !ENABLE_RAYCAST_PICKING - // help function to process grabbers // call start_dragging, stop_dragging, on_dragging bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 1d134948d4..3c3f5c287e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -6,10 +6,8 @@ #include "slic3r/GUI/I18N.hpp" #include "slic3r/GUI/GLModel.hpp" -#if ENABLE_RAYCAST_PICKING #include "slic3r/GUI/MeshUtils.hpp" #include "slic3r/GUI/SceneRaycaster.hpp" -#endif // ENABLE_RAYCAST_PICKING #include @@ -73,44 +71,26 @@ protected: #endif // ENABLE_LEGACY_OPENGL_REMOVAL ColorRGBA color{ ColorRGBA::WHITE() }; EGrabberExtension extensions{ EGrabberExtension::None }; -#if ENABLE_RAYCAST_PICKING // the picking id shared by all the elements int picking_id{ -1 }; std::array, GRABBER_ELEMENTS_MAX_COUNT> raycasters = { nullptr }; -#endif // ENABLE_RAYCAST_PICKING Grabber() = default; ~Grabber(); -#if ENABLE_RAYCAST_PICKING void render(bool hover, float size) { render(size, hover ? complementary(color) : color); } -#else - void render(bool hover, float size) { render(size, hover ? complementary(color) : color, false); } - void render_for_picking(float size) { render(size, color, true); } -#endif // ENABLE_RAYCAST_PICKING float get_half_size(float size) const; float get_dragging_half_size(float size) const; -#if ENABLE_RAYCAST_PICKING void register_raycasters_for_picking(int id); void unregister_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING private: -#if ENABLE_RAYCAST_PICKING void render(float size, const ColorRGBA& render_color); -#else - void render(float size, const ColorRGBA& render_color, bool picking); -#endif // ENABLE_RAYCAST_PICKING -#if ENABLE_RAYCAST_PICKING static PickingModel s_cube; static PickingModel s_cone; -#else - static GLModel s_cube; - static GLModel s_cone; -#endif // ENABLE_RAYCAST_PICKING }; public: @@ -186,9 +166,6 @@ public: bool update_items_state(); void render() { on_render(); } -#if !ENABLE_RAYCAST_PICKING - void render_for_picking() { on_render_for_picking(); } -#endif // !ENABLE_RAYCAST_PICKING void render_input_window(float x, float y, float bottom_limit); /// @@ -210,10 +187,8 @@ public: /// Return True when use the information and don't want to propagate it otherwise False. virtual bool on_mouse(const wxMouseEvent &mouse_event) { return false; } -#if ENABLE_RAYCAST_PICKING void register_raycasters_for_picking() { register_grabbers_for_picking(); on_register_raycasters_for_picking(); } void unregister_raycasters_for_picking() { unregister_grabbers_for_picking(); on_unregister_raycasters_for_picking(); } -#endif // ENABLE_RAYCAST_PICKING virtual bool is_in_editing_mode() const { return false; } virtual bool is_selection_rectangle_dragging() const { return false; } @@ -237,27 +212,15 @@ protected: virtual void on_dragging(const UpdateData& data) {} virtual void on_render() = 0; -#if !ENABLE_RAYCAST_PICKING - virtual void on_render_for_picking() = 0; -#endif // !ENABLE_RAYCAST_PICKING virtual void on_render_input_window(float x, float y, float bottom_limit) {} -#if ENABLE_RAYCAST_PICKING void register_grabbers_for_picking(); void unregister_grabbers_for_picking(); virtual void on_register_raycasters_for_picking() {} virtual void on_unregister_raycasters_for_picking() {} -#else - // 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) - ColorRGBA picking_color_component(unsigned int id) const; -#endif // ENABLE_RAYCAST_PICKING void render_grabbers(const BoundingBoxf3& box) const; void render_grabbers(float size) const; -#if !ENABLE_RAYCAST_PICKING - void render_grabbers_for_picking(const BoundingBoxf3& box) const; -#endif // !ENABLE_RAYCAST_PICKING std::string format(float value, unsigned int decimals) const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 09a7deba8a..29d578fba9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -1901,14 +1901,15 @@ void GLGizmoCut3D::render_connectors() m_has_invalid_connector = true; render_color = CONNECTOR_ERR_COLOR; } - else if (!m_connectors_editing) + else // default connector color + render_color = connector.attribs.type == CutConnectorType::Dowel ? DOWEL_COLOR : PLAG_COLOR; + + if (!m_connectors_editing) render_color = CONNECTOR_ERR_COLOR; else if (size_t(m_hover_id - m_connectors_group_id) == i) - render_color = connector.attribs.type == CutConnectorType::Dowel ? HOVERED_DOWEL_COLOR : HOVERED_PLAG_COLOR; + render_color = connector.attribs.type == CutConnectorType::Dowel ? HOVERED_DOWEL_COLOR : HOVERED_PLAG_COLOR; else if (m_selected[i]) render_color = connector.attribs.type == CutConnectorType::Dowel ? SELECTED_DOWEL_COLOR : SELECTED_PLAG_COLOR; - else // neither hover nor picking - render_color = connector.attribs.type == CutConnectorType::Dowel ? DOWEL_COLOR : PLAG_COLOR; const Camera& camera = wxGetApp().plater()->get_camera(); if (connector.attribs.type == CutConnectorType::Dowel && @@ -2141,12 +2142,14 @@ bool GLGizmoCut3D::add_connector(CutConnectors& connectors, const Vec2d& mouse_p std::pair pos_and_normal; Vec3d pos_world; if (unproject_on_cut_plane(mouse_position.cast(), pos_and_normal, pos_world)) { - const Vec3d& hit = pos_and_normal.first; + // check if pos is out of enabled clipping plane + if (m_c->object_clipper() && !m_c->object_clipper()->is_projection_inside_cut(pos_world)) + return true; Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add connector"), UndoRedo::SnapshotType::GizmoAction); unselect_all_connectors(); - connectors.emplace_back(hit, m_rotation_m, + connectors.emplace_back(pos_and_normal.first, m_rotation_m, m_connector_size * 0.5f, m_connector_depth_ratio, m_connector_size_tolerance, m_connector_depth_ratio_tolerance, CutConnectorAttributes( CutConnectorType(m_connector_type), @@ -2241,8 +2244,20 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi (action == SLAGizmoEventType::LeftDown || action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::Moving) ) return process_cut_line(action, mouse_position); - if (!m_connectors_editing) + if (!m_connectors_editing) { + if (0 && action == SLAGizmoEventType::LeftDown) { + // disable / enable current contour + std::pair pos_and_normal; + Vec3d pos_world; + if (unproject_on_cut_plane(mouse_position.cast(), pos_and_normal, pos_world)) { + // Following would inform the clipper about the mouse click, so it can + // toggle the respective contour as disabled. + m_c->object_clipper()->pass_mouse_click(pos_world); + return true; + } + } return false; + } CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index 7a853e7187..542aceead0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -600,18 +600,12 @@ void GLGizmoEmboss::on_render() { } } -#if ENABLE_RAYCAST_PICKING void GLGizmoEmboss::on_register_raycasters_for_picking(){ m_rotate_gizmo.register_raycasters_for_picking(); } void GLGizmoEmboss::on_unregister_raycasters_for_picking(){ m_rotate_gizmo.unregister_raycasters_for_picking(); } -#else // !ENABLE_RAYCAST_PICKING -void GLGizmoEmboss::on_render_for_picking() { - m_rotate_gizmo.render_for_picking(); -} -#endif // ENABLE_RAYCAST_PICKING #ifdef SHOW_FINE_POSITION // draw suggested position of window diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp index 092041e96e..fe3ccf73bc 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.hpp @@ -56,12 +56,8 @@ protected: bool on_init() override; std::string on_get_name() const override; void on_render() override; -#if ENABLE_RAYCAST_PICKING virtual void on_register_raycasters_for_picking() override; virtual void on_unregister_raycasters_for_picking() override; -#else // !ENABLE_RAYCAST_PICKING - void on_render_for_picking() override; -#endif // ENABLE_RAYCAST_PICKING void on_render_input_window(float x, float y, float bottom_limit) override; bool on_is_activable() const override { return true; } bool on_is_selectable() const override { return false; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp index ddabec7e61..463eb3182b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -131,14 +131,9 @@ void GLGizmoFlatten::on_render() update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING m_planes_casters[i]->set_transform(model_matrix); m_planes[i].vbo.model.set_color(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR : DEFAULT_PLANE_COLOR); m_planes[i].vbo.model.render(); -#else - m_planes[i].vbo.set_color(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR : DEFAULT_PLANE_COLOR); - m_planes[i].vbo.render(); -#endif // ENABLE_RAYCAST_PICKING #else glsafe(::glColor4fv(i == m_hover_id ? DEFAULT_HOVER_PLANE_COLOR.data() : DEFAULT_PLANE_COLOR.data())); if (m_planes[i].vbo.has_VBOs()) @@ -158,7 +153,6 @@ void GLGizmoFlatten::on_render() #endif // ENABLE_LEGACY_OPENGL_REMOVAL } -#if ENABLE_RAYCAST_PICKING void GLGizmoFlatten::on_register_raycasters_for_picking() { // the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account @@ -183,66 +177,12 @@ void GLGizmoFlatten::on_unregister_raycasters_for_picking() m_parent.set_raycaster_gizmos_on_top(false); m_planes_casters.clear(); } -#else -void GLGizmoFlatten::on_render_for_picking() -{ - const Selection& selection = m_parent.get_selection(); - -#if ENABLE_LEGACY_OPENGL_REMOVAL - GLShaderProgram* shader = wxGetApp().get_shader("flat"); - if (shader == nullptr) - return; - - shader->start_using(); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL - - glsafe(::glDisable(GL_DEPTH_TEST)); - glsafe(::glDisable(GL_BLEND)); - - if (selection.is_single_full_instance() && !wxGetKeyState(WXK_CONTROL)) { - const Transform3d& m = selection.get_first_volume()->get_instance_transformation().get_matrix(); -#if ENABLE_LEGACY_OPENGL_REMOVAL - const Camera& camera = wxGetApp().plater()->get_camera(); - const Transform3d view_model_matrix = camera.get_view_matrix() * - Geometry::translation_transform(selection.get_first_volume()->get_sla_shift_z() * Vec3d::UnitZ()) * m; - - shader->set_uniform("view_model_matrix", view_model_matrix); - shader->set_uniform("projection_matrix", camera.get_projection_matrix()); -#else - glsafe(::glPushMatrix()); - glsafe(::glTranslatef(0.f, 0.f, selection.get_first_volume()->get_sla_shift_z())); - glsafe(::glMultMatrixd(m.data())); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL - if (this->is_plane_update_necessary()) - update_planes(); - for (int i = 0; i < (int)m_planes.size(); ++i) { -#if ENABLE_LEGACY_OPENGL_REMOVAL - m_planes[i].vbo.set_color(picking_color_component(i)); -#else - glsafe(::glColor4fv(picking_color_component(i).data())); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL - m_planes[i].vbo.render(); - } -#if !ENABLE_LEGACY_OPENGL_REMOVAL - glsafe(::glPopMatrix()); -#endif // !ENABLE_LEGACY_OPENGL_REMOVAL - } - - glsafe(::glEnable(GL_CULL_FACE)); - -#if ENABLE_LEGACY_OPENGL_REMOVAL - shader->stop_using(); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL -} -#endif // ENABLE_RAYCAST_PICKING void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) { if (model_object != m_old_model_object) { m_planes.clear(); -#if ENABLE_RAYCAST_PICKING on_unregister_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING } } @@ -259,9 +199,7 @@ void GLGizmoFlatten::update_planes() } ch = ch.convex_hull_3d(); m_planes.clear(); -#if ENABLE_RAYCAST_PICKING on_unregister_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING #if ENABLE_WORLD_COORDINATE const Transform3d inst_matrix = mo->instances.front()->get_matrix_no_offset(); #else @@ -458,7 +396,6 @@ void GLGizmoFlatten::update_planes() // the vertices in order, so triangulation is trivial. for (auto& plane : m_planes) { #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING indexed_triangle_set its; its.vertices.reserve(plane.vertices.size()); its.indices.reserve(plane.vertices.size() / 3); @@ -470,18 +407,6 @@ void GLGizmoFlatten::update_planes() } plane.vbo.model.init_from(its); plane.vbo.mesh_raycaster = std::make_unique(std::make_shared(std::move(its))); -#else - GLModel::Geometry init_data; - init_data.format = { GLModel::Geometry::EPrimitiveType::TriangleFan, GLModel::Geometry::EVertexLayout::P3N3 }; - init_data.reserve_vertices(plane.vertices.size()); - init_data.reserve_indices(plane.vertices.size()); - // vertices + indices - for (size_t i = 0; i < plane.vertices.size(); ++i) { - init_data.add_vertex((Vec3f)plane.vertices[i].cast(), (Vec3f)plane.normal.cast()); - init_data.add_index((unsigned int)i); - } - plane.vbo.init_from(std::move(init_data)); -#endif // ENABLE_RAYCAST_PICKING #else plane.vbo.reserve(plane.vertices.size()); for (const auto& vert : plane.vertices) @@ -496,12 +421,9 @@ void GLGizmoFlatten::update_planes() plane.vertices.shrink_to_fit(); } -#if ENABLE_RAYCAST_PICKING on_register_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING } - bool GLGizmoFlatten::is_plane_update_necessary() const { const ModelObject* mo = m_c->selection_info()->model_object(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp index b4e47d3985..900a3361db 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp @@ -4,9 +4,7 @@ #include "GLGizmoBase.hpp" #if ENABLE_LEGACY_OPENGL_REMOVAL #include "slic3r/GUI/GLModel.hpp" -#if ENABLE_RAYCAST_PICKING #include "slic3r/GUI/MeshUtils.hpp" -#endif // ENABLE_RAYCAST_PICKING #else #include "slic3r/GUI/3DScene.hpp" #endif // ENABLE_LEGACY_OPENGL_REMOVAL @@ -30,19 +28,13 @@ private: struct PlaneData { std::vector vertices; // should be in fact local in update_planes() #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING PickingModel vbo; -#else - GLModel vbo; -#endif // ENABLE_RAYCAST_PICKING #else GLIndexedVertexArray vbo; #endif // ENABLE_LEGACY_OPENGL_REMOVAL Vec3d normal; float area; -#if ENABLE_RAYCAST_PICKING int picking_id{ -1 }; -#endif // ENABLE_RAYCAST_PICKING }; // This holds information to decide whether recalculation is necessary: @@ -52,9 +44,7 @@ private: Vec3d m_first_instance_mirror; std::vector m_planes; -#if ENABLE_RAYCAST_PICKING std::vector> m_planes_casters; -#endif // ENABLE_RAYCAST_PICKING bool m_mouse_left_down = false; // for detection left_up of this gizmo const ModelObject* m_old_model_object = nullptr; @@ -79,12 +69,8 @@ protected: std::string on_get_name() const override; bool on_is_activable() const override; void on_render() override; -#if ENABLE_RAYCAST_PICKING virtual void on_register_raycasters_for_picking() override; virtual void on_unregister_raycasters_for_picking() override; -#else - void on_render_for_picking() override; -#endif // ENABLE_RAYCAST_PICKING void on_set_state() override; CommonGizmosDataID on_get_requirements() const override; }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 633e61e56e..8b150cce90 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -60,12 +60,10 @@ void GLGizmoHollow::data_changed() update_volumes(); -#if ENABLE_RAYCAST_PICKING if (m_hole_raycasters.empty()) register_hole_raycasters_for_picking(); else update_hole_raycasters_for_picking_transform(); -#endif // ENABLE_RAYCAST_PICKING m_c->instances_hider()->set_hide_full_scene(true); } @@ -75,11 +73,6 @@ void GLGizmoHollow::data_changed() void GLGizmoHollow::on_render() { -#if !ENABLE_RAYCAST_PICKING - if (!m_cylinder.is_initialized()) - m_cylinder.init_from(its_make_cylinder(1.0, 1.0)); -#endif // !ENABLE_RAYCAST_PICKING - const Selection& selection = m_parent.get_selection(); const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info(); @@ -94,12 +87,8 @@ void GLGizmoHollow::on_render() glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_DEPTH_TEST)); -#if ENABLE_RAYCAST_PICKING render_volumes(); render_points(selection); -#else - render_points(selection, false); -#endif // ENABLE_RAYCAST_PICKING m_selection_rectangle.render(m_parent); m_c->object_clipper()->render_cut(); @@ -107,7 +96,6 @@ void GLGizmoHollow::on_render() glsafe(::glDisable(GL_BLEND)); } -#if ENABLE_RAYCAST_PICKING void GLGizmoHollow::on_register_raycasters_for_picking() { register_hole_raycasters_for_picking(); @@ -119,27 +107,11 @@ void GLGizmoHollow::on_unregister_raycasters_for_picking() unregister_hole_raycasters_for_picking(); unregister_volume_raycasters_for_picking(); } -#else -void GLGizmoHollow::on_render_for_picking() -{ - const Selection& selection = m_parent.get_selection(); - glsafe(::glEnable(GL_DEPTH_TEST)); - render_points(selection, true); -} -#endif // ENABLE_RAYCAST_PICKING -#if ENABLE_RAYCAST_PICKING void GLGizmoHollow::render_points(const Selection& selection) -#else -void GLGizmoHollow::render_points(const Selection& selection, bool picking) -#endif // ENABLE_RAYCAST_PICKING { #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); -#else - GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light"); -#endif // ENABLE_RAYCAST_PICKING if (shader == nullptr) return; @@ -181,41 +153,19 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) const sla::DrainHole& drain_hole = drain_holes[i]; const bool point_selected = m_selected[i]; -#if ENABLE_RAYCAST_PICKING const bool clipped = is_mesh_point_clipped(drain_hole.pos.cast()); m_hole_raycasters[i]->set_active(!clipped); if (clipped) continue; -#else - if (is_mesh_point_clipped(drain_hole.pos.cast())) - continue; -#endif // ENABLE_RAYCAST_PICKING // First decide about the color of the point. -#if !ENABLE_RAYCAST_PICKING - if (picking) - render_color = picking_color_component(i); - else { -#endif // !ENABLE_RAYCAST_PICKING - if (size_t(m_hover_id) == i) - render_color = ColorRGBA::CYAN(); -// else if (m_c->hollowed_mesh() && -// i < m_c->hollowed_mesh()->get_drainholes().size() && -// m_c->hollowed_mesh()->get_drainholes()[i].failed) { -// render_color = { 1.0f, 0.0f, 0.0f, 0.5f }; -// } - else - render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f); -#if !ENABLE_RAYCAST_PICKING - } -#endif // !ENABLE_RAYCAST_PICKING + if (size_t(m_hover_id) == i) + render_color = ColorRGBA::CYAN(); + else + render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f); #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING m_cylinder.model.set_color(render_color); -#else - m_cylinder.set_color(render_color); -#endif // ENABLE_RAYCAST_PICKING // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. const Transform3d hole_matrix = Geometry::translation_transform(drain_hole.pos.cast()) * instance_scaling_matrix_inverse; #else @@ -244,11 +194,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) glsafe(::glTranslated(0., 0., -drain_hole.height)); glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength)); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING m_cylinder.model.render(); -#else - m_cylinder.render(); -#endif // ENABLE_RAYCAST_PICKING if (vol->is_left_handed()) glsafe(::glFrontFace(GL_CCW)); @@ -324,10 +270,8 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos assert(m_selected.size() == mo->sla_drain_holes.size()); m_parent.set_as_dirty(); m_wait_for_up_event = true; -#if ENABLE_RAYCAST_PICKING unregister_hole_raycasters_for_picking(); register_hole_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING } else return false; @@ -352,12 +296,8 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos // Now ask the rectangle which of the points are inside. std::vector points_inside; -#if ENABLE_RAYCAST_PICKING std::vector points_idxs = m_selection_rectangle.contains(points); m_selection_rectangle.stop_dragging(); -#else - std::vector points_idxs = m_selection_rectangle.stop_dragging(m_parent, points); -#endif // ENABLE_RAYCAST_PICKING for (size_t idx : points_idxs) points_inside.push_back(points[idx].cast()); @@ -451,10 +391,8 @@ void GLGizmoHollow::delete_selected_points() } } -#if ENABLE_RAYCAST_PICKING unregister_hole_raycasters_for_picking(); register_hole_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING select_point(NoPoints); } @@ -523,7 +461,6 @@ bool GLGizmoHollow::on_mouse(const wxMouseEvent &mouse_event) return false; } -#if ENABLE_RAYCAST_PICKING void GLGizmoHollow::register_hole_raycasters_for_picking() { assert(m_hole_raycasters.empty()); @@ -572,7 +509,6 @@ void GLGizmoHollow::update_hole_raycasters_for_picking_transform() } } } -#endif // ENABLE_RAYCAST_PICKING std::vector> GLGizmoHollow::get_config_options(const std::vector& keys) const @@ -851,7 +787,6 @@ RENDER_AGAIN: m_c->object_clipper()->set_position_by_ratio(clp_dist, true); m_imgui->disabled_end(); - m_imgui->end(); @@ -1038,7 +973,6 @@ void GLGizmoHollow::on_set_hover_id() m_hover_id = -1; } -#if ENABLE_RAYCAST_PICKING void GLGizmoHollow::init_cylinder_model() { if (!m_cylinder.model.is_initialized()) { @@ -1047,7 +981,6 @@ void GLGizmoHollow::init_cylinder_model() m_cylinder.mesh_raycaster = std::make_unique(std::make_shared(std::move(its))); } } -#endif // ENABLE_RAYCAST_PICKING diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp index c1664b458b..abfb2503fa 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -42,33 +42,19 @@ public: protected: bool on_init() override; void on_render() override; -#if ENABLE_RAYCAST_PICKING virtual void on_register_raycasters_for_picking() override; virtual void on_unregister_raycasters_for_picking() override; -#else - void on_render_for_picking() override; -#endif // ENABLE_RAYCAST_PICKING private: -#if ENABLE_RAYCAST_PICKING void render_points(const Selection& selection); -#else - void render_points(const Selection& selection, bool picking = false); -#endif // ENABLE_RAYCAST_PICKING -#if ENABLE_RAYCAST_PICKING void register_hole_raycasters_for_picking(); void unregister_hole_raycasters_for_picking(); void update_hole_raycasters_for_picking_transform(); -#endif // ENABLE_RAYCAST_PICKING ObjectID m_old_mo_id = -1; -#if ENABLE_RAYCAST_PICKING PickingModel m_cylinder; std::vector> m_hole_raycasters; -#else - GLModel m_cylinder; -#endif // ENABLE_RAYCAST_PICKING float m_new_hole_radius = 2.f; // Size of a new hole. float m_new_hole_height = 6.f; @@ -123,9 +109,7 @@ protected: void on_load(cereal::BinaryInputArchive& ar) override; void on_save(cereal::BinaryOutputArchive& ar) const override; -#if ENABLE_RAYCAST_PICKING void init_cylinder_model(); -#endif // ENABLE_RAYCAST_PICKING }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index a026ae2552..a2d2518d6a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -5,9 +5,7 @@ #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/GUI_ObjectManipulation.hpp" -#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp" -#include "libslic3r/Model.hpp" #include "libslic3r/PresetBundle.hpp" #include "libslic3r/MeasureUtils.hpp" @@ -22,15 +20,16 @@ namespace Slic3r { namespace GUI { -static const Slic3r::ColorRGBA SELECTED_1ST_COLOR = { 0.25f, 0.75f, 0.75f, 1.0f }; -static const Slic3r::ColorRGBA SELECTED_2ND_COLOR = { 0.75f, 0.25f, 0.75f, 1.0f }; +static const Slic3r::ColorRGBA SELECTED_1ST_COLOR = { 0.25f, 0.75f, 0.75f, 1.0f }; +static const Slic3r::ColorRGBA SELECTED_2ND_COLOR = { 0.75f, 0.25f, 0.75f, 1.0f }; +static const Slic3r::ColorRGBA NEUTRAL_COLOR = { 0.5f, 0.5f, 0.5f, 1.0f }; static const int POINT_ID = 100; static const int EDGE_ID = 200; static const int CIRCLE_ID = 300; static const int PLANE_ID = 400; -static const int SELECTION_1_ID = 501; -static const int SELECTION_2_ID = 502; +static const int SEL_SPHERE_1_ID = 501; +static const int SEL_SPHERE_2_ID = 502; static const float TRIANGLE_BASE = 10.0f; static const float TRIANGLE_HEIGHT = TRIANGLE_BASE * 1.618033f; @@ -89,7 +88,7 @@ static std::string center_on_feature_type_as_string(Measure::SurfaceFeatureType switch (type) { case Measure::SurfaceFeatureType::Edge: { ret = _u8L("Center of edge"); break; } case Measure::SurfaceFeatureType::Circle: { ret = _u8L("Center of circle"); break; } - default: { assert(false); break; } + default: { assert(false); break; } } return ret; } @@ -166,6 +165,41 @@ static GLModel::Geometry init_torus_data(unsigned int primary_resolution, unsign return data; } +static bool is_feature_with_center(const Measure::SurfaceFeature& feature) +{ + const Measure::SurfaceFeatureType type = feature.get_type(); + return (type == Measure::SurfaceFeatureType::Circle || (type == Measure::SurfaceFeatureType::Edge && feature.get_extra_point().has_value())); +} + +static Vec3d get_feature_offset(const Measure::SurfaceFeature& feature) +{ + Vec3d ret; + switch (feature.get_type()) + { + case Measure::SurfaceFeatureType::Circle: + { + const auto [center, radius, normal] = feature.get_circle(); + ret = center; + break; + } + case Measure::SurfaceFeatureType::Edge: + { + std::optional p = feature.get_extra_point(); + assert(p.has_value()); + ret = *p; + break; + } + case Measure::SurfaceFeatureType::Point: + { + ret = feature.get_point(); + break; + } + default: { assert(false); } + } + + return ret; +} + class TransformHelper { struct Cache @@ -242,7 +276,7 @@ private: TransformHelper::Cache TransformHelper::s_cache = { { 0, 0, 0, 0 }, Matrix4d::Identity(), Transform3d::Identity() }; GLGizmoMeasure::GLGizmoMeasure(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) +: GLGizmoBase(parent, icon_filename, sprite_id) { GLModel::Geometry sphere_geometry = smooth_sphere(16, 7.5f); m_sphere.mesh_raycaster = std::make_unique(std::make_shared(sphere_geometry.get_as_indexed_triangle_set())); @@ -267,112 +301,127 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event) // Ctrl is pressed or the mouse is not hovering a selected volume bool unlock_dragging = mouse_event.CmdDown() || (m_hover_id == -1 && !m_parent.get_selection().contains_volume(m_parent.get_first_hover_volume_idx())); // mode is not center selection or mouse is not hovering a center - unlock_dragging &= !mouse_event.ShiftDown() || (m_hover_id != SELECTION_1_ID && m_hover_id != SELECTION_2_ID && m_hover_id != POINT_ID); + unlock_dragging &= !mouse_event.ShiftDown() || (m_hover_id != SEL_SPHERE_1_ID && m_hover_id != SEL_SPHERE_2_ID && m_hover_id != POINT_ID); return !unlock_dragging; } else if (mouse_event.LeftDown()) { // let the event pass through to allow panning/rotating the 3D scene - if ((m_mode != EMode::CenterSelection && mouse_event.CmdDown()) || - (m_mode == EMode::CenterSelection && m_hover_id != SELECTION_1_ID && m_hover_id != SELECTION_2_ID && m_hover_id != POINT_ID)) { + if (mouse_event.CmdDown()) return false; - } if (m_hover_id != -1) { - SelectedFeatures selected_features_old = m_selected_features; m_mouse_left_down = true; - auto item_from_feature = [this]() { + auto detect_current_item = [this]() { SelectedFeatures::Item item; - if (m_hover_id == SELECTION_1_ID && m_selected_features.first.feature.has_value()) - item = m_selected_features.first; - else if (m_hover_id == SELECTION_2_ID && m_selected_features.second.feature.has_value()) - item = m_selected_features.second; + if (m_hover_id == SEL_SPHERE_1_ID) { + if (m_selected_features.first.is_center) + // mouse is hovering over a selected center + item = { true, m_selected_features.first.source, { Measure::SurfaceFeature(get_feature_offset(*m_selected_features.first.source)) } }; + else if (is_feature_with_center(*m_selected_features.first.feature)) + // mouse is hovering over a unselected center + item = { true, m_selected_features.first.feature, { Measure::SurfaceFeature(get_feature_offset(*m_selected_features.first.feature)) } }; + else + // mouse is hovering over a point + item = m_selected_features.first; + } + else if (m_hover_id == SEL_SPHERE_2_ID) { + if (m_selected_features.second.is_center) + // mouse is hovering over a selected center + item = { true, m_selected_features.second.source, { Measure::SurfaceFeature(get_feature_offset(*m_selected_features.second.source)) } }; + else if (is_feature_with_center(*m_selected_features.second.feature)) + // mouse is hovering over a center + item = { true, m_selected_features.second.feature, { Measure::SurfaceFeature(get_feature_offset(*m_selected_features.second.feature)) } }; + else + // mouse is hovering over a point + item = m_selected_features.second; + } else { switch (m_mode) { - case EMode::FeatureSelection: - { - item = { surface_feature_type_as_string(m_curr_feature->get_type()), m_curr_feature }; - break; - } - case EMode::PointSelection: - { - item = { point_on_feature_type_as_string(m_curr_feature->get_type(), m_hover_id), Measure::SurfaceFeature(*m_curr_point_on_feature_position) }; - break; - } - case EMode::CenterSelection: - { - Vec3d position; - switch (m_curr_feature->get_type()) - { - case Measure::SurfaceFeatureType::Circle: - { - position = std::get<0>(m_curr_feature->get_circle()); - break; - } - case Measure::SurfaceFeatureType::Edge: - { - assert(m_curr_feature->get_extra_point().has_value()); - position = *m_curr_feature->get_extra_point(); - break; - } - default: { assert(false); break; } - } - - item = { center_on_feature_type_as_string(m_curr_feature->get_type()), Measure::SurfaceFeature(position) }; - break; - } + case EMode::FeatureSelection: { item = { false, m_curr_feature, m_curr_feature }; break; } + case EMode::PointSelection: { item = { false, m_curr_feature, Measure::SurfaceFeature(*m_curr_point_on_feature_position) }; break; } } } return item; }; - if (m_selected_features.first.feature.has_value()) { - auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(), - [](std::shared_ptr item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_2_ID; }); - if (it != m_selection_raycasters.end()) - m_selection_raycasters.erase(it); - m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, SELECTION_2_ID); + auto requires_sphere_raycaster_for_picking = [this](const SelectedFeatures::Item& item) { + if (m_mode == EMode::PointSelection || item.feature->get_type() == Measure::SurfaceFeatureType::Point) + return true; + else if (m_mode == EMode::FeatureSelection) { + if (is_feature_with_center(*item.feature)) + return true; + } + return false; + }; - const SelectedFeatures::Item item = item_from_feature(); + if (m_selected_features.first.feature.has_value()) { + const SelectedFeatures::Item item = detect_current_item(); if (m_selected_features.first != item) { - if (m_selected_features.second == item) - m_selected_features.second.reset(); - else { - m_selected_features.second = item; - if (m_mode == EMode::PointSelection || m_mode == EMode::CenterSelection) - m_selection_raycasters.push_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, SELECTION_2_ID, *m_sphere.mesh_raycaster)); - if (m_mode == EMode::CenterSelection) { - // Fake ctrl up event to exit the center selection mode - gizmo_event(SLAGizmoEventType::CtrlUp, Vec2d::Zero(), true, false, false); - // increase counter to avoid that keeping the ctrl key pressed triggers a ctrl down event - m_ctrl_kar_filter.increase_count(); + bool processed = false; + if (item.is_center) { + if (item.source == m_selected_features.first.feature) { + // switch 1st selection from feature to its center + m_selected_features.first = item; + processed = true; + } + else if (item.source == m_selected_features.second.feature) { + // switch 2nd selection from feature to its center + m_selected_features.second = item; + processed = true; + } + } + else if (is_feature_with_center(*item.feature)) { + if (m_selected_features.first.is_center && m_selected_features.first.source == item.feature) { + // switch 1st selection from center to its feature + m_selected_features.first = item; + processed = true; + } + else if (m_selected_features.second.is_center && m_selected_features.second.source == item.feature) { + // switch 2nd selection from center to its feature + m_selected_features.second = item; + processed = true; + } + } + + if (!processed) { + remove_selected_sphere_raycaster(SEL_SPHERE_2_ID); + if (m_selected_features.second == item) + // 2nd feature deselection + m_selected_features.second.reset(); + else { + // 2nd feature selection + m_selected_features.second = item; + if (requires_sphere_raycaster_for_picking(item)) + m_selected_sphere_raycasters.push_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, SEL_SPHERE_2_ID, *m_sphere.mesh_raycaster)); } } } else { - if (!m_selected_features.second.feature.has_value()) + remove_selected_sphere_raycaster(SEL_SPHERE_1_ID); + if (m_selected_features.second.feature.has_value()) { + // promote 2nd feature to 1st feature + remove_selected_sphere_raycaster(SEL_SPHERE_2_ID); + m_selected_features.first = m_selected_features.second; + if (requires_sphere_raycaster_for_picking(m_selected_features.first)) + m_selected_sphere_raycasters.push_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, SEL_SPHERE_1_ID, *m_sphere.mesh_raycaster)); + m_selected_features.second.reset(); + } + else + // 1st feature deselection m_selected_features.first.reset(); } } else { - const SelectedFeatures::Item item = item_from_feature(); + // 1st feature selection + const SelectedFeatures::Item item = detect_current_item(); m_selected_features.first = item; - if (m_mode == EMode::PointSelection || m_mode == EMode::CenterSelection) - m_selection_raycasters.push_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, SELECTION_1_ID, *m_sphere.mesh_raycaster)); - if (m_mode == EMode::CenterSelection) { - // Fake ctrl up event to exit the center selection mode - gizmo_event(SLAGizmoEventType::CtrlUp, Vec2d::Zero(), true, false, false); - // increase counter to avoid that keeping the ctrl key pressed triggers a ctrl down event - m_ctrl_kar_filter.increase_count(); - } + if (requires_sphere_raycaster_for_picking(item)) + m_selected_sphere_raycasters.push_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, SEL_SPHERE_1_ID, *m_sphere.mesh_raycaster)); } - if (m_selected_features != selected_features_old && m_selected_features.second.feature.has_value()) { - m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get()); - // transform to world coordinates - m_measurement_result.transform(m_volume_matrix); - } + update_measurement_result(); m_imgui->set_requires_extra_frame(); @@ -400,16 +449,8 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event) } else if (mouse_event.RightDown()) { // let the event pass through to allow panning/rotating the 3D scene - if ((m_mode != EMode::CenterSelection && mouse_event.CmdDown()) || (m_mode == EMode::CenterSelection && m_hover_id != SELECTION_1_ID && m_hover_id != SELECTION_2_ID)) { - std::cout << "RightDown -> false\n"; + if (mouse_event.CmdDown()) return false; - } - - if (mouse_event.ShiftDown()) { - m_selected_features.reset(); - m_selection_raycasters.clear(); - m_parent.request_extra_frame(); - } } else if (mouse_event.Leaving()) m_mouse_left_down = false; @@ -419,55 +460,28 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event) void GLGizmoMeasure::data_changed() { - const Selection& selection = m_parent.get_selection(); - const ModelObject* model_object = nullptr; - const ModelVolume* model_volume = nullptr; - if (selection.is_single_full_instance() || - selection.is_from_single_object() ) { - model_object = selection.get_model()->objects[selection.get_object_idx()]; - model_volume = model_object->volumes[selection.get_first_volume()->volume_idx()]; - } - if (model_object != m_old_model_object || model_volume != m_old_model_volume) - update_if_needed(); + m_parent.toggle_sla_auxiliaries_visibility(false, nullptr, -1); + + update_if_needed(); m_last_inv_zoom = 0.0f; m_last_plane_idx = -1; if (m_pending_scale) { - m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get()); - // transform to world coordinates - m_measurement_result.transform(m_volume_matrix); + update_measurement_result(); m_pending_scale = false; } else m_selected_features.reset(); - m_selection_raycasters.clear(); + m_selected_sphere_raycasters.clear(); m_editing_distance = false; m_is_editing_distance_first_frame = true; } -static bool feature_has_center(std::optional feature) -{ - return feature.has_value() ? - (feature->get_type() == Measure::SurfaceFeatureType::Circle || (feature->get_type() == Measure::SurfaceFeatureType::Edge && feature->get_extra_point().has_value())) - : false; -} - bool GLGizmoMeasure::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down) { - auto activate_center_selection = [this, shift_down, control_down](SLAGizmoEventType action) { - bool ret = false; - switch (action) - { - case SLAGizmoEventType::CtrlDown: { ret = shift_down && feature_has_center(m_curr_feature); break; } - case SLAGizmoEventType::ShiftDown: { ret = control_down && feature_has_center(m_curr_feature); break; } - default: { break; } - } - return ret; - }; - if (action == SLAGizmoEventType::ShiftDown) { if (m_shift_kar_filter.is_first()) { - m_mode = activate_center_selection(SLAGizmoEventType::ShiftDown) ? EMode::CenterSelection : EMode::PointSelection; + m_mode = EMode::PointSelection; disable_scene_raycasters(); } m_shift_kar_filter.increase_count(); @@ -477,19 +491,28 @@ bool GLGizmoMeasure::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_po m_mode = EMode::FeatureSelection; restore_scene_raycasters_state(); } - else if (action == SLAGizmoEventType::CtrlDown) { - if (m_ctrl_kar_filter.is_first()) { - if (activate_center_selection(SLAGizmoEventType::CtrlDown)) { - m_mode = EMode::CenterSelection; - disable_scene_raycasters(); - } - } - m_ctrl_kar_filter.increase_count(); + else if (action == SLAGizmoEventType::Delete) { + m_selected_features.reset(); + m_selected_sphere_raycasters.clear(); + m_parent.request_extra_frame(); } - else if (action == SLAGizmoEventType::CtrlUp) { - m_ctrl_kar_filter.reset_count(); - m_mode = control_down ? EMode::PointSelection : EMode::FeatureSelection; - restore_scene_raycasters_state(); + else if (action == SLAGizmoEventType::Escape) { + if (!m_selected_features.first.feature.has_value()) { + update_measurement_result(); + return false; + } + else { + if (m_selected_features.second.feature.has_value()) { + remove_selected_sphere_raycaster(SEL_SPHERE_2_ID); + m_selected_features.second.feature.reset(); + } + else { + remove_selected_sphere_raycaster(SEL_SPHERE_1_ID); + m_selected_features.first.feature.reset(); + } + + update_measurement_result(); + } } return true; @@ -504,7 +527,7 @@ bool GLGizmoMeasure::on_init() void GLGizmoMeasure::on_set_state() { if (m_state == Off) { - m_ctrl_kar_filter.reset_count(); + m_parent.toggle_sla_auxiliaries_visibility(true, nullptr, -1); m_shift_kar_filter.reset_count(); m_curr_feature.reset(); m_curr_point_on_feature_position.reset(); @@ -512,6 +535,7 @@ void GLGizmoMeasure::on_set_state() m_editing_distance = false; m_is_editing_distance_first_frame = true; m_measuring.reset(); + m_raycaster.reset(); } else { m_mode = EMode::FeatureSelection; @@ -528,11 +552,6 @@ void GLGizmoMeasure::on_set_state() } } -CommonGizmosDataID GLGizmoMeasure::on_get_requirements() const -{ - return CommonGizmosDataID(int(CommonGizmosDataID::SelectionInfo) | int(CommonGizmosDataID::Raycaster)); -} - std::string GLGizmoMeasure::on_get_name() const { return _u8L("Measure"); @@ -543,9 +562,9 @@ bool GLGizmoMeasure::on_is_activable() const const Selection& selection = m_parent.get_selection(); bool res = (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA) ? selection.is_single_full_instance() : - selection.is_single_volume() || selection.is_single_volume_instance(); + selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier(); if (res) - res &= !selection.get_first_volume()->is_sinking(); + res &= !selection.contains_sinking_volumes(); return res; } @@ -560,398 +579,460 @@ void GLGizmoMeasure::on_render() // if (m_parent.is_mouse_dragging()) // return; - const Selection& selection = m_parent.get_selection(); + update_if_needed(); - if ((wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA && selection.is_single_full_instance()) || - (selection.is_single_volume() || selection.is_single_volume_instance())) { - update_if_needed(); + const Camera& camera = wxGetApp().plater()->get_camera(); + const float inv_zoom = (float)camera.get_inv_zoom(); - const Camera& camera = wxGetApp().plater()->get_camera(); - const float inv_zoom = (float)camera.get_inv_zoom(); + Vec3f position_on_model; + Vec3f normal_on_model; + size_t model_facet_idx; + const bool mouse_on_object = m_raycaster->unproject_on_mesh(m_mouse_pos, Transform3d::Identity(), camera, position_on_model, normal_on_model, nullptr, &model_facet_idx); + const bool is_hovering_on_feature = m_mode == EMode::PointSelection && m_hover_id != -1; - Vec3f position_on_model; - Vec3f normal_on_model; - size_t model_facet_idx; - const bool mouse_on_object = m_c->raycaster()->raycasters().front()->unproject_on_mesh(m_mouse_pos, m_volume_matrix, camera, position_on_model, normal_on_model, nullptr, &model_facet_idx); - const bool is_hovering_on_feature = (m_mode == EMode::PointSelection || m_mode == EMode::CenterSelection) && m_hover_id != -1; + auto update_circle = [this, inv_zoom]() { + if (m_last_inv_zoom != inv_zoom || m_last_circle != m_curr_feature) { + m_last_inv_zoom = inv_zoom; + m_last_circle = m_curr_feature; + m_circle.reset(); + const auto [center, radius, normal] = m_curr_feature->get_circle(); + GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast(), float(radius), 5.0f * inv_zoom, normal.cast(), Transform3f::Identity()); + m_circle.mesh_raycaster = std::make_unique(std::make_shared(circle_geometry.get_as_indexed_triangle_set())); + m_circle.model.init_from(std::move(circle_geometry)); + return true; + } + return false; + }; - auto update_circle = [this, inv_zoom]() { - if (m_last_inv_zoom != inv_zoom || m_last_circle != m_curr_feature) { - m_last_inv_zoom = inv_zoom; - m_last_circle = m_curr_feature; - m_circle.reset(); - const auto [center, radius, normal] = m_curr_feature->get_circle(); - GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast(), float(radius), 5.0f * inv_zoom, normal.cast(), m_volume_matrix.cast()); - m_circle.mesh_raycaster = std::make_unique(std::make_shared(circle_geometry.get_as_indexed_triangle_set())); - m_circle.model.init_from(std::move(circle_geometry)); - return true; - } - return false; - }; + if (m_mode == EMode::FeatureSelection || m_mode == EMode::PointSelection) { + if (m_hover_id == SEL_SPHERE_1_ID || m_hover_id == SEL_SPHERE_2_ID) { + // Skip feature detection if hovering on a selected point/center + m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, POINT_ID); + m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, EDGE_ID); + m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, PLANE_ID); + m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, CIRCLE_ID); + m_curr_feature.reset(); + m_curr_point_on_feature_position.reset(); + } + else { + std::optional curr_feature = wxGetMouseState().LeftIsDown() ? m_curr_feature : + mouse_on_object ? m_measuring->get_feature(model_facet_idx, position_on_model.cast()) : std::nullopt; - if (m_mode == EMode::FeatureSelection || m_mode == EMode::PointSelection) { - if ((m_hover_id == SELECTION_1_ID && boost::algorithm::istarts_with(m_selected_features.first.source, _u8L("Center"))) || - (m_hover_id == SELECTION_2_ID && boost::algorithm::istarts_with(m_selected_features.second.source, _u8L("Center")))) { - // Skip feature detection if hovering on a selected center - m_curr_feature.reset(); + if (m_curr_feature != curr_feature || + (curr_feature.has_value() && curr_feature->get_type() == Measure::SurfaceFeatureType::Circle && (m_curr_feature != curr_feature || m_last_inv_zoom != inv_zoom))) { m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, POINT_ID); m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, EDGE_ID); m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, PLANE_ID); m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, CIRCLE_ID); - m_curr_point_on_feature_position.reset(); - } - else { - std::optional curr_feature = mouse_on_object ? m_measuring->get_feature(model_facet_idx, position_on_model.cast()) : std::nullopt; - if (m_curr_feature != curr_feature || - (curr_feature.has_value() && curr_feature->get_type() == Measure::SurfaceFeatureType::Circle && (m_curr_feature != curr_feature || m_last_inv_zoom != inv_zoom))) { - m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, POINT_ID); - m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, EDGE_ID); - m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, PLANE_ID); - m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, CIRCLE_ID); - m_raycasters.clear(); - m_curr_feature = curr_feature; - if (!m_curr_feature.has_value()) - return; + m_raycasters.clear(); + m_curr_feature = curr_feature; + if (!m_curr_feature.has_value()) + return; - switch (m_curr_feature->get_type()) { - default: { assert(false); break; } - case Measure::SurfaceFeatureType::Point: - { - m_raycasters.insert({ POINT_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, POINT_ID, *m_sphere.mesh_raycaster) }); - break; - } - case Measure::SurfaceFeatureType::Edge: - { - m_raycasters.insert({ EDGE_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, EDGE_ID, *m_cylinder.mesh_raycaster) }); - if (m_curr_feature->get_extra_point().has_value()) - m_raycasters.insert({ POINT_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, POINT_ID, *m_sphere.mesh_raycaster) }); - break; - } - case Measure::SurfaceFeatureType::Circle: - { - update_circle(); - m_raycasters.insert({ CIRCLE_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, CIRCLE_ID, *m_circle.mesh_raycaster) }); - m_raycasters.insert({ POINT_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, POINT_ID, *m_sphere.mesh_raycaster) }); - break; - } - case Measure::SurfaceFeatureType::Plane: - { - const auto [idx, normal, point] = m_curr_feature->get_plane(); - if (m_last_plane_idx != idx) { - m_last_plane_idx = idx; - const indexed_triangle_set its = (m_old_model_volume != nullptr) ? m_old_model_volume->mesh().its : m_old_model_object->volumes.front()->mesh().its; - const std::vector> planes_triangles = m_measuring->get_planes_triangle_indices(); - GLModel::Geometry init_data = init_plane_data(its, planes_triangles, idx); - m_plane.reset(); - m_plane.mesh_raycaster = std::make_unique(std::make_shared(init_data.get_as_indexed_triangle_set())); - m_plane.model.init_from(std::move(init_data)); - } - - m_raycasters.insert({ PLANE_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, PLANE_ID, *m_plane.mesh_raycaster) }); - break; - } - } - } - } - } - - if (m_mode != EMode::PointSelection) - m_curr_point_on_feature_position.reset(); - else if (is_hovering_on_feature) { - auto position_on_feature = [this](int feature_type_id, const Camera& camera, std::function callback = nullptr) -> Vec3d { - auto it = m_raycasters.find(feature_type_id); - if (it != m_raycasters.end() && it->second != nullptr) { - Vec3f p; - Vec3f n; - const Transform3d& trafo = it->second->get_transform(); - bool res = it->second->get_raycaster()->closest_hit(m_mouse_pos, trafo, camera, p, n); - if (res) { - if (callback) - p = callback(p); - return trafo * p.cast(); - } - } - return Vec3d::Zero(); - }; - - if (m_curr_feature.has_value()) { - switch (m_curr_feature->get_type()) - { + switch (m_curr_feature->get_type()) { default: { assert(false); break; } case Measure::SurfaceFeatureType::Point: { - m_curr_point_on_feature_position = m_curr_feature->get_point(); + m_raycasters.insert({ POINT_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, POINT_ID, *m_sphere.mesh_raycaster) }); break; } case Measure::SurfaceFeatureType::Edge: { - const std::optional extra = m_curr_feature->get_extra_point(); - if (extra.has_value() && m_hover_id == POINT_ID) - m_curr_point_on_feature_position = *extra; - else - m_curr_point_on_feature_position = m_volume_matrix.inverse() * position_on_feature(EDGE_ID, camera, [](const Vec3f& v) { return Vec3f(0.0f, 0.0f, v.z()); }); - break; - } - case Measure::SurfaceFeatureType::Plane: - { - m_curr_point_on_feature_position = m_volume_matrix.inverse() * position_on_feature(PLANE_ID, camera); + m_raycasters.insert({ EDGE_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, EDGE_ID, *m_cylinder.mesh_raycaster) }); break; } case Measure::SurfaceFeatureType::Circle: { - const auto [center, radius, normal] = m_curr_feature->get_circle(); - if (m_hover_id == POINT_ID) - m_curr_point_on_feature_position = center; - else { - const Vec3d world_pof = position_on_feature(CIRCLE_ID, camera, [](const Vec3f& v) { return v; }); - const Eigen::Hyperplane plane(m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal, m_volume_matrix * center); - const Transform3d local_to_model_matrix = Geometry::translation_transform(center) * Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), normal); - const Vec3d local_proj = local_to_model_matrix.inverse() * m_volume_matrix.inverse() * plane.projection(world_pof); - double angle = std::atan2(local_proj.y(), local_proj.x()); - if (angle < 0.0) - angle += 2.0 * double(M_PI); - - const Vec3d local_pos = radius * Vec3d(std::cos(angle), std::sin(angle), 0.0); - m_curr_point_on_feature_position = local_to_model_matrix * local_pos; - } - break; - } - } - } - } - else { - if (m_curr_feature.has_value() && m_curr_feature->get_type() == Measure::SurfaceFeatureType::Circle) { - if (update_circle()) { - m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, CIRCLE_ID); - auto it = m_raycasters.find(CIRCLE_ID); - if (it != m_raycasters.end()) - m_raycasters.erase(it); + update_circle(); m_raycasters.insert({ CIRCLE_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, CIRCLE_ID, *m_circle.mesh_raycaster) }); - } - } - } - - if (!m_curr_feature.has_value() && !m_selected_features.first.feature.has_value()) - return; - - GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); - if (shader == nullptr) - return; - - shader->start_using(); - shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - - glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); - glsafe(::glEnable(GL_DEPTH_TEST)); - const bool old_cullface = ::glIsEnabled(GL_CULL_FACE); - glsafe(::glDisable(GL_CULL_FACE)); - - const Transform3d& view_matrix = camera.get_view_matrix(); - - auto set_matrix_uniforms = [shader, &view_matrix](const Transform3d& model_matrix) { - const Transform3d view_model_matrix = view_matrix * model_matrix; - shader->set_uniform("view_model_matrix", view_model_matrix); - const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); - shader->set_uniform("view_normal_matrix", view_normal_matrix); - }; - - auto set_emission_uniform = [this, shader](const ColorRGBA& color, bool hover) { - shader->set_uniform("emission_factor", (color == m_parent.get_selection().get_first_volume()->render_color) ? 0.0f : - hover ? 0.5f : 0.25f); - }; - - auto render_feature = [this, set_matrix_uniforms, set_emission_uniform](const Measure::SurfaceFeature& feature, const std::vector& colors, - float inv_zoom, bool hover, bool update_raycasters_transform) { - switch (feature.get_type()) - { - default: { assert(false); break; } - case Measure::SurfaceFeatureType::Point: - { - const Vec3d position = TransformHelper::model_to_world(feature.get_point(), m_volume_matrix); - const Transform3d feature_matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom); - set_matrix_uniforms(feature_matrix); - set_emission_uniform(colors.front(), hover); - m_sphere.model.set_color(colors.front()); - m_sphere.model.render(); - if (update_raycasters_transform) { - auto it = m_raycasters.find(POINT_ID); - if (it != m_raycasters.end() && it->second != nullptr) - it->second->set_transform(feature_matrix); - } - break; - } - case Measure::SurfaceFeatureType::Circle: - { - const auto& [center, radius, normal] = feature.get_circle(); - // render center - if (update_raycasters_transform) { - const Vec3d center_world = TransformHelper::model_to_world(center, m_volume_matrix); - const Transform3d center_matrix = Geometry::translation_transform(center_world) * Geometry::scale_transform(inv_zoom); - set_matrix_uniforms(center_matrix); - set_emission_uniform(colors.front(), hover); - m_sphere.model.set_color(colors.front()); - m_sphere.model.render(); - auto it = m_raycasters.find(POINT_ID); - if (it != m_raycasters.end() && it->second != nullptr) - it->second->set_transform(center_matrix); - } - // render circle - if (m_mode != EMode::CenterSelection) { - const Transform3d circle_matrix = Transform3d::Identity(); - set_matrix_uniforms(circle_matrix); - if (update_raycasters_transform) { - set_emission_uniform(colors.back(), hover); - m_circle.model.set_color(colors.back()); - m_circle.model.render(); - auto it = m_raycasters.find(CIRCLE_ID); - if (it != m_raycasters.end() && it->second != nullptr) - it->second->set_transform(circle_matrix); - } - else { - GLModel circle; - GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast(), float(radius), 5.0f * inv_zoom, normal.cast(), m_volume_matrix.cast()); - circle.init_from(std::move(circle_geometry)); - set_emission_uniform(colors.back(), hover); - circle.set_color(colors.back()); - circle.render(); - } - } - break; - } - case Measure::SurfaceFeatureType::Edge: - { - const auto& [from, to] = feature.get_edge(); - // render extra point - if (update_raycasters_transform) { - const std::optional extra = feature.get_extra_point(); - if (extra.has_value()) { - const Vec3d extra_world = TransformHelper::model_to_world(*extra, m_volume_matrix); - const Transform3d point_matrix = Geometry::translation_transform(extra_world) * Geometry::scale_transform(inv_zoom); - set_matrix_uniforms(point_matrix); - set_emission_uniform(colors.front(), hover); - m_sphere.model.set_color(colors.front()); - m_sphere.model.render(); - auto it = m_raycasters.find(POINT_ID); - if (it != m_raycasters.end() && it->second != nullptr) - it->second->set_transform(point_matrix); - } - } - // render edge - if (m_mode != EMode::CenterSelection) { - const Vec3d from_world = TransformHelper::model_to_world(from, m_volume_matrix); - const Vec3d to_world = TransformHelper::model_to_world(to, m_volume_matrix); - const Transform3d edge_matrix = Geometry::translation_transform(from_world) * - Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), to_world - from_world) * - Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (to_world - from_world).norm() }); - set_matrix_uniforms(edge_matrix); - set_emission_uniform(colors.back(), hover); - m_cylinder.model.set_color(colors.back()); - m_cylinder.model.render(); - if (update_raycasters_transform) { - auto it = m_raycasters.find(EDGE_ID); - if (it != m_raycasters.end() && it->second != nullptr) - it->second->set_transform(edge_matrix); - } - } break; } case Measure::SurfaceFeatureType::Plane: { - const auto& [idx, normal, pt] = feature.get_plane(); - assert(idx < m_plane_models_cache.size()); - set_matrix_uniforms(m_volume_matrix); - set_emission_uniform(colors.front(), hover); - m_plane_models_cache[idx].set_color(colors.front()); - m_plane_models_cache[idx].render(); - if (update_raycasters_transform) { - auto it = m_raycasters.find(PLANE_ID); - if (it != m_raycasters.end() && it->second != nullptr) - it->second->set_transform(m_volume_matrix); + const auto [idx, normal, point] = m_curr_feature->get_plane(); + if (m_last_plane_idx != idx) { + m_last_plane_idx = idx; + const indexed_triangle_set& its = m_measuring->get_mesh().its; + const std::vector> planes_triangles = m_measuring->get_planes_triangle_indices(); + GLModel::Geometry init_data = init_plane_data(its, planes_triangles, idx); + m_plane.reset(); + m_plane.mesh_raycaster = std::make_unique(std::make_shared(init_data.get_as_indexed_triangle_set())); + m_plane.model.init_from(std::move(init_data)); } + + m_raycasters.insert({ PLANE_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, PLANE_ID, *m_plane.mesh_raycaster) }); break; } } - }; + } + } + } - auto hover_selection_color = [this]() { - return !m_selected_features.first.feature.has_value() ? SELECTED_1ST_COLOR : SELECTED_2ND_COLOR; - }; - - auto hovering_color = [this, hover_selection_color, &selection]() { - return (m_mode == EMode::PointSelection) ? selection.get_first_volume()->render_color : hover_selection_color(); + if (m_mode != EMode::PointSelection) + m_curr_point_on_feature_position.reset(); + else if (is_hovering_on_feature) { + auto position_on_feature = [this](int feature_type_id, const Camera& camera, std::function callback = nullptr) -> Vec3d { + auto it = m_raycasters.find(feature_type_id); + if (it != m_raycasters.end() && it->second != nullptr) { + Vec3f p; + Vec3f n; + const Transform3d& trafo = it->second->get_transform(); + bool res = it->second->get_raycaster()->closest_hit(m_mouse_pos, trafo, camera, p, n); + if (res) { + if (callback) + p = callback(p); + return trafo * p.cast(); + } + } + return Vec3d(DBL_MAX, DBL_MAX, DBL_MAX); }; if (m_curr_feature.has_value()) { - std::vector colors; - if (m_selected_features.first.feature.has_value() && *m_curr_feature == *m_selected_features.first.feature) - colors.emplace_back(hovering_color()); - else if (m_selected_features.second.feature.has_value() && *m_curr_feature == *m_selected_features.second.feature) - colors.emplace_back(hovering_color()); - else { - switch (m_curr_feature->get_type()) - { - default: { assert(false); break; } - case Measure::SurfaceFeatureType::Point: - { - colors.emplace_back(hover_selection_color()); - break; - } - case Measure::SurfaceFeatureType::Edge: - case Measure::SurfaceFeatureType::Circle: - { - colors.emplace_back((m_hover_id == POINT_ID) ? hover_selection_color() : hovering_color()); - colors.emplace_back(hovering_color()); - break; - } - case Measure::SurfaceFeatureType::Plane: - { - colors.emplace_back(hovering_color()); - break; - } - } + switch (m_curr_feature->get_type()) + { + default: { assert(false); break; } + case Measure::SurfaceFeatureType::Point: + { + m_curr_point_on_feature_position = m_curr_feature->get_point(); + break; } + case Measure::SurfaceFeatureType::Edge: + { + const std::optional extra = m_curr_feature->get_extra_point(); + if (extra.has_value() && m_hover_id == POINT_ID) + m_curr_point_on_feature_position = *extra; + else { + const Vec3d pos = position_on_feature(EDGE_ID, camera, [](const Vec3f& v) { return Vec3f(0.0f, 0.0f, v.z()); }); + if (!pos.isApprox(Vec3d(DBL_MAX, DBL_MAX, DBL_MAX))) + m_curr_point_on_feature_position = pos; + } + break; + } + case Measure::SurfaceFeatureType::Plane: + { + m_curr_point_on_feature_position = position_on_feature(PLANE_ID, camera); + break; + } + case Measure::SurfaceFeatureType::Circle: + { + const auto [center, radius, normal] = m_curr_feature->get_circle(); + if (m_hover_id == POINT_ID) + m_curr_point_on_feature_position = center; + else { + const Vec3d world_pof = position_on_feature(CIRCLE_ID, camera, [](const Vec3f& v) { return v; }); + const Eigen::Hyperplane plane(normal, center); + const Transform3d local_to_model_matrix = Geometry::translation_transform(center) * Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), normal); + const Vec3d local_proj = local_to_model_matrix.inverse() * plane.projection(world_pof); + double angle = std::atan2(local_proj.y(), local_proj.x()); + if (angle < 0.0) + angle += 2.0 * double(M_PI); - render_feature(*m_curr_feature, colors, inv_zoom, true, true); - } - - if (m_selected_features.first.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.first.feature)) { - const std::vector colors = { SELECTED_1ST_COLOR }; - render_feature(*m_selected_features.first.feature, colors, inv_zoom, m_hover_id == SELECTION_1_ID, false); - if (m_selected_features.first.feature->get_type() == Measure::SurfaceFeatureType::Point) { - auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(), - [](std::shared_ptr item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_1_ID; }); - if (it != m_selection_raycasters.end()) - (*it)->set_transform(m_volume_matrix * Geometry::translation_transform(m_selected_features.first.feature->get_point()) * Geometry::scale_transform(inv_zoom)); + const Vec3d local_pos = radius * Vec3d(std::cos(angle), std::sin(angle), 0.0); + m_curr_point_on_feature_position = local_to_model_matrix * local_pos; + } + break; + } } } - if (m_selected_features.second.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.second.feature)) { - const std::vector colors = { SELECTED_2ND_COLOR }; - render_feature(*m_selected_features.second.feature, colors, inv_zoom, m_hover_id == SELECTION_2_ID, false); - if (m_selected_features.second.feature->get_type() == Measure::SurfaceFeatureType::Point) { - auto it = std::find_if(m_selection_raycasters.begin(), m_selection_raycasters.end(), - [](std::shared_ptr item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SELECTION_2_ID; }); - if (it != m_selection_raycasters.end()) - (*it)->set_transform(m_volume_matrix * Geometry::translation_transform(m_selected_features.second.feature->get_point()) * Geometry::scale_transform(inv_zoom)); - } - } - - if (is_hovering_on_feature && m_curr_point_on_feature_position.has_value()) { - if (m_hover_id != POINT_ID) { - const Vec3d position = TransformHelper::model_to_world(*m_curr_point_on_feature_position, m_volume_matrix); - const Transform3d matrix = Geometry::translation_transform(position) * Geometry::scale_transform(inv_zoom); - set_matrix_uniforms(matrix); - const ColorRGBA color = hover_selection_color(); - set_emission_uniform(color, true); - m_sphere.model.set_color(color); - m_sphere.model.render(); - } - } - - shader->stop_using(); - - if (old_cullface) - glsafe(::glEnable(GL_CULL_FACE)); } + else { + m_curr_point_on_feature_position.reset(); + if (m_curr_feature.has_value() && m_curr_feature->get_type() == Measure::SurfaceFeatureType::Circle) { + if (update_circle()) { + m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, CIRCLE_ID); + auto it = m_raycasters.find(CIRCLE_ID); + if (it != m_raycasters.end()) + m_raycasters.erase(it); + m_raycasters.insert({ CIRCLE_ID, m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, CIRCLE_ID, *m_circle.mesh_raycaster) }); + } + } + } + + if (!m_curr_feature.has_value() && !m_selected_features.first.feature.has_value()) + return; + + GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + if (shader == nullptr) + return; + + shader->start_using(); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + + glsafe(::glClear(GL_DEPTH_BUFFER_BIT)); + glsafe(::glEnable(GL_DEPTH_TEST)); + const bool old_cullface = ::glIsEnabled(GL_CULL_FACE); + glsafe(::glDisable(GL_CULL_FACE)); + + const Transform3d& view_matrix = camera.get_view_matrix(); + + auto set_matrix_uniforms = [shader, &view_matrix](const Transform3d& model_matrix) { + const Transform3d view_model_matrix = view_matrix * model_matrix; + shader->set_uniform("view_model_matrix", view_model_matrix); + const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); + shader->set_uniform("view_normal_matrix", view_normal_matrix); + }; + + auto set_emission_uniform = [shader](const ColorRGBA& color, bool hover) { + shader->set_uniform("emission_factor", (color == GLVolume::SELECTED_COLOR) ? 0.0f : + hover ? 0.5f : 0.25f); + }; + + auto render_feature = [this, set_matrix_uniforms, set_emission_uniform](const Measure::SurfaceFeature& feature, const std::vector& colors, + float inv_zoom, bool hover, bool update_raycasters_transform) { + switch (feature.get_type()) + { + default: { assert(false); break; } + case Measure::SurfaceFeatureType::Point: + { + const Transform3d feature_matrix = Geometry::translation_transform(feature.get_point()) * Geometry::scale_transform(inv_zoom); + set_matrix_uniforms(feature_matrix); + set_emission_uniform(colors.front(), hover); + m_sphere.model.set_color(colors.front()); + m_sphere.model.render(); + if (update_raycasters_transform) { + auto it = m_raycasters.find(POINT_ID); + if (it != m_raycasters.end() && it->second != nullptr) + it->second->set_transform(feature_matrix); + } + break; + } + case Measure::SurfaceFeatureType::Circle: + { + const auto& [center, radius, normal] = feature.get_circle(); + // render circle + const Transform3d circle_matrix = Transform3d::Identity(); + set_matrix_uniforms(circle_matrix); + if (update_raycasters_transform) { + set_emission_uniform(colors.front(), hover); + m_circle.model.set_color(colors.front()); + m_circle.model.render(); + auto it = m_raycasters.find(CIRCLE_ID); + if (it != m_raycasters.end() && it->second != nullptr) + it->second->set_transform(circle_matrix); + } + else { + GLModel circle; + GLModel::Geometry circle_geometry = init_torus_data(64, 16, center.cast(), float(radius), 5.0f * inv_zoom, normal.cast(), Transform3f::Identity()); + circle.init_from(std::move(circle_geometry)); + set_emission_uniform(colors.front(), hover); + circle.set_color(colors.front()); + circle.render(); + } + // render center + if (colors.size() > 1) { + const Transform3d center_matrix = Geometry::translation_transform(center) * Geometry::scale_transform(inv_zoom); + set_matrix_uniforms(center_matrix); + set_emission_uniform(colors.back(), hover); + m_sphere.model.set_color(colors.back()); + m_sphere.model.render(); + auto it = m_raycasters.find(POINT_ID); + if (it != m_raycasters.end() && it->second != nullptr) + it->second->set_transform(center_matrix); + } + break; + } + case Measure::SurfaceFeatureType::Edge: + { + const auto& [from, to] = feature.get_edge(); + // render edge + const Transform3d edge_matrix = Geometry::translation_transform(from) * + Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), to - from) * + Geometry::scale_transform({ (double)inv_zoom, (double)inv_zoom, (to - from).norm() }); + set_matrix_uniforms(edge_matrix); + set_emission_uniform(colors.front(), hover); + m_cylinder.model.set_color(colors.front()); + m_cylinder.model.render(); + if (update_raycasters_transform) { + auto it = m_raycasters.find(EDGE_ID); + if (it != m_raycasters.end() && it->second != nullptr) + it->second->set_transform(edge_matrix); + } + + // render extra point + if (colors.size() > 1) { + const std::optional extra = feature.get_extra_point(); + if (extra.has_value()) { + const Transform3d point_matrix = Geometry::translation_transform(*extra) * Geometry::scale_transform(inv_zoom); + set_matrix_uniforms(point_matrix); + set_emission_uniform(colors.back(), hover); + m_sphere.model.set_color(colors.back()); + m_sphere.model.render(); + auto it = m_raycasters.find(POINT_ID); + if (it != m_raycasters.end() && it->second != nullptr) + it->second->set_transform(point_matrix); + } + } + break; + } + case Measure::SurfaceFeatureType::Plane: + { + const auto& [idx, normal, pt] = feature.get_plane(); + assert(idx < m_plane_models_cache.size()); + set_matrix_uniforms(Transform3d::Identity()); + set_emission_uniform(colors.front(), hover); + m_plane_models_cache[idx].set_color(colors.front()); + m_plane_models_cache[idx].render(); + if (update_raycasters_transform) { + auto it = m_raycasters.find(PLANE_ID); + if (it != m_raycasters.end() && it->second != nullptr) + it->second->set_transform(Transform3d::Identity()); + } + break; + } + } + }; + + auto hover_selection_color = [this]() { + return ((m_mode == EMode::PointSelection && !m_selected_features.first.feature.has_value()) || + (m_mode != EMode::PointSelection && (!m_selected_features.first.feature.has_value() || *m_curr_feature == *m_selected_features.first.feature))) ? + SELECTED_1ST_COLOR : SELECTED_2ND_COLOR; + }; + + auto hovering_color = [this, hover_selection_color]() { + return (m_mode == EMode::PointSelection) ? GLVolume::SELECTED_COLOR : hover_selection_color(); + }; + + if (m_curr_feature.has_value()) { + // render hovered feature + + std::vector colors; + if (m_selected_features.first.feature.has_value() && *m_curr_feature == *m_selected_features.first.feature) { + // hovering over the 1st selected feature + if (m_selected_features.first.is_center) + // hovering over a center + colors = { NEUTRAL_COLOR, hovering_color() }; + else if (is_feature_with_center(*m_selected_features.first.feature)) + // hovering over a feature with center + colors = { hovering_color(), NEUTRAL_COLOR }; + else + colors = { hovering_color() }; + } + else if (m_selected_features.second.feature.has_value() && *m_curr_feature == *m_selected_features.second.feature) { + // hovering over the 2nd selected feature + if (m_selected_features.second.is_center) + // hovering over a center + colors = { NEUTRAL_COLOR, hovering_color() }; + else if (is_feature_with_center(*m_selected_features.second.feature)) + // hovering over a feature with center + colors = { hovering_color(), NEUTRAL_COLOR }; + else + colors = { hovering_color() }; + } + else { + switch (m_curr_feature->get_type()) + { + default: { assert(false); break; } + case Measure::SurfaceFeatureType::Point: + { + colors.emplace_back(hover_selection_color()); + break; + } + case Measure::SurfaceFeatureType::Edge: + case Measure::SurfaceFeatureType::Circle: + { + if (m_selected_features.first.is_center && m_curr_feature == m_selected_features.first.source) + colors = { SELECTED_1ST_COLOR, NEUTRAL_COLOR }; + else if (m_selected_features.second.is_center && m_curr_feature == m_selected_features.second.source) + colors = { SELECTED_2ND_COLOR, NEUTRAL_COLOR }; + else + colors = { hovering_color(), hovering_color() }; + break; + } + case Measure::SurfaceFeatureType::Plane: + { + colors.emplace_back(hovering_color()); + break; + } + } + } + + render_feature(*m_curr_feature, colors, inv_zoom, true, true); + } + + if (m_selected_features.first.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.first.feature)) { + // render 1st selected feature + + std::optional feature_to_render; + std::vector colors; + bool requires_raycaster_update = false; + if (m_hover_id == SEL_SPHERE_1_ID && (m_selected_features.first.is_center || is_feature_with_center(*m_selected_features.first.feature))) { + // hovering over a center + feature_to_render = m_selected_features.first.source; + colors = { NEUTRAL_COLOR, SELECTED_1ST_COLOR }; + requires_raycaster_update = true; + } + else if (is_feature_with_center(*m_selected_features.first.feature)) { + // hovering over a feature with center + feature_to_render = m_selected_features.first.feature; + colors = { SELECTED_1ST_COLOR, NEUTRAL_COLOR }; + requires_raycaster_update = true; + } + else { + feature_to_render = m_selected_features.first.feature; + colors = { SELECTED_1ST_COLOR }; + requires_raycaster_update = m_selected_features.first.feature->get_type() == Measure::SurfaceFeatureType::Point; + } + + render_feature(*feature_to_render, colors, inv_zoom, m_hover_id == SEL_SPHERE_1_ID, false); + + if (requires_raycaster_update) { + auto it = std::find_if(m_selected_sphere_raycasters.begin(), m_selected_sphere_raycasters.end(), + [](std::shared_ptr item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SEL_SPHERE_1_ID; }); + if (it != m_selected_sphere_raycasters.end()) + (*it)->set_transform(Geometry::translation_transform(get_feature_offset(*m_selected_features.first.feature)) * Geometry::scale_transform(inv_zoom)); + } + } + + if (m_selected_features.second.feature.has_value() && (!m_curr_feature.has_value() || *m_curr_feature != *m_selected_features.second.feature)) { + // render 2nd selected feature + + std::optional feature_to_render; + std::vector colors; + bool requires_raycaster_update = false; + if (m_hover_id == SEL_SPHERE_2_ID && (m_selected_features.second.is_center || is_feature_with_center(*m_selected_features.second.feature))) { + // hovering over a center + feature_to_render = m_selected_features.second.source; + colors = { NEUTRAL_COLOR, SELECTED_2ND_COLOR }; + requires_raycaster_update = true; + } + else if (is_feature_with_center(*m_selected_features.second.feature)) { + // hovering over a feature with center + feature_to_render = m_selected_features.second.feature; + colors = { SELECTED_2ND_COLOR, NEUTRAL_COLOR }; + requires_raycaster_update = true; + } + else { + feature_to_render = m_selected_features.second.feature; + colors = { SELECTED_2ND_COLOR }; + requires_raycaster_update = m_selected_features.second.feature->get_type() == Measure::SurfaceFeatureType::Point; + } + + render_feature(*feature_to_render, colors, inv_zoom, m_hover_id == SEL_SPHERE_2_ID, false); + + if (requires_raycaster_update) { + auto it = std::find_if(m_selected_sphere_raycasters.begin(), m_selected_sphere_raycasters.end(), + [](std::shared_ptr item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == SEL_SPHERE_2_ID; }); + if (it != m_selected_sphere_raycasters.end()) + (*it)->set_transform(Geometry::translation_transform(get_feature_offset(*m_selected_features.second.feature)) * Geometry::scale_transform(inv_zoom)); + } + } + + if (is_hovering_on_feature && m_curr_point_on_feature_position.has_value()) { + if (m_hover_id != POINT_ID) { + // render point on feature while SHIFT is pressed + const Transform3d matrix = Geometry::translation_transform(*m_curr_point_on_feature_position) * Geometry::scale_transform(inv_zoom); + set_matrix_uniforms(matrix); + const ColorRGBA color = hover_selection_color(); + set_emission_uniform(color, true); + m_sphere.model.set_color(color); + m_sphere.model.render(); + } + } + + shader->stop_using(); + + if (old_cullface) + glsafe(::glEnable(GL_CULL_FACE)); render_dimensioning(); } @@ -968,61 +1049,51 @@ void GLGizmoMeasure::update_if_needed() } }; - auto do_update = [this, update_plane_models_cache](const ModelObject* object, const ModelVolume* volume) { - const indexed_triangle_set& its = (volume != nullptr) ? volume->mesh().its : object->volumes.front()->mesh().its; - m_measuring.reset(new Measure::Measuring(its)); + auto do_update = [this, update_plane_models_cache](const std::vector& volumes_cache, const Selection& selection) { + TriangleMesh composite_mesh; + for (const auto& vol : volumes_cache) { +// if (selection.is_single_full_instance() && vol.volume->is_modifier()) +// continue; - update_plane_models_cache(its); - - // Let's save what we calculated it from: - m_volumes_matrices.clear(); - m_volumes_types.clear(); - m_first_instance_scale = Vec3d::Ones(); - m_first_instance_mirror = Vec3d::Ones(); - if (object != nullptr) { - for (const ModelVolume* vol : object->volumes) { - m_volumes_matrices.push_back(vol->get_matrix()); - m_volumes_types.push_back(vol->type()); - } - m_first_instance_scale = object->instances.front()->get_scaling_factor(); - m_first_instance_mirror = object->instances.front()->get_mirror(); + TriangleMesh volume_mesh = vol.volume->mesh(); + volume_mesh.transform(vol.world_trafo); + composite_mesh.merge(volume_mesh); } - m_old_model_object = object; - m_old_model_volume = volume; + + m_measuring.reset(new Measure::Measuring(composite_mesh.its)); + update_plane_models_cache(m_measuring->get_mesh().its); + m_raycaster.reset(new MeshRaycaster(std::make_shared(m_measuring->get_mesh()))); + m_volumes_cache = volumes_cache; }; const Selection& selection = m_parent.get_selection(); if (selection.is_empty()) return; - m_volume_matrix = selection.get_first_volume()->world_matrix(); + const Selection::IndicesList& idxs = selection.get_volume_idxs(); + std::vector volumes_cache; + volumes_cache.reserve(idxs.size()); + for (unsigned int idx : idxs) { + const GLVolume* v = selection.get_volume(idx); + const int volume_idx = v->volume_idx(); + if (volume_idx < 0) + continue; - const ModelObject* mo = m_c->selection_info()->model_object(); - const ModelVolume* mv = m_c->selection_info()->model_volume(); - if (m_state != On || (mo == nullptr && mv == nullptr)) - return; - - if (mo == nullptr) - mo = mv->get_object(); - - if (mo->instances.empty()) - return; - - if (!m_measuring || mo != m_old_model_object || mv != m_old_model_volume || mo->volumes.size() != m_volumes_matrices.size()) - do_update(mo, mv); - - // We want to recalculate when the scale changes - some planes could (dis)appear. - if (!mo->instances.front()->get_scaling_factor().isApprox(m_first_instance_scale) || - !mo->instances.front()->get_mirror().isApprox(m_first_instance_mirror)) - do_update(mo, mv); - - for (unsigned int i = 0; i < mo->volumes.size(); ++i) { - if (!mo->volumes[i]->get_matrix().isApprox(m_volumes_matrices[i]) || - mo->volumes[i]->type() != m_volumes_types[i]) { - do_update(mo, mv); - break; - } + const ModelObject* obj = selection.get_model()->objects[v->object_idx()]; + const ModelInstance* inst = obj->instances[v->instance_idx()]; + const ModelVolume* vol = obj->volumes[volume_idx]; + const VolumeCacheItem item = { + obj, inst, vol, + Geometry::translation_transform(selection.get_first_volume()->get_sla_shift_z() * Vec3d::UnitZ()) * inst->get_matrix() * vol->get_matrix() + }; + volumes_cache.emplace_back(item); } + + if (m_state != On || volumes_cache.empty()) + return; + + if (m_measuring == nullptr || m_volumes_cache != volumes_cache) + do_update(volumes_cache, selection); } void GLGizmoMeasure::disable_scene_raycasters() @@ -1043,14 +1114,17 @@ void GLGizmoMeasure::render_dimensioning() { static SelectedFeatures last_selected_features; - if (!m_selected_features.first.feature.has_value() || !m_selected_features.second.feature.has_value()) + if (!m_selected_features.first.feature.has_value()) + return; + + if (!m_selected_features.second.feature.has_value() && m_selected_features.first.feature->get_type() != Measure::SurfaceFeatureType::Circle) return; GLShaderProgram* shader = wxGetApp().get_shader("flat"); if (shader == nullptr) return; - auto point_point = [this, shader](const Vec3d& v1, const Vec3d& v2, float distance) { + auto point_point = [this, &shader](const Vec3d& v1, const Vec3d& v2, float distance) { if ((v2 - v1).squaredNorm() < 0.000001 || distance < 0.001f) return; @@ -1080,6 +1154,25 @@ void GLGizmoMeasure::render_dimensioning() const Transform3d ss_to_ndc_matrix = TransformHelper::ndc_to_ss_matrix_inverse(viewport); +#if ENABLE_GL_CORE_PROFILE + if (OpenGLManager::get_gl_info().is_core_profile()) { + shader->stop_using(); + + shader = wxGetApp().get_shader("dashed_thick_lines"); + if (shader == nullptr) + return; + + shader->start_using(); + shader->set_uniform("projection_matrix", Transform3d::Identity()); + const std::array& viewport = camera.get_viewport(); + shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3]))); + shader->set_uniform("width", 1.0f); + shader->set_uniform("gap_size", 0.0f); + } + else +#endif // ENABLE_GL_CORE_PROFILE + glsafe(::glLineWidth(2.0f)); + // stem shader->set_uniform("view_model_matrix", overlap ? ss_to_ndc_matrix * Geometry::translation_transform(v1ss_3) * q12ss * Geometry::translation_transform(-2.0 * TRIANGLE_HEIGHT * Vec3d::UnitX()) * Geometry::scale_transform({ v12ss_len + 4.0 * TRIANGLE_HEIGHT, 1.0f, 1.0f }) : @@ -1087,6 +1180,20 @@ void GLGizmoMeasure::render_dimensioning() m_dimensioning.line.set_color(ColorRGBA::WHITE()); m_dimensioning.line.render(); +#if ENABLE_GL_CORE_PROFILE + if (OpenGLManager::get_gl_info().is_core_profile()) { + shader->stop_using(); + + shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) + return; + + shader->start_using(); + } + else +#endif // ENABLE_GL_CORE_PROFILE + glsafe(::glLineWidth(1.0f)); + // arrow 1 shader->set_uniform("view_model_matrix", overlap ? ss_to_ndc_matrix * Geometry::translation_transform(v1ss_3) * q12ss : @@ -1115,8 +1222,17 @@ void GLGizmoMeasure::render_dimensioning() ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 1.0f, 1.0f }); m_imgui->begin(std::string("distance"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration); + ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow()); ImGui::AlignTextToFramePadding(); - m_imgui->text(curr_value_str + " " + units); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + const ImVec2 pos = ImGui::GetCursorScreenPos(); + const std::string txt = curr_value_str + " " + units; + ImVec2 txt_size = ImGui::CalcTextSize(txt.c_str()); + const ImGuiStyle& style = ImGui::GetStyle(); + draw_list->AddRectFilled({ pos.x - style.FramePadding.x, pos.y + style.FramePadding.y }, { pos.x + txt_size.x + 2.0f * style.FramePadding.x , pos.y + txt_size.y + 2.0f * style.FramePadding.y }, + ImGuiWrapper::to_ImU32(ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f))); + ImGui::SetCursorScreenPos({ pos.x + style.FramePadding.x, pos.y }); + m_imgui->text(txt); ImGui::SameLine(); if (m_imgui->image_button(ImGui::SliderFloatEditBtnIcon, _L("Edit to scale"))) { m_editing_distance = true; @@ -1142,18 +1258,76 @@ void GLGizmoMeasure::render_dimensioning() const double ratio = new_value / old_value; wxGetApp().plater()->take_snapshot(_L("Scale")); + struct TrafoData + { + double ratio; + Vec3d old_pivot; + Vec3d new_pivot; + Transform3d scale_matrix; + + TrafoData(double ratio, const Vec3d& old_pivot, const Vec3d& new_pivot) { + this->ratio = ratio; + this->scale_matrix = Geometry::scale_transform(ratio); + this->old_pivot = old_pivot; + this->new_pivot = new_pivot; + } + + Vec3d transform(const Vec3d& point) const { return this->scale_matrix * (point - this->old_pivot) + this->new_pivot; } + }; + + auto scale_feature = [](Measure::SurfaceFeature& feature, const TrafoData& trafo_data) { + switch (feature.get_type()) + { + case Measure::SurfaceFeatureType::Point: + { + feature = Measure::SurfaceFeature(trafo_data.transform(feature.get_point())); + break; + } + case Measure::SurfaceFeatureType::Edge: + { + const auto [from, to] = feature.get_edge(); + const std::optional extra = feature.get_extra_point(); + const std::optional new_extra = extra.has_value() ? trafo_data.transform(*extra) : extra; + feature = Measure::SurfaceFeature(Measure::SurfaceFeatureType::Edge, trafo_data.transform(from), trafo_data.transform(to), new_extra); + break; + } + case Measure::SurfaceFeatureType::Circle: + { + const auto [center, radius, normal] = feature.get_circle(); + feature = Measure::SurfaceFeature(Measure::SurfaceFeatureType::Circle, trafo_data.transform(center), normal, std::nullopt, trafo_data.ratio * radius); + break; + } + case Measure::SurfaceFeatureType::Plane: + { + const auto [idx, normal, origin] = feature.get_plane(); + feature = Measure::SurfaceFeature(Measure::SurfaceFeatureType::Plane, normal, trafo_data.transform(origin), std::nullopt, idx); + break; + } + default: { break; } + } + }; + + // apply scale TransformationType type; type.set_world(); type.set_relative(); type.set_joint(); - // apply scale + // scale selection Selection& selection = m_parent.get_selection(); + const Vec3d old_center = selection.get_bounding_box().center(); selection.setup_cache(); selection.scale(ratio * Vec3d::Ones(), type); wxGetApp().plater()->canvas3D()->do_scale(""); // avoid storing another snapshot wxGetApp().obj_manipul()->set_dirty(); + // scale dimensioning + const Vec3d new_center = selection.get_bounding_box().center(); + const TrafoData trafo_data(ratio, old_center, new_center); + scale_feature(*m_selected_features.first.feature, trafo_data); + if (m_selected_features.second.feature.has_value()) + scale_feature(*m_selected_features.second.feature, trafo_data); + // update measure on next call to data_changed() m_pending_scale = true; }; @@ -1199,12 +1373,7 @@ void GLGizmoMeasure::render_dimensioning() auto point_edge = [this, shader](const Measure::SurfaceFeature& f1, const Measure::SurfaceFeature& f2) { assert(f1.get_type() == Measure::SurfaceFeatureType::Point && f2.get_type() == Measure::SurfaceFeatureType::Edge); std::pair e = f2.get_edge(); - // Transform to world coordinates - e.first = TransformHelper::model_to_world(e.first, m_volume_matrix); - e.second = TransformHelper::model_to_world(e.second, m_volume_matrix); - const Vec3d v_proj = m_measurement_result.distance_infinite->to; - const Vec3d e1e2 = e.second - e.first; const Vec3d v_proje1 = v_proj - e.first; const bool on_e1_side = v_proje1.dot(e1e2) < -EPSILON; @@ -1236,7 +1405,7 @@ void GLGizmoMeasure::render_dimensioning() } }; - auto arc_edge_edge = [this, shader](const Measure::SurfaceFeature& f1, const Measure::SurfaceFeature& f2, double radius = 0.0) { + auto arc_edge_edge = [this, &shader](const Measure::SurfaceFeature& f1, const Measure::SurfaceFeature& f2, double radius = 0.0) { assert(f1.get_type() == Measure::SurfaceFeatureType::Edge && f2.get_type() == Measure::SurfaceFeatureType::Edge); if (!m_measurement_result.angle.has_value()) return; @@ -1278,18 +1447,51 @@ void GLGizmoMeasure::render_dimensioning() m_dimensioning.arc.init_from(std::move(init_data)); } - // arc const Camera& camera = wxGetApp().plater()->get_camera(); +#if ENABLE_GL_CORE_PROFILE + if (OpenGLManager::get_gl_info().is_core_profile()) { + shader->stop_using(); + + shader = wxGetApp().get_shader("dashed_thick_lines"); + if (shader == nullptr) + return; + + shader->start_using(); + shader->set_uniform("projection_matrix", Transform3d::Identity()); + const std::array& viewport = camera.get_viewport(); + shader->set_uniform("viewport_size", Vec2d(double(viewport[2]), double(viewport[3]))); + shader->set_uniform("width", 1.0f); + shader->set_uniform("gap_size", 0.0f); + } + else +#endif // ENABLE_GL_CORE_PROFILE + glsafe(::glLineWidth(2.0f)); + + // arc shader->set_uniform("projection_matrix", camera.get_projection_matrix()); shader->set_uniform("view_model_matrix", camera.get_view_matrix() * Geometry::translation_transform(center)); m_dimensioning.arc.render(); +#if ENABLE_GL_CORE_PROFILE + if (OpenGLManager::get_gl_info().is_core_profile()) { + shader->stop_using(); + + shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) + return; + + shader->start_using(); + } + else +#endif // ENABLE_GL_CORE_PROFILE + glsafe(::glLineWidth(1.0f)); + // arrows auto render_arrow = [this, shader, &camera, &normal, ¢er, &e1_unit, draw_radius, step, resolution](unsigned int endpoint_id) { const double angle = (endpoint_id == 1) ? 0.0 : step * double(resolution); const Vec3d position_model = Geometry::translation_transform(center) * (draw_radius * (Eigen::Quaternion(Eigen::AngleAxisd(angle, normal)) * e1_unit)); const Vec3d direction_model = (endpoint_id == 1) ? -normal.cross(position_model - center).normalized() : normal.cross(position_model - center).normalized(); - const auto qz = Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), normal); + const auto qz = Eigen::Quaternion::FromTwoVectors(Vec3d::UnitZ(), (endpoint_id == 1) ? normal : -normal); const auto qx = Eigen::Quaternion::FromTwoVectors(qz * Vec3d::UnitX(), direction_model); const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::translation_transform(position_model) * qx * qz * Geometry::scale_transform(camera.get_inv_zoom()); @@ -1339,7 +1541,16 @@ void GLGizmoMeasure::render_dimensioning() ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); m_imgui->begin(_L("##angle"), ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove); ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow()); - m_imgui->text(format_double(Geometry::rad2deg(angle)) + "°"); + ImGui::AlignTextToFramePadding(); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + const ImVec2 pos = ImGui::GetCursorScreenPos(); + const std::string txt = format_double(Geometry::rad2deg(angle)) + "°"; + ImVec2 txt_size = ImGui::CalcTextSize(txt.c_str()); + const ImGuiStyle& style = ImGui::GetStyle(); + draw_list->AddRectFilled({ pos.x - style.FramePadding.x, pos.y + style.FramePadding.y }, { pos.x + txt_size.x + 2.0f * style.FramePadding.x , pos.y + txt_size.y + 2.0f * style.FramePadding.y }, + ImGuiWrapper::to_ImU32(ColorRGBA(0.5f, 0.5f, 0.5f, 0.5f))); + ImGui::SetCursorScreenPos({ pos.x + style.FramePadding.x, pos.y }); + m_imgui->text(txt); m_imgui->end(); ImGui::PopStyleVar(); }; @@ -1418,41 +1629,51 @@ void GLGizmoMeasure::render_dimensioning() glsafe(::glDisable(GL_DEPTH_TEST)); - if (m_selected_features.second.feature.has_value()) { - const bool has_distance = m_measurement_result.has_distance_data(); + const bool has_distance = m_measurement_result.has_distance_data(); - const Measure::SurfaceFeature* f1 = &(*m_selected_features.first.feature); - const Measure::SurfaceFeature* f2 = &(*m_selected_features.second.feature); - Measure::SurfaceFeatureType ft1 = f1->get_type(); - Measure::SurfaceFeatureType ft2 = f2->get_type(); - - // Order features by type so following conditions are simple. - if (ft1 > ft2) { - std::swap(ft1, ft2); - std::swap(f1, f2); - } - - // If there is an angle to show, draw the arc: - if (ft1 == Measure::SurfaceFeatureType::Edge && ft2 == Measure::SurfaceFeatureType::Edge) - arc_edge_edge(*f1, *f2); - else if (ft1 == Measure::SurfaceFeatureType::Edge && ft2 == Measure::SurfaceFeatureType::Plane) - arc_edge_plane(*f1, *f2); - else if (ft1 == Measure::SurfaceFeatureType::Plane && ft2 == Measure::SurfaceFeatureType::Plane) - arc_plane_plane(*f1, *f2); - - if (has_distance){ - // Where needed, draw the extension of the edge to where the dist is measured: - if (ft1 == Measure::SurfaceFeatureType::Point && ft2 == Measure::SurfaceFeatureType::Edge) - point_edge(*f1, *f2); - - // Render the arrow between the points that the backend passed: - const Measure::DistAndPoints& dap = m_measurement_result.distance_infinite.has_value() - ? *m_measurement_result.distance_infinite - : *m_measurement_result.distance_strict; - point_point(dap.from, dap.to, dap.dist); - } + const Measure::SurfaceFeature* f1 = &(*m_selected_features.first.feature); + const Measure::SurfaceFeature* f2 = nullptr; + std::unique_ptr temp_feature; + if (m_selected_features.second.feature.has_value()) + f2 = &(*m_selected_features.second.feature); + else { + assert(m_selected_features.first.feature->get_type() == Measure::SurfaceFeatureType::Circle); + temp_feature = std::make_unique(std::get<0>(m_selected_features.first.feature->get_circle())); + f2 = temp_feature.get(); } - + + if (!m_selected_features.second.feature.has_value() && m_selected_features.first.feature->get_type() != Measure::SurfaceFeatureType::Circle) + return; + + Measure::SurfaceFeatureType ft1 = f1->get_type(); + Measure::SurfaceFeatureType ft2 = f2->get_type(); + + // Order features by type so following conditions are simple. + if (ft1 > ft2) { + std::swap(ft1, ft2); + std::swap(f1, f2); + } + + // If there is an angle to show, draw the arc: + if (ft1 == Measure::SurfaceFeatureType::Edge && ft2 == Measure::SurfaceFeatureType::Edge) + arc_edge_edge(*f1, *f2); + else if (ft1 == Measure::SurfaceFeatureType::Edge && ft2 == Measure::SurfaceFeatureType::Plane) + arc_edge_plane(*f1, *f2); + else if (ft1 == Measure::SurfaceFeatureType::Plane && ft2 == Measure::SurfaceFeatureType::Plane) + arc_plane_plane(*f1, *f2); + + if (has_distance){ + // Where needed, draw the extension of the edge to where the dist is measured: + if (ft1 == Measure::SurfaceFeatureType::Point && ft2 == Measure::SurfaceFeatureType::Edge) + point_edge(*f1, *f2); + + // Render the arrow between the points that the backend passed: + const Measure::DistAndPoints& dap = m_measurement_result.distance_infinite.has_value() + ? *m_measurement_result.distance_infinite + : *m_measurement_result.distance_strict; + point_point(dap.from, dap.to, dap.dist); + } + glsafe(::glEnable(GL_DEPTH_TEST)); shader->stop_using(); @@ -1477,20 +1698,18 @@ static void add_strings_row_to_table(ImGuiWrapper& imgui, const std::string& col void GLGizmoMeasure::render_debug_dialog() { auto add_feature_data = [this](const SelectedFeatures::Item& item) { - add_strings_row_to_table(*m_imgui, "Type", ImGuiWrapper::COL_ORANGE_LIGHT, item.source, ImGui::GetStyleColorVec4(ImGuiCol_Text)); + const std::string text = (item.source == item.feature) ? surface_feature_type_as_string(item.feature->get_type()) : point_on_feature_type_as_string(item.source->get_type(), m_hover_id); + add_strings_row_to_table(*m_imgui, "Type", ImGuiWrapper::COL_ORANGE_LIGHT, text, ImGui::GetStyleColorVec4(ImGuiCol_Text)); switch (item.feature->get_type()) { case Measure::SurfaceFeatureType::Point: { - const Vec3d position = m_volume_matrix * item.feature->get_point(); - add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(position), ImGui::GetStyleColorVec4(ImGuiCol_Text)); + add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(item.feature->get_point()), ImGui::GetStyleColorVec4(ImGuiCol_Text)); break; } case Measure::SurfaceFeatureType::Edge: { auto [from, to] = item.feature->get_edge(); - from = m_volume_matrix * from; - to = m_volume_matrix * to; add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(from), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(to), ImGui::GetStyleColorVec4(ImGuiCol_Text)); break; @@ -1498,8 +1717,6 @@ void GLGizmoMeasure::render_debug_dialog() case Measure::SurfaceFeatureType::Plane: { auto [idx, normal, origin] = item.feature->get_plane(); - origin = m_volume_matrix * origin; - normal = m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal; add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(origin), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_value", ImGuiWrapper::COL_ORANGE_LIGHT, format_double(idx), ImGui::GetStyleColorVec4(ImGuiCol_Text)); @@ -1508,9 +1725,7 @@ void GLGizmoMeasure::render_debug_dialog() case Measure::SurfaceFeatureType::Circle: { auto [center, radius, normal] = item.feature->get_circle(); - const Vec3d on_circle = m_volume_matrix * (center + radius * Measure::get_orthogonal(normal, true)); - center = m_volume_matrix * center; - normal = (m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal).normalized(); + const Vec3d on_circle = center + radius * Measure::get_orthogonal(normal, true); radius = (on_circle - center).norm(); add_strings_row_to_table(*m_imgui, "m_pt1", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(center), ImGui::GetStyleColorVec4(ImGuiCol_Text)); add_strings_row_to_table(*m_imgui, "m_pt2", ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text)); @@ -1530,7 +1745,6 @@ void GLGizmoMeasure::render_debug_dialog() { case EMode::FeatureSelection: { txt = "Feature selection"; break; } case EMode::PointSelection: { txt = "Point selection"; break; } - case EMode::CenterSelection: { txt = "Center selection"; break; } default: { assert(false); break; } } add_strings_row_to_table(*m_imgui, "Mode", ImGuiWrapper::COL_ORANGE_LIGHT, txt, ImGui::GetStyleColorVec4(ImGuiCol_Text)); @@ -1606,30 +1820,114 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit std::string text; ColorRGBA color; if (m_selected_features.second.feature.has_value()) { - if (m_selected_features.second.feature == m_curr_feature && m_mode == EMode::FeatureSelection) + if (m_selected_features.first.feature == m_curr_feature && m_mode == EMode::FeatureSelection) { + // hovering over 1st selected feature text = _u8L("Unselect feature"); - else if (m_hover_id == SELECTION_2_ID) - text = (m_mode == EMode::CenterSelection) ? _u8L("Unselect center") : _u8L("Unselect point"); - else - text = (m_mode == EMode::PointSelection) ? _u8L("Select point") : - (m_mode == EMode::CenterSelection) ? _u8L("Select center") : _u8L("Select feature"); - color = SELECTED_2ND_COLOR; + color = SELECTED_1ST_COLOR; + } + else if (m_hover_id == SEL_SPHERE_1_ID) { + if (m_selected_features.first.is_center) { + // hovering over center selected as 1st feature + text = _u8L("Unselect center"); + color = SELECTED_1ST_COLOR; + } + else if (is_feature_with_center(*m_selected_features.first.feature)) { + // hovering over center of 1st selected feature + text = _u8L("Select center"); + color = SELECTED_1ST_COLOR; + } + else { + // hovering over point selected as 1st feature + text = _u8L("Unselect point"); + color = SELECTED_1ST_COLOR; + } + } + else if (m_selected_features.first.is_center && m_selected_features.first.source == m_curr_feature) { + // hovering over feature whose center is selected as 1st feature + text = _u8L("Select feature"); + color = SELECTED_1ST_COLOR; + } + else if (m_selected_features.second.feature == m_curr_feature && m_mode == EMode::FeatureSelection) { + // hovering over 2nd selected feature + text = _u8L("Unselect feature"); + color = SELECTED_2ND_COLOR; + } + else if (m_hover_id == SEL_SPHERE_2_ID) { + if (m_selected_features.second.is_center) { + // hovering over center selected as 2nd feature + text = _u8L("Unselect feature"); + color = SELECTED_2ND_COLOR; + } + else if (is_feature_with_center(*m_selected_features.second.feature)) { + // hovering over center of 2nd selected feature + text = _u8L("Select center"); + color = SELECTED_2ND_COLOR; + } + else { + // hovering over point selected as 2nd feature + text = _u8L("Unselect point"); + color = SELECTED_2ND_COLOR; + } + } + else if (m_selected_features.second.is_center && m_selected_features.second.source == m_curr_feature) { + // hovering over feature whose center is selected as 2nd feature + text = _u8L("Select feature"); + color = SELECTED_2ND_COLOR; + } + else { + // 1st feature selected + text = (m_mode == EMode::PointSelection) ? _u8L("Select point") : _u8L("Select feature"); + color = SELECTED_2ND_COLOR; + } } else { if (m_selected_features.first.feature.has_value()) { - if (m_selected_features.first.feature == m_curr_feature) + if (m_selected_features.first.feature == m_curr_feature && m_mode == EMode::FeatureSelection) { + // hovering over 1st selected feature text = _u8L("Unselect feature"); - else if (m_hover_id == SELECTION_1_ID) - text = (m_mode == EMode::CenterSelection) ? _u8L("Unselect center") : _u8L("Unselect point"); + color = SELECTED_1ST_COLOR; + } + else { + if (m_hover_id == SEL_SPHERE_1_ID) { + if (m_selected_features.first.is_center) { + // hovering over center selected as 1st feature + text = _u8L("Unselect feature"); + color = SELECTED_1ST_COLOR; + } + else if (is_feature_with_center(*m_selected_features.first.feature)) { + // hovering over center of 1st selected feature + text = _u8L("Select center"); + color = SELECTED_1ST_COLOR; + } + else { + // hovering over point selected as 1st feature + text = _u8L("Unselect point"); + color = SELECTED_1ST_COLOR; + } + } + else { + if (m_selected_features.first.is_center && m_selected_features.first.source == m_curr_feature) { + // hovering over feature whose center is selected as 1st feature + text = _u8L("Select feature"); + color = SELECTED_1ST_COLOR; + } + else { + // 1st feature selected + text = (m_mode == EMode::PointSelection) ? _u8L("Select point") : _u8L("Select feature"); + color = SELECTED_2ND_COLOR; + } + } + } + } + else { + // nothing is selected + text = (m_mode == EMode::PointSelection) ? _u8L("Select point") : _u8L("Select feature"); color = SELECTED_1ST_COLOR; } - if (text.empty()) { - text = (m_mode == EMode::PointSelection) ? _u8L("Select point") : - (m_mode == EMode::CenterSelection) ? _u8L("Select center") : _u8L("Select feature"); - color = m_selected_features.first.feature.has_value() ? SELECTED_2ND_COLOR : SELECTED_1ST_COLOR; - } } + assert(!text.empty()); + m_imgui->text_colored(ImGui::GetStyleColorVec4(ImGuiCol_Text), text); ImGui::SameLine(); const ImVec2 pos = ImGui::GetCursorScreenPos(); @@ -1644,14 +1942,28 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit ++row_count; } - if (m_mode != EMode::CenterSelection && feature_has_center(m_curr_feature)) { - add_strings_row_to_table(*m_imgui, _u8L("Shift") + "+" + CTRL_STR, ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Enable center selection"), ImGui::GetStyleColorVec4(ImGuiCol_Text)); + if (m_selected_features.first.feature.has_value()) { + add_strings_row_to_table(*m_imgui, _u8L("Delete"), ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Restart selection"), ImGui::GetStyleColorVec4(ImGuiCol_Text)); ++row_count; } - if (m_selected_features.first.feature.has_value()) { - add_strings_row_to_table(*m_imgui, _u8L("Shift") + "+" + _u8L("Right mouse button"), ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Restart selection"), ImGui::GetStyleColorVec4(ImGuiCol_Text)); - ++row_count; + if (m_selected_features.first.feature.has_value() || m_selected_features.second.feature.has_value()) { + add_row_to_table( + [this]() { + m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _u8L("Esc")); + }, + [this]() { + m_imgui->text_colored(ImGui::GetStyleColorVec4(ImGuiCol_Text), _u8L("Unselect")); + ImGui::SameLine(); + const ImVec2 pos = ImGui::GetCursorScreenPos(); + const float rect_size = ImGui::GetTextLineHeight(); + const ColorRGBA color = m_selected_features.second.feature.has_value() ? SELECTED_2ND_COLOR : SELECTED_1ST_COLOR; + ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + 1.0f, pos.y + 1.0f), ImVec2(pos.x + rect_size, pos.y + rect_size), ImGuiWrapper::to_ImU32(color)); + ImGui::Dummy(ImVec2(rect_size, rect_size)); + } + ); + + ++row_count; } // add dummy rows to keep dialog size fixed @@ -1665,127 +1977,40 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit const bool use_inches = wxGetApp().app_config->get("use_inches") == "1"; const std::string units = use_inches ? " " + _u8L("in") : " " + _u8L("mm"); - //const Measure::SurfaceFeatureType feature_type = m_curr_feature.has_value() ? m_curr_feature->get_type() : Measure::SurfaceFeatureType::Undef; - //bool data_text_set = false; - //ImGui::Separator(); - //if (feature_type != Measure::SurfaceFeatureType::Undef) { - // if (m_mode == EMode::FeatureSelection) { - // m_imgui->text(surface_feature_type_as_string(feature_type)); - // data_text_set = true; - // } - // else if (m_mode == EMode::PointSelection) { - // if (m_hover_id != -1 && m_curr_point_on_feature_position.has_value()) { - // m_imgui->text(point_on_feature_type_as_string(feature_type, m_hover_id)); - // data_text_set = true; - // } - // } - // else if (m_mode == EMode::CenterSelection) { - // if (m_hover_id != -1 && m_curr_point_on_feature_position.has_value()) { - // m_imgui->text(center_on_feature_type_as_string(feature_type)); - // data_text_set = true; - // } - // } - //} - //if (!data_text_set) - // m_imgui->text(_u8L("No feature")); - - //const unsigned int max_data_row_count = 3; - //unsigned int data_row_count = 0; - //if (ImGui::BeginTable("Data", 2)) { - // if (m_mode == EMode::FeatureSelection) { - // switch (feature_type) - // { - // default: { break; } - // case Measure::SurfaceFeatureType::Point: - // { - // Vec3d position = m_volume_matrix * m_curr_feature->get_point(); - // if (use_inches) - // position = ObjectManipulation::mm_to_in * position; - // add_strings_row_to_table(*m_imgui, _u8L("Position"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(position), ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // data_row_count = 1; - // break; - // } - // case Measure::SurfaceFeatureType::Edge: - // { - // auto [from, to] = m_curr_feature->get_edge(); - // from = m_volume_matrix * from; - // to = m_volume_matrix * to; - // if (use_inches) { - // from = ObjectManipulation::mm_to_in * from; - // to = ObjectManipulation::mm_to_in * to; - // } - // add_strings_row_to_table(*m_imgui, _u8L("From"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(from), ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // add_strings_row_to_table(*m_imgui, _u8L("To"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(to), ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // add_strings_row_to_table(*m_imgui, _u8L("Length"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double((to - from).norm()) + units, ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // data_row_count = 3; - // break; - // } - // case Measure::SurfaceFeatureType::Circle: - // { - // auto [center, radius, normal] = m_curr_feature->get_circle(); - // // generic point on circle, used to recalculate radius after transformation - // const Vec3d on_circle = m_volume_matrix * (center + radius * Measure::get_orthogonal(normal, true)); - // center = m_volume_matrix * center; - // normal = (m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal).normalized(); - // radius = (on_circle - center).norm(); - // if (use_inches) { - // center = ObjectManipulation::mm_to_in * center; - // radius = ObjectManipulation::mm_to_in * radius; - // } - // add_strings_row_to_table(*m_imgui, _u8L("Center"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(center), ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // add_strings_row_to_table(*m_imgui, _u8L("Radius"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(radius) + units, ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // add_strings_row_to_table(*m_imgui, _u8L("Normal"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // data_row_count = 3; - // break; - // } - // case Measure::SurfaceFeatureType::Plane: - // { - // auto [idx, normal, origin] = m_curr_feature->get_plane(); - // origin = m_volume_matrix * origin; - // normal = m_volume_matrix.matrix().block(0, 0, 3, 3).inverse().transpose() * normal; - // if (use_inches) - // origin = ObjectManipulation::mm_to_in * origin; - // add_strings_row_to_table(*m_imgui, _u8L("Origin"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(origin), ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // add_strings_row_to_table(*m_imgui, _u8L("Normal"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(normal), ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // data_row_count = 2; - // break; - // } - // } - // } - // else { - // if (m_hover_id != -1 && m_curr_point_on_feature_position.has_value()) { - // Vec3d position = m_volume_matrix * *m_curr_point_on_feature_position; - // if (use_inches) - // position = ObjectManipulation::mm_to_in * position; - // add_strings_row_to_table(*m_imgui, _u8L("Position"), ImGuiWrapper::COL_ORANGE_LIGHT, format_vec3(position), ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // data_row_count = 1; - // } - // } - - // // add dummy rows to keep dialog size fixed - // for (unsigned int i = data_row_count; i < max_data_row_count; ++i) { - // add_strings_row_to_table(*m_imgui, " ", ImGuiWrapper::COL_ORANGE_LIGHT, " ", ImGui::GetStyleColorVec4(ImGuiCol_Text)); - // } - // ImGui::EndTable(); - //} - ImGui::Separator(); const ImGuiTableFlags flags = ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersH; if (ImGui::BeginTable("Selection", 2, flags)) { - add_strings_row_to_table(*m_imgui, _u8L("Selection") + " 1:", ImGuiWrapper::to_ImVec4(SELECTED_1ST_COLOR), m_selected_features.first.feature.has_value() ? - m_selected_features.first.source : _u8L("None"), ImGuiWrapper::to_ImVec4(SELECTED_1ST_COLOR)); - add_strings_row_to_table(*m_imgui, _u8L("Selection") + " 2:", ImGuiWrapper::to_ImVec4(SELECTED_2ND_COLOR), m_selected_features.second.feature.has_value() ? - m_selected_features.second.source : _u8L("None"), ImGuiWrapper::to_ImVec4(SELECTED_2ND_COLOR)); + auto format_item_text = [this, use_inches, &units](const SelectedFeatures::Item& item) { + if (!item.feature.has_value()) + return _u8L("None"); + + std::string text = (item.source == item.feature) ? surface_feature_type_as_string(item.feature->get_type()) : + item.is_center ? center_on_feature_type_as_string(item.source->get_type()) : point_on_feature_type_as_string(item.source->get_type(), m_hover_id); + if (item.feature.has_value() && item.feature->get_type() == Measure::SurfaceFeatureType::Circle) { + auto [center, radius, normal] = item.feature->get_circle(); + const Vec3d on_circle = center + radius * Measure::get_orthogonal(normal, true); + radius = (on_circle - center).norm(); + if (use_inches) + radius = ObjectManipulation::mm_to_in * radius; + text += " (" + _u8L("Diameter:") + " " + format_double(2.0 * radius) + units + ")"; + } + return text; + }; + + add_strings_row_to_table(*m_imgui, _u8L("Selection") + " 1:", ImGuiWrapper::to_ImVec4(SELECTED_1ST_COLOR), format_item_text(m_selected_features.first), + ImGuiWrapper::to_ImVec4(SELECTED_1ST_COLOR)); + add_strings_row_to_table(*m_imgui, _u8L("Selection") + " 2:", ImGuiWrapper::to_ImVec4(SELECTED_2ND_COLOR), format_item_text(m_selected_features.second), + ImGuiWrapper::to_ImVec4(SELECTED_2ND_COLOR)); ImGui::EndTable(); } - //if (m_selected_features.first.feature.has_value()) { - // if (m_imgui->button(_u8L("Restart"))) { - // m_selected_features.reset(); - // m_selection_raycasters.clear(); - // m_imgui->set_requires_extra_frame(); - // } - //} + m_imgui->disabled_begin(!m_selected_features.first.feature.has_value()); + if (m_imgui->button(_u8L("Restart selection"))) { + m_selected_features.reset(); + m_selected_sphere_raycasters.clear(); + m_imgui->set_requires_extra_frame(); + } + m_imgui->disabled_end(); auto add_measure_row_to_table = [this](const std::string& col_1, const ImVec4& col_1_color, const std::string& col_2, const ImVec4& col_2_color) { ImGui::TableNextRow(); @@ -1821,7 +2046,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit if (use_inches) distance = ObjectManipulation::mm_to_in * distance; ImGui::PushID("ClipboardDistanceInfinite"); - add_measure_row_to_table(_u8L("Distance Infinite"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(distance) + units, + add_measure_row_to_table(_u8L("Distance"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(distance) + units, ImGui::GetStyleColorVec4(ImGuiCol_Text)); ++measure_row_count; ImGui::PopID(); @@ -1832,7 +2057,7 @@ void GLGizmoMeasure::on_render_input_window(float x, float y, float bottom_limit if (use_inches) distance = ObjectManipulation::mm_to_in * distance; ImGui::PushID("ClipboardDistanceStrict"); - add_measure_row_to_table(_u8L("Distance Strict"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(distance) + units, + add_measure_row_to_table(_u8L("Distance"), ImGuiWrapper::COL_ORANGE_LIGHT, format_double(distance) + units, ImGui::GetStyleColorVec4(ImGuiCol_Text)); ++measure_row_count; ImGui::PopID(); @@ -1878,7 +2103,26 @@ void GLGizmoMeasure::on_unregister_raycasters_for_picking() m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo); m_parent.set_raycaster_gizmos_on_top(false); m_raycasters.clear(); - m_selection_raycasters.clear(); + m_selected_sphere_raycasters.clear(); +} + +void GLGizmoMeasure::remove_selected_sphere_raycaster(int id) +{ + auto it = std::find_if(m_selected_sphere_raycasters.begin(), m_selected_sphere_raycasters.end(), + [id](std::shared_ptr item) { return SceneRaycaster::decode_id(SceneRaycaster::EType::Gizmo, item->get_id()) == id; }); + if (it != m_selected_sphere_raycasters.end()) + m_selected_sphere_raycasters.erase(it); + m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, id); +} + +void GLGizmoMeasure::update_measurement_result() +{ + if (!m_selected_features.first.feature.has_value()) + m_measurement_result = Measure::MeasurementResult(); + else if (m_selected_features.second.feature.has_value()) + m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get()); + else if (!m_selected_features.second.feature.has_value() && m_selected_features.first.feature->get_type() == Measure::SurfaceFeatureType::Circle) + m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, Measure::SurfaceFeature(std::get<0>(m_selected_features.first.feature->get_circle())), m_measuring.get()); } } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp index 7bfc2e8c93..4652a171b7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp @@ -4,12 +4,12 @@ #include "GLGizmoBase.hpp" #include "slic3r/GUI/GLModel.hpp" #include "slic3r/GUI/GUI_Utils.hpp" +#include "slic3r/GUI/MeshUtils.hpp" #include "libslic3r/Measure.hpp" +#include "libslic3r/Model.hpp" namespace Slic3r { -class ModelVolume; - enum class ModelVolumeType : int; namespace Measure { class Measuring; } @@ -24,20 +24,19 @@ class GLGizmoMeasure : public GLGizmoBase enum class EMode : unsigned char { FeatureSelection, - PointSelection, - CenterSelection + PointSelection }; struct SelectedFeatures { struct Item { - std::string source; + bool is_center{ false }; + std::optional source; std::optional feature; bool operator == (const Item& other) const { - if (this->source != other.source) return false; - return this->feature == other.feature; + return this->is_center == other.is_center && this->source == other.source && this->feature == other.feature; } bool operator != (const Item& other) const { @@ -45,7 +44,8 @@ class GLGizmoMeasure : public GLGizmoBase } void reset() { - source.clear(); + is_center = false; + source.reset(); feature.reset(); } }; @@ -68,6 +68,21 @@ class GLGizmoMeasure : public GLGizmoBase } }; + struct VolumeCacheItem + { + const ModelObject* object{ nullptr }; + const ModelInstance* instance{ nullptr }; + const ModelVolume* volume{ nullptr }; + Transform3d world_trafo; + + bool operator == (const VolumeCacheItem& other) const { + return this->object == other.object && this->instance == other.instance && this->volume == other.volume && + this->world_trafo.isApprox(other.world_trafo); + } + }; + + std::vector m_volumes_cache; + EMode m_mode{ EMode::FeatureSelection }; Measure::MeasurementResult m_measurement_result; @@ -85,10 +100,14 @@ class GLGizmoMeasure : public GLGizmoBase }; Dimensioning m_dimensioning; - Transform3d m_volume_matrix{ Transform3d::Identity() }; + // Uses a standalone raycaster and not the shared one because of the + // difference in how the mesh is updated + std::unique_ptr m_raycaster; + std::vector m_plane_models_cache; std::map> m_raycasters; - std::vector> m_selection_raycasters; + // used to keep the raycasters for point/center spheres + std::vector> m_selected_sphere_raycasters; std::optional m_curr_feature; std::optional m_curr_point_on_feature_position; struct SceneRaycasterState @@ -100,21 +119,14 @@ class GLGizmoMeasure : public GLGizmoBase std::vector m_scene_raycasters; // These hold information to decide whether recalculation is necessary: - std::vector m_volumes_matrices; - std::vector m_volumes_types; - Vec3d m_first_instance_scale{ Vec3d::Ones() }; - Vec3d m_first_instance_mirror{ Vec3d::Ones() }; float m_last_inv_zoom{ 0.0f }; std::optional m_last_circle; int m_last_plane_idx{ -1 }; bool m_mouse_left_down{ false }; // for detection left_up of this gizmo - const ModelObject* m_old_model_object{ nullptr }; - const ModelVolume* m_old_model_volume{ nullptr }; Vec2d m_mouse_pos{ Vec2d::Zero() }; - KeyAutoRepeatFilter m_ctrl_kar_filter; KeyAutoRepeatFilter m_shift_kar_filter; SelectedFeatures m_selected_features; @@ -147,17 +159,24 @@ public: bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); + bool wants_enter_leave_snapshots() const override { return true; } + std::string get_gizmo_entering_text() const override { return _u8L("Entering Measure gizmo"); } + std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Measure gizmo"); } + std::string get_action_snapshot_name() override { return _u8L("Measure gizmo editing"); } + protected: bool on_init() override; std::string on_get_name() const override; bool on_is_activable() const override; void on_render() override; void on_set_state() override; - CommonGizmosDataID on_get_requirements() const override; virtual void on_render_input_window(float x, float y, float bottom_limit) override; virtual void on_register_raycasters_for_picking() override; virtual void on_unregister_raycasters_for_picking() override; + + void remove_selected_sphere_raycaster(int id); + void update_measurement_result(); }; } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 23edd6143f..bb5ebfd260 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -362,7 +362,6 @@ void GLGizmoMove3D::on_render() #endif // ENABLE_WORLD_COORDINATE } -#if ENABLE_RAYCAST_PICKING void GLGizmoMove3D::on_register_raycasters_for_picking() { // the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account @@ -373,32 +372,6 @@ void GLGizmoMove3D::on_unregister_raycasters_for_picking() { m_parent.set_raycaster_gizmos_on_top(false); } -#else -void GLGizmoMove3D::on_render_for_picking() -{ - glsafe(::glDisable(GL_DEPTH_TEST)); - -#if ENABLE_WORLD_COORDINATE -#if ENABLE_LEGACY_OPENGL_REMOVAL - const Transform3d base_matrix = local_transform(m_parent.get_selection()); - for (int i = 0; i < 3; ++i) { - m_grabbers[i].matrix = base_matrix; - } -#else - glsafe(::glPushMatrix()); - transform_to_local(m_parent.get_selection()); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL - render_grabbers_for_picking(m_bounding_box); -#if ENABLE_LEGACY_OPENGL_REMOVAL -#else - glsafe(::glPopMatrix()); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL -#else - const BoundingBoxf3& box = m_parent.get_selection().get_bounding_box(); - render_grabbers_for_picking(box); -#endif // ENABLE_WORLD_COORDINATE -} -#endif // ENABLE_RAYCAST_PICKING double GLGizmoMove3D::calc_projection(const UpdateData& data) const { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index 7a4d82a41c..3a69e86efb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -62,12 +62,8 @@ protected: void on_stop_dragging() override; void on_dragging(const UpdateData& data) override; void on_render() override; -#if ENABLE_RAYCAST_PICKING virtual void on_register_raycasters_for_picking() override; virtual void on_unregister_raycasters_for_picking() override; -#else - void on_render_for_picking() override; -#endif // ENABLE_RAYCAST_PICKING private: double calc_projection(const UpdateData& data) const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 94aca4fdb7..d4261761f6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -138,9 +138,6 @@ private: ObjectID m_old_mo_id; size_t m_old_volumes_size = 0; void on_render() override {} -#if !ENABLE_RAYCAST_PICKING - void on_render_for_picking() override {} -#endif // !ENABLE_RAYCAST_PICKING public: GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 6c57df7e59..5b39c09291 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -256,33 +256,6 @@ void GLGizmoRotate::on_render() #endif // !ENABLE_LEGACY_OPENGL_REMOVAL } -#if !ENABLE_RAYCAST_PICKING -void GLGizmoRotate::on_render_for_picking() -{ - const Selection& selection = m_parent.get_selection(); - - glsafe(::glDisable(GL_DEPTH_TEST)); - -#if ENABLE_LEGACY_OPENGL_REMOVAL - m_grabbers.front().matrix = local_transform(selection); -#else - glsafe(::glPushMatrix()); - transform_to_local(selection); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL - -#if ENABLE_WORLD_COORDINATE - render_grabbers_for_picking(m_bounding_box); -#else - const BoundingBoxf3& box = selection.get_bounding_box(); - render_grabbers_for_picking(box); -#endif // ENABLE_WORLD_COORDINATE - -#if !ENABLE_LEGACY_OPENGL_REMOVAL - glsafe(::glPopMatrix()); -#endif // !ENABLE_LEGACY_OPENGL_REMOVAL -} -#endif // !ENABLE_RAYCAST_PICKING - #if ENABLE_WORLD_COORDINATE void GLGizmoRotate::init_data_from_selection(const Selection& selection) { @@ -906,7 +879,6 @@ void GLGizmoRotate3D::on_render() m_gizmos[Z].render(); } -#if ENABLE_RAYCAST_PICKING void GLGizmoRotate3D::on_register_raycasters_for_picking() { // the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account @@ -923,7 +895,6 @@ void GLGizmoRotate3D::on_unregister_raycasters_for_picking() } m_parent.set_raycaster_gizmos_on_top(false); } -#endif // ENABLE_RAYCAST_PICKING GLGizmoRotate3D::RotoptimzeWindow::RotoptimzeWindow(ImGuiWrapper * imgui, State & state, diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp index cbc0f104b3..d117a12192 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -98,9 +98,6 @@ protected: void on_start_dragging() override; void on_dragging(const UpdateData &data) override; void on_render() override; -#if !ENABLE_RAYCAST_PICKING - void on_render_for_picking() override; -#endif // !ENABLE_RAYCAST_PICKING private: #if ENABLE_LEGACY_OPENGL_REMOVAL @@ -189,16 +186,8 @@ protected: void on_dragging(const UpdateData &data) override; void on_render() override; -#if ENABLE_RAYCAST_PICKING virtual void on_register_raycasters_for_picking() override; virtual void on_unregister_raycasters_for_picking() override; -#else - void on_render_for_picking() override { - for (GLGizmoRotate& g : m_gizmos) { - g.render_for_picking(); - } - } -#endif // ENABLE_RAYCAST_PICKING void on_render_input_window(float x, float y, float bottom_limit) override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 03be5c2f4c..42c74594c7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -650,7 +650,6 @@ void GLGizmoScale3D::on_render() #endif // ENABLE_WORLD_COORDINATE } -#if ENABLE_RAYCAST_PICKING void GLGizmoScale3D::on_register_raycasters_for_picking() { // the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account @@ -661,29 +660,6 @@ void GLGizmoScale3D::on_unregister_raycasters_for_picking() { m_parent.set_raycaster_gizmos_on_top(false); } -#else -void GLGizmoScale3D::on_render_for_picking() -{ - glsafe(::glDisable(GL_DEPTH_TEST)); -#if ENABLE_WORLD_COORDINATE -#if ENABLE_LEGACY_OPENGL_REMOVAL - const Transform3d base_matrix = local_transform(m_parent.get_selection()); - for (int i = 0; i < 10; ++i) { - m_grabbers[i].matrix = base_matrix; - } -#else - glsafe(::glPushMatrix()); - transform_to_local(m_parent.get_selection()); -#endif // ENABLE_LEGACY_OPENGL_REMOVAL - render_grabbers_for_picking(m_bounding_box); -#if !ENABLE_LEGACY_OPENGL_REMOVAL - glsafe(::glPopMatrix()); -#endif // !ENABLE_LEGACY_OPENGL_REMOVAL -#else - render_grabbers_for_picking(m_parent.get_selection().get_bounding_box()); -#endif // ENABLE_WORLD_COORDINATE -} -#endif // !ENABLE_RAYCAST_PICKING #if ENABLE_LEGACY_OPENGL_REMOVAL void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2, const ColorRGBA& color) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp index d51cec8150..bf55115282 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp @@ -94,12 +94,8 @@ protected: virtual void on_stop_dragging() override; virtual void on_dragging(const UpdateData& data) override; virtual void on_render() override; -#if ENABLE_RAYCAST_PICKING virtual void on_register_raycasters_for_picking() override; virtual void on_unregister_raycasters_for_picking() override; -#else - virtual void on_render_for_picking() override; -#endif // ENABLE_RAYCAST_PICKING private: #if ENABLE_LEGACY_OPENGL_REMOVAL diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp index 8317b45d71..f95aad4953 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp @@ -38,9 +38,6 @@ protected: // must implement virtual bool on_init() override { return true;}; virtual void on_render() override; -#if !ENABLE_RAYCAST_PICKING - virtual void on_render_for_picking() override{}; -#endif // !ENABLE_RAYCAST_PICKING CommonGizmosDataID on_get_requirements() const override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp index 7db24bb115..9e94b9604b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.cpp @@ -10,9 +10,7 @@ namespace Slic3r { namespace GUI { static const ColorRGBA DISABLED_COLOR = ColorRGBA::DARK_GRAY(); -#if ENABLE_RAYCAST_PICKING static const int VOLUME_RAYCASTERS_BASE_ID = (int)SceneRaycaster::EIdBase::Gizmo; -#endif // ENABLE_RAYCAST_PICKING GLGizmoSlaBase::GLGizmoSlaBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id, SLAPrintObjectStep min_step) : GLGizmoBase(parent, icon_filename, sprite_id) @@ -87,9 +85,7 @@ void GLGizmoSlaBase::update_volumes() } } -#if ENABLE_RAYCAST_PICKING register_volume_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING } void GLGizmoSlaBase::render_volumes() @@ -111,7 +107,6 @@ void GLGizmoSlaBase::render_volumes() } -#if ENABLE_RAYCAST_PICKING void GLGizmoSlaBase::register_volume_raycasters_for_picking() { for (size_t i = 0; i < m_volumes.volumes.size(); ++i) { @@ -127,7 +122,6 @@ void GLGizmoSlaBase::unregister_volume_raycasters_for_picking() } m_volume_raycasters.clear(); } -#endif // ENABLE_RAYCAST_PICKING int GLGizmoSlaBase::last_completed_step(const SLAPrint& sla) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.hpp index ca87d75ac9..7bcc01b719 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaBase.hpp @@ -32,10 +32,8 @@ protected: void update_volumes(); void render_volumes(); -#if ENABLE_RAYCAST_PICKING void register_volume_raycasters_for_picking(); void unregister_volume_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING bool is_input_enabled() const { return m_input_enabled; } int get_min_sla_print_object_step() const { return m_min_sla_print_object_step; } @@ -48,9 +46,7 @@ private: GLVolumeCollection m_volumes; bool m_input_enabled{ false }; int m_min_sla_print_object_step{ -1 }; -#if ENABLE_RAYCAST_PICKING std::vector> m_volume_raycasters; -#endif // ENABLE_RAYCAST_PICKING }; } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 2884d49698..db908ea91d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -18,10 +18,8 @@ #include "libslic3r/PresetBundle.hpp" #include "libslic3r/SLAPrint.hpp" -#if ENABLE_RAYCAST_PICKING static const double CONE_RADIUS = 0.25; static const double CONE_HEIGHT = 0.75; -#endif // ENABLE_RAYCAST_PICKING namespace Slic3r { namespace GUI { @@ -47,12 +45,6 @@ bool GLGizmoSlaSupports::on_init() m_desc["clipping_of_view"] = _L("Clipping of view")+ ": "; m_desc["reset_direction"] = _L("Reset direction"); -#if !ENABLE_RAYCAST_PICKING - m_cone.init_from(its_make_cone(1., 1., 2 * PI / 24)); - m_cylinder.init_from(its_make_cylinder(1., 1., 2 * PI / 24.)); - m_sphere.init_from(its_make_sphere(1., (2 * M_PI) / 24.)); -#endif // !ENABLE_RAYCAST_PICKING - return true; } @@ -82,12 +74,10 @@ void GLGizmoSlaSupports::data_changed() if (mo->sla_points_status == sla::PointsStatus::Generating) get_data_from_backend(); -#if ENABLE_RAYCAST_PICKING if (m_point_raycasters.empty()) register_point_raycasters_for_picking(); else update_point_raycasters_for_picking_transform(); -#endif // ENABLE_RAYCAST_PICKING } // m_parent.toggle_model_objects_visibility(false); @@ -97,7 +87,6 @@ void GLGizmoSlaSupports::data_changed() void GLGizmoSlaSupports::on_render() { -#if ENABLE_RAYCAST_PICKING if (!m_sphere.model.is_initialized()) { indexed_triangle_set its = its_make_sphere(1.0, double(PI) / 12.0); m_sphere.model.init_from(its); @@ -108,12 +97,6 @@ void GLGizmoSlaSupports::on_render() m_cone.model.init_from(its); m_cone.mesh_raycaster = std::make_unique(std::make_shared(std::move(its))); } -#else - if (!m_cone.is_initialized()) - m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 12.0)); - if (!m_sphere.is_initialized()) - m_sphere.init_from(its_make_sphere(1.0, double(PI) / 12.0)); -#endif // ENABLE_RAYCAST_PICKING ModelObject* mo = m_c->selection_info()->model_object(); const Selection& selection = m_parent.get_selection(); @@ -129,12 +112,8 @@ void GLGizmoSlaSupports::on_render() glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_DEPTH_TEST)); -#if ENABLE_RAYCAST_PICKING render_volumes(); render_points(selection); -#else - render_points(selection, false); -#endif // ENABLE_RAYCAST_PICKING m_selection_rectangle.render(m_parent); m_c->object_clipper()->render_cut(); @@ -142,7 +121,6 @@ void GLGizmoSlaSupports::on_render() glsafe(::glDisable(GL_BLEND)); } -#if ENABLE_RAYCAST_PICKING void GLGizmoSlaSupports::on_register_raycasters_for_picking() { register_point_raycasters_for_picking(); @@ -154,20 +132,8 @@ void GLGizmoSlaSupports::on_unregister_raycasters_for_picking() unregister_point_raycasters_for_picking(); unregister_volume_raycasters_for_picking(); } -#else -void GLGizmoSlaSupports::on_render_for_picking() -{ - const Selection& selection = m_parent.get_selection(); - //glsafe(::glEnable(GL_DEPTH_TEST)); - render_points(selection, true); -} -#endif // ENABLE_RAYCAST_PICKING -#if ENABLE_RAYCAST_PICKING void GLGizmoSlaSupports::render_points(const Selection& selection) -#else -void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) -#endif // ENABLE_RAYCAST_PICKING { const size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size(); @@ -176,11 +142,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) return; #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); -#else - GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light"); -#endif // ENABLE_RAYCAST_PICKING if (shader == nullptr) return; @@ -220,7 +182,6 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) const sla::SupportPoint& support_point = m_editing_mode ? m_editing_cache[i].support_point : m_normal_cache[i]; const bool point_selected = m_editing_mode ? m_editing_cache[i].selected : false; -#if ENABLE_RAYCAST_PICKING const bool clipped = is_mesh_point_clipped(support_point.pos.cast()); if (i < m_point_raycasters.size()) { m_point_raycasters[i].first->set_active(!clipped); @@ -228,48 +189,28 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) } if (clipped) continue; -#else - if (is_mesh_point_clipped(support_point.pos.cast())) - continue; -#endif // ENABLE_RAYCAST_PICKING // First decide about the color of the point. -#if !ENABLE_RAYCAST_PICKING - if (picking) - render_color = picking_color_component(i); - else { -#endif // !ENABLE_RAYCAST_PICKING - if (size_t(m_hover_id) == i && m_editing_mode) // ignore hover state unless editing mode is active - render_color = { 0.f, 1.f, 1.f, 1.f }; - else { // neigher hover nor picking - bool supports_new_island = m_lock_unique_islands && support_point.is_new_island; - if (m_editing_mode) { - if (point_selected) - render_color = { 1.f, 0.3f, 0.3f, 1.f}; - else - if (supports_new_island) - render_color = { 0.3f, 0.3f, 1.f, 1.f }; - else - render_color = { 0.7f, 0.7f, 0.7f, 1.f }; - } + if (size_t(m_hover_id) == i && m_editing_mode) // ignore hover state unless editing mode is active + render_color = { 0.f, 1.f, 1.f, 1.f }; + else { // neigher hover nor picking + bool supports_new_island = m_lock_unique_islands && support_point.is_new_island; + if (m_editing_mode) { + if (point_selected) + render_color = { 1.f, 0.3f, 0.3f, 1.f}; else - render_color = { 0.5f, 0.5f, 0.5f, 1.f }; + if (supports_new_island) + render_color = { 0.3f, 0.3f, 1.f, 1.f }; + else + render_color = { 0.7f, 0.7f, 0.7f, 1.f }; } -#if !ENABLE_RAYCAST_PICKING + else + render_color = { 0.5f, 0.5f, 0.5f, 1.f }; } -#endif // !ENABLE_RAYCAST_PICKING #if ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING m_cone.model.set_color(render_color); m_sphere.model.set_color(render_color); -#else - m_cone.set_color(render_color); - m_sphere.set_color(render_color); -#endif // ENABLE_RAYCAST_PICKING -#if !ENABLE_RAYCAST_PICKING - if (!picking) -#endif // !ENABLE_RAYCAST_PICKING #else m_cone.set_color(-1, render_color); m_sphere.set_color(-1, render_color); @@ -299,19 +240,10 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) Eigen::Quaterniond q; q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast()); const Eigen::AngleAxisd aa(q); -#if !ENABLE_RAYCAST_PICKING - const double cone_radius = 0.25; // mm - const double cone_height = 0.75; -#endif // !ENABLE_RAYCAST_PICKING #if ENABLE_LEGACY_OPENGL_REMOVAL const Transform3d model_matrix = vol->world_matrix() * support_matrix * Transform3d(aa.toRotationMatrix()) * -#if ENABLE_RAYCAST_PICKING Geometry::translation_transform((CONE_HEIGHT + support_point.head_front_radius * RenderPointScale) * Vec3d::UnitZ()) * Geometry::rotation_transform({ double(PI), 0.0, 0.0 }) * Geometry::scale_transform({ CONE_RADIUS, CONE_RADIUS, CONE_HEIGHT }); -#else - Geometry::translation_transform((cone_height + support_point.head_front_radius * RenderPointScale) * Vec3d::UnitZ()) * - Geometry::rotation_transform({ double(PI), 0.0, 0.0 }), * Geometry::scale_transform({ cone_radius, cone_radius, cone_height }); -#endif // ENABLE_RAYCAST_PICKING shader->set_uniform("view_model_matrix", view_matrix * model_matrix); const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); @@ -323,11 +255,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) glsafe(::glRotated(180., 1., 0., 0.)); glsafe(::glScaled(cone_radius, cone_radius, cone_height)); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING m_cone.model.render(); -#else - m_cone.render(); -#endif // ENABLE_RAYCAST_PICKING #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL @@ -343,11 +271,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) glsafe(::glPushMatrix()); glsafe(::glScaled(radius, radius, radius)); #endif // ENABLE_LEGACY_OPENGL_REMOVAL -#if ENABLE_RAYCAST_PICKING m_sphere.model.render(); -#else - m_sphere.render(); -#endif // ENABLE_RAYCAST_PICKING #if !ENABLE_LEGACY_OPENGL_REMOVAL glsafe(::glPopMatrix()); #endif // !ENABLE_LEGACY_OPENGL_REMOVAL @@ -424,10 +348,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous m_editing_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second); m_parent.set_as_dirty(); m_wait_for_up_event = true; -#if ENABLE_RAYCAST_PICKING unregister_point_raycasters_for_picking(); register_point_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING } else return false; @@ -452,12 +374,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous // Now ask the rectangle which of the points are inside. std::vector points_inside; -#if ENABLE_RAYCAST_PICKING std::vector points_idxs = m_selection_rectangle.contains(points); m_selection_rectangle.stop_dragging(); -#else - std::vector points_idxs = m_selection_rectangle.stop_dragging(m_parent, points); -#endif // ENABLE_RAYCAST_PICKING for (size_t idx : points_idxs) points_inside.push_back(points[idx].cast()); @@ -587,11 +505,8 @@ void GLGizmoSlaSupports::delete_selected_points(bool force) } } -#if ENABLE_RAYCAST_PICKING unregister_point_raycasters_for_picking(); register_point_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING - select_point(NoPoints); } @@ -1260,9 +1175,7 @@ void GLGizmoSlaSupports::switch_to_editing_mode() for (const sla::SupportPoint& sp : m_normal_cache) m_editing_cache.emplace_back(sp); select_point(NoPoints); -#if ENABLE_RAYCAST_PICKING register_point_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING m_parent.set_as_dirty(); } @@ -1273,9 +1186,7 @@ void GLGizmoSlaSupports::disable_editing_mode() m_editing_mode = false; wxGetApp().plater()->leave_gizmos_stack(); m_parent.set_as_dirty(); -#if ENABLE_RAYCAST_PICKING unregister_point_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING } wxGetApp().plater()->get_notification_manager()->close_notification_of_type(NotificationType::QuitSLAManualMode); } @@ -1294,7 +1205,6 @@ bool GLGizmoSlaSupports::unsaved_changes() const return false; } -#if ENABLE_RAYCAST_PICKING void GLGizmoSlaSupports::register_point_raycasters_for_picking() { assert(m_point_raycasters.empty()); @@ -1345,7 +1255,6 @@ void GLGizmoSlaSupports::update_point_raycasters_for_picking_transform() m_point_raycasters[i].first->set_transform(sphere_matrix); } } -#endif // ENABLE_RAYCAST_PICKING SlaGizmoHelpDialog::SlaGizmoHelpDialog() : wxDialog(nullptr, wxID_ANY, _L("SLA gizmo keyboard shortcuts"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index c10d225da0..578858b5bd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -77,24 +77,14 @@ public: private: bool on_init() override; void on_render() override; -#if ENABLE_RAYCAST_PICKING virtual void on_register_raycasters_for_picking() override; virtual void on_unregister_raycasters_for_picking() override; -#else - void on_render_for_picking() override; -#endif // ENABLE_RAYCAST_PICKING -#if ENABLE_RAYCAST_PICKING void render_points(const Selection& selection); -#else - void render_points(const Selection& selection, bool picking = false); -#endif // ENABLE_RAYCAST_PICKING bool unsaved_changes() const; -#if ENABLE_RAYCAST_PICKING void register_point_raycasters_for_picking(); void unregister_point_raycasters_for_picking(); void update_point_raycasters_for_picking_transform(); -#endif // ENABLE_RAYCAST_PICKING bool m_lock_unique_islands = false; bool m_editing_mode = false; // Is editing mode active? @@ -107,14 +97,9 @@ private: std::vector m_normal_cache; // to restore after discarding changes or undo/redo ObjectID m_old_mo_id; -#if ENABLE_RAYCAST_PICKING PickingModel m_sphere; PickingModel m_cone; std::vector, std::shared_ptr>> m_point_raycasters; -#else - GLModel m_cone; - GLModel m_sphere; -#endif // ENABLE_RAYCAST_PICKING // This map holds all translated description texts, so they can be easily referenced during layout calculations // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect. diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index d8a858bacd..818dae7676 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -249,8 +249,6 @@ void InstancesHider::render_cut() const } - - void Raycaster::on_update() { wxBusyCursor wait; @@ -291,11 +289,7 @@ void Raycaster::on_update() if (force_raycaster_regeneration || meshes != m_old_meshes) { m_raycasters.clear(); for (const TriangleMesh* mesh : meshes) -#if ENABLE_RAYCAST_PICKING m_raycasters.emplace_back(new MeshRaycaster(std::make_shared(*mesh))); -#else - m_raycasters.emplace_back(new MeshRaycaster(*mesh)); -#endif // ENABLE_RAYCAST_PICKING m_old_meshes = meshes; } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp index aa9493d9d3..2ae30a71bc 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp @@ -29,6 +29,7 @@ enum class SLAGizmoEventType : unsigned char { ShiftDown, ShiftUp, AltUp, + Escape, ApplyChanges, DiscardChanges, AutomaticGeneration, @@ -136,7 +137,6 @@ protected: virtual void on_update() = 0; CommonGizmosDataPool* get_pool() const { return m_common; } - private: bool m_is_valid = false; CommonGizmosDataPool* m_common = nullptr; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index ad0e268f6f..2e53f7f97c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -339,17 +339,6 @@ void GLGizmosManager::render_painter_gizmo() gizmo->render_painter_gizmo(); } -#if !ENABLE_RAYCAST_PICKING -void GLGizmosManager::render_current_gizmo_for_picking_pass() const -{ - if (! m_enabled || m_current == Undefined) - - return; - - m_gizmos[m_current]->render_for_picking(); -} -#endif // !ENABLE_RAYCAST_PICKING - void GLGizmosManager::render_overlay() { if (!m_enabled) @@ -526,7 +515,10 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt) case WXK_ESCAPE: { if (m_current != Undefined) { - if ((m_current != SlaSupports) || !gizmo_event(SLAGizmoEventType::DiscardChanges)) + if (m_current == Measure && gizmo_event(SLAGizmoEventType::Escape)) { + // do nothing + } + else if (m_current != SlaSupports || !gizmo_event(SLAGizmoEventType::DiscardChanges)) reset_all_states(); processed = true; @@ -554,7 +546,7 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt) case WXK_BACK: case WXK_DELETE: { - if ((m_current == SlaSupports || m_current == Hollow || m_current == Cut) && gizmo_event(SLAGizmoEventType::Delete)) + if ((m_current == SlaSupports || m_current == Hollow || m_current == Cut || m_current == Measure) && gizmo_event(SLAGizmoEventType::Delete)) processed = true; break; @@ -1129,9 +1121,7 @@ bool GLGizmosManager::activate_gizmo(EType type) if (old_gizmo.get_state() != GLGizmoBase::Off) return false; // gizmo refused to be turned off, do nothing. -#if ENABLE_RAYCAST_PICKING old_gizmo.unregister_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING if (!m_serializing && old_gizmo.wants_enter_leave_snapshots()) Plater::TakeSnapshot @@ -1162,9 +1152,7 @@ bool GLGizmosManager::activate_gizmo(EType type) return false; // gizmo refused to be turned on. } -#if ENABLE_RAYCAST_PICKING new_gizmo.register_raycasters_for_picking(); -#endif // ENABLE_RAYCAST_PICKING // sucessful activation of gizmo return true; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index 1469c2ef75..b380c55c46 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -216,9 +216,6 @@ public: bool is_hiding_instances() const; void render_current_gizmo() const; -#if !ENABLE_RAYCAST_PICKING - void render_current_gizmo_for_picking_pass() const; -#endif // !ENABLE_RAYCAST_PICKING void render_painter_gizmo(); void render_overlay(); diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 9e62283e38..7214ccdaba 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -165,8 +165,6 @@ void ArrangeJob::process(Ctl &ctl) { static const auto arrangestr = _u8L("Arranging"); - ctl.update_status(0, arrangestr); - arrangement::ArrangeParams params; Points bedpts; ctl.call_on_main_thread([this, ¶ms, &bedpts]{ @@ -175,7 +173,12 @@ void ArrangeJob::process(Ctl &ctl) bedpts = get_bed_shape(*m_plater->config()); }).wait(); - auto count = unsigned(m_selected.size() + m_unprintable.size()); + auto count = unsigned(m_selected.size() + m_unprintable.size()); + + if (count == 0) // Should be taken care of by plater, but doesn't hurt + return; + + ctl.update_status(0, arrangestr); params.stopcondition = [&ctl]() { return ctl.was_canceled(); }; diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index e33d29ba16..8ac1af7dcd 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -24,7 +24,7 @@ namespace GUI { void MeshClipper::set_behaviour(bool fill_cut, double contour_width) { - if (fill_cut != m_fill_cut || contour_width != m_contour_width) + if (fill_cut != m_fill_cut || is_approx(contour_width, m_contour_width)) m_result.reset(); m_fill_cut = fill_cut; m_contour_width = contour_width; @@ -97,7 +97,7 @@ void MeshClipper::render_cut() shader->set_uniform("view_model_matrix", camera.get_view_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); for (CutIsland& isl : m_result->cut_islands) { - isl.model.set_color(isl.disabled ? ColorRGBA(1.f, 0.f, 0.f, 1.f) : color); + isl.model.set_color(isl.disabled ? ColorRGBA(0.5f, 0.5f, 0.5f, 1.f) : color); isl.model.render(); } shader->stop_using(); @@ -132,7 +132,7 @@ void MeshClipper::render_contour() shader->set_uniform("view_model_matrix", camera.get_view_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); for (CutIsland& isl : m_result->cut_islands) { - isl.model_expanded.set_color(color); + isl.model_expanded.set_color(isl.disabled ? ColorRGBA(1.f, 0.f, 0.f, 1.f) : color); isl.model_expanded.render(); } shader->stop_using(); @@ -155,7 +155,7 @@ bool MeshClipper::is_projection_inside_cut(const Vec3d& point_in) const for (const CutIsland& isl : m_result->cut_islands) { if (isl.expoly_bb.contains(pt_2d) && isl.expoly.contains(pt_2d)) - return true; + return !isl.disabled; } return false; } @@ -370,13 +370,8 @@ Vec3f MeshRaycaster::get_triangle_normal(size_t facet_idx) const return m_normals[facet_idx]; } -#if ENABLE_RAYCAST_PICKING void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera, Vec3d& point, Vec3d& direction) -#else -void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera, - Vec3d& point, Vec3d& direction) -#endif // ENABLE_RAYCAST_PICKING { Matrix4d modelview = camera.get_view_matrix().matrix(); Matrix4d projection= camera.get_projection_matrix().matrix(); @@ -429,10 +424,10 @@ bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& // All hits are clipped. return false; } - if ((hits.size()-i) % 2 != 0) { + if (clipping_plane && (hits.size()-i) % 2 != 0) { // There is an odd number of unclipped hits - meaning the nearest must be from inside the mesh. // In that case, calculate intersection with the clipping place. - if (clipping_plane && was_clipping_plane_hit) { + if (was_clipping_plane_hit) { direction = direction + point; point = trafo * point; // transform to world coords direction = trafo * direction - point; @@ -540,7 +535,6 @@ std::vector MeshRaycaster::get_unobscured_idxs(const Geometry::Transfo return out; } -#if ENABLE_RAYCAST_PICKING bool MeshRaycaster::closest_hit(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera, Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane, size_t* facet_idx) const { @@ -573,7 +567,6 @@ bool MeshRaycaster::closest_hit(const Vec2d& mouse_pos, const Transform3d& trafo return true; } -#endif // ENABLE_RAYCAST_PICKING Vec3f MeshRaycaster::get_closest_point(const Vec3f& point, Vec3f* normal) const { diff --git a/src/slic3r/GUI/MeshUtils.hpp b/src/slic3r/GUI/MeshUtils.hpp index 1815df9cac..55e1560560 100644 --- a/src/slic3r/GUI/MeshUtils.hpp +++ b/src/slic3r/GUI/MeshUtils.hpp @@ -15,9 +15,7 @@ #include #include -#if ENABLE_RAYCAST_PICKING #include -#endif // ENABLE_RAYCAST_PICKING namespace Slic3r { @@ -61,10 +59,8 @@ public: void set_offset(double offset) { m_data[3] = offset; } double get_offset() const { return m_data[3]; } Vec3d get_normal() const { return Vec3d(m_data[0], m_data[1], m_data[2]); } -#if ENABLE_RAYCAST_PICKING void invert_normal() { m_data[0] *= -1.0; m_data[1] *= -1.0; m_data[2] *= -1.0; } ClippingPlane inverted_normal() const { return ClippingPlane(-get_normal(), get_offset()); } -#endif // ENABLE_RAYCAST_PICKING bool is_active() const { return m_data[3] != DBL_MAX; } static ClippingPlane ClipsNothing() { return ClippingPlane(Vec3d(0., 0., 1.), DBL_MAX); } const std::array& get_data() const { return m_data; } @@ -155,7 +151,6 @@ private: // whether certain points are visible or obscured by the mesh etc. class MeshRaycaster { public: -#if ENABLE_RAYCAST_PICKING explicit MeshRaycaster(std::shared_ptr mesh) : m_mesh(std::move(mesh)) , m_emesh(*m_mesh, true) // calculate epsilon for triangle-ray intersection from an average edge length @@ -170,20 +165,6 @@ public: static void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera, Vec3d& point, Vec3d& direction); -#else - // The class references extern TriangleMesh, which must stay alive - // during MeshRaycaster existence. - MeshRaycaster(const TriangleMesh& mesh) - : m_emesh(mesh, true) // calculate epsilon for triangle-ray intersection from an average edge length - , m_normals(its_face_normals(mesh.its)) - { - } - - static void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera, - Vec3d& point, Vec3d& direction); -// void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera, -// Vec3d& point, Vec3d& direction) const; -#endif // ENABLE_RAYCAST_PICKING // Given a mouse position, this returns true in case it is on the mesh. bool unproject_on_mesh( @@ -212,7 +193,6 @@ public: const ClippingPlane* clipping_plane = nullptr // clipping plane (if active) ) const; -#if ENABLE_RAYCAST_PICKING // Returns true if the ray, built from mouse position and camera direction, intersects the mesh. // In this case, position and normal contain the position and normal, in model coordinates, of the intersection closest to the camera, // depending on the position/orientation of the clipping_plane, if specified @@ -225,7 +205,6 @@ public: const ClippingPlane* clipping_plane = nullptr, // clipping plane (if active) size_t* facet_idx = nullptr // index of the facet hit ) const; -#endif // ENABLE_RAYCAST_PICKING // Given a point in world coords, the method returns closest point on the mesh. // The output is in mesh coords. @@ -238,14 +217,11 @@ public: Vec3f get_triangle_normal(size_t facet_idx) const; private: -#if ENABLE_RAYCAST_PICKING std::shared_ptr m_mesh; -#endif // ENABLE_RAYCAST_PICKING AABBMesh m_emesh; std::vector m_normals; }; -#if ENABLE_RAYCAST_PICKING struct PickingModel { GLModel model; @@ -256,7 +232,6 @@ struct PickingModel mesh_raycaster.reset(); } }; -#endif // ENABLE_RAYCAST_PICKING } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index cfc78f9f80..fe57d7d5a4 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -772,11 +772,7 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item) // get index of the last VolumeItem in CildrenList size_t vol_idx = GetItemIndexForFirstVolume(node_parent); - ObjectDataViewModelNode *last_child_node = node_parent->GetNthChild(vol_idx); - // if last volume is text then don't delete it - if (last_child_node->is_text_volume()) - return parent; // delete this last volume DeleteSettings(wxDataViewItem(last_child_node)); diff --git a/src/slic3r/GUI/OpenGLManager.cpp b/src/slic3r/GUI/OpenGLManager.cpp index 2924470e07..0366031d29 100644 --- a/src/slic3r/GUI/OpenGLManager.cpp +++ b/src/slic3r/GUI/OpenGLManager.cpp @@ -37,20 +37,20 @@ std::string gl_get_string_safe(GLenum param, const std::string& default_value) return std::string((value != nullptr) ? value : default_value); } -const std::string& OpenGLManager::GLInfo::get_version() const +const std::string& OpenGLManager::GLInfo::get_version_string() const { if (!m_detected) detect(); - return m_version; + return m_version_string; } -const std::string& OpenGLManager::GLInfo::get_glsl_version() const +const std::string& OpenGLManager::GLInfo::get_glsl_version_string() const { if (!m_detected) detect(); - return m_glsl_version; + return m_glsl_version_string; } const std::string& OpenGLManager::GLInfo::get_vendor() const @@ -71,7 +71,7 @@ const std::string& OpenGLManager::GLInfo::get_renderer() const bool OpenGLManager::GLInfo::is_mesa() const { - return boost::icontains(m_version, "mesa"); + return m_version_is_mesa; } int OpenGLManager::GLInfo::get_max_tex_size() const @@ -97,13 +97,19 @@ float OpenGLManager::GLInfo::get_max_anisotropy() const return m_max_anisotropy; } +static Semver parse_version_string(const std::string& version); + void OpenGLManager::GLInfo::detect() const { - *const_cast(&m_version) = gl_get_string_safe(GL_VERSION, "N/A"); - *const_cast(&m_glsl_version) = gl_get_string_safe(GL_SHADING_LANGUAGE_VERSION, "N/A"); + *const_cast(&m_version_string) = gl_get_string_safe(GL_VERSION, "N/A"); + *const_cast(&m_glsl_version_string) = gl_get_string_safe(GL_SHADING_LANGUAGE_VERSION, "N/A"); *const_cast(&m_vendor) = gl_get_string_safe(GL_VENDOR, "N/A"); *const_cast(&m_renderer) = gl_get_string_safe(GL_RENDERER, "N/A"); + *const_cast(&m_version) = parse_version_string(m_version_string); + *const_cast(&m_version_is_mesa) = boost::icontains(m_version_string, "mesa"); + *const_cast(&m_glsl_version) = parse_version_string(m_glsl_version_string); + int* max_tex_size = const_cast(&m_max_tex_size); glsafe(::glGetIntegerv(GL_MAX_TEXTURE_SIZE, max_tex_size)); @@ -119,16 +125,16 @@ void OpenGLManager::GLInfo::detect() const *const_cast(&m_detected) = true; } -static bool version_greater_or_equal_to(const std::string& version, unsigned int major, unsigned int minor) +static Semver parse_version_string(const std::string& version) { if (version == "N/A") - return false; + return Semver::invalid(); std::vector tokens; boost::split(tokens, version, boost::is_any_of(" "), boost::token_compress_on); if (tokens.empty()) - return false; + return Semver::invalid(); #if ENABLE_OPENGL_ES const std::string version_container = (tokens.size() > 1 && boost::istarts_with(tokens[1], "ES")) ? tokens[2] : tokens[0]; @@ -150,20 +156,15 @@ static bool version_greater_or_equal_to(const std::string& version, unsigned int if (numbers.size() > 1) gl_minor = ::atoi(numbers[1].c_str()); - if (gl_major < major) - return false; - else if (gl_major > major) - return true; - else - return gl_minor >= minor; + return Semver(gl_major, gl_minor, 0); } bool OpenGLManager::GLInfo::is_version_greater_or_equal_to(unsigned int major, unsigned int minor) const { if (!m_detected) detect(); - - return version_greater_or_equal_to(m_version, major, minor); + + return m_version >= Semver(major, minor, 0); } bool OpenGLManager::GLInfo::is_glsl_version_greater_or_equal_to(unsigned int major, unsigned int minor) const @@ -171,7 +172,7 @@ bool OpenGLManager::GLInfo::is_glsl_version_greater_or_equal_to(unsigned int maj if (!m_detected) detect(); - return version_greater_or_equal_to(m_glsl_version, major, minor); + return m_glsl_version >= Semver(major, minor, 0); } // If formatted for github, plaintext with OpenGL extensions enclosed into
. @@ -378,13 +379,13 @@ bool OpenGLManager::init_gl() wxString message = from_u8((boost::format( #if ENABLE_OPENGL_ES _utf8(L("PrusaSlicer requires OpenGL ES 2.0 capable graphics driver to run correctly, \n" - "while OpenGL version %s, render %s, vendor %s was detected."))) % s_gl_info.get_version() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); + "while OpenGL version %s, render %s, vendor %s was detected."))) % s_gl_info.get_version_string() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); #elif ENABLE_GL_CORE_PROFILE _utf8(L("PrusaSlicer requires OpenGL %s capable graphics driver to run correctly, \n" - "while OpenGL version %s, render %s, vendor %s was detected."))) % (s_gl_info.is_core_profile() ? "3.3" : "2.0") % s_gl_info.get_version() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); + "while OpenGL version %s, render %s, vendor %s was detected."))) % (s_gl_info.is_core_profile() ? "3.3" : "2.0") % s_gl_info.get_version_string() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); #else _utf8(L("PrusaSlicer requires OpenGL 2.0 capable graphics driver to run correctly, \n" - "while OpenGL version %s, render %s, vendor %s was detected."))) % s_gl_info.get_version() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); + "while OpenGL version %s, render %s, vendor %s was detected."))) % s_gl_info.get_version_string() % s_gl_info.get_renderer() % s_gl_info.get_vendor()).str()); #endif // ENABLE_OPENGL_ES message += "\n"; message += _L("You may need to update your graphics card driver."); @@ -423,7 +424,7 @@ bool OpenGLManager::init_gl() // WHQL: 4.6.14800 Compatibility Profile Context 22.6.1 30.0.21023.1015 // Non-WHQL: 4.6.0 Compatibility Profile Context 22.8.1.220810 std::regex version_rgx(R"(Compatibility\sProfile\sContext\s(\d+)\.(\d+)\.(\d+))"); - if (std::smatch matches; std::regex_search(gl_info.get_version(), matches, version_rgx) && matches.size() == 4) { + if (std::smatch matches; std::regex_search(gl_info.get_version_string(), matches, version_rgx) && matches.size() == 4) { int version_major = std::stoi(matches[1].str()); int version_minor = std::stoi(matches[2].str()); int version_patch = std::stoi(matches[3].str()); diff --git a/src/slic3r/GUI/OpenGLManager.hpp b/src/slic3r/GUI/OpenGLManager.hpp index 5c810d83ef..ece9009622 100644 --- a/src/slic3r/GUI/OpenGLManager.hpp +++ b/src/slic3r/GUI/OpenGLManager.hpp @@ -31,16 +31,21 @@ public: int m_max_tex_size{ 0 }; float m_max_anisotropy{ 0.0f }; - std::string m_version; - std::string m_glsl_version; + std::string m_version_string; + Semver m_version = Semver::invalid(); + bool m_version_is_mesa = false; + + std::string m_glsl_version_string; + Semver m_glsl_version = Semver::invalid(); + std::string m_vendor; std::string m_renderer; public: GLInfo() = default; - const std::string& get_version() const; - const std::string& get_glsl_version() const; + const std::string& get_version_string() const; + const std::string& get_glsl_version_string() const; const std::string& get_vendor() const; const std::string& get_renderer() const; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 9db47ffb04..871ed5e4f5 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2990,7 +2990,7 @@ bool Plater::priv::delete_object_from_model(size_t obj_idx) InfoDialog dialog(q, _L("Delete object which is a part of cut object"), _L("You try to delete an object which is a part of a cut object.\n" "This action will break a cut correspondence.\n" - "After that PrusaSlicer can't garantie model consistency"), + "After that PrusaSlicer can't guarantee model consistency"), false, wxYES | wxCANCEL | wxCANCEL_DEFAULT | wxICON_WARNING); dialog.SetButtonLabel(wxID_YES, _L("Delete object")); if (dialog.ShowModal() == wxID_CANCEL) @@ -4966,7 +4966,7 @@ bool Plater::priv::can_split_to_volumes() const bool Plater::priv::can_arrange() const { - if (model.objects.empty() && m_worker.is_idle()) return false; + if (model.objects.empty() || !m_worker.is_idle()) return false; if (q->canvas3D()->get_gizmos_manager().get_current_type() == GLGizmosManager::Emboss) return false; return true; } @@ -6794,8 +6794,8 @@ GLCanvas3D* Plater::get_current_canvas3D() void Plater::arrange() { - auto &w = get_ui_job_worker(); - if (w.is_idle()) { + if (p->can_arrange()) { + auto &w = get_ui_job_worker(); p->take_snapshot(_L("Arrange")); replace_job(w, std::make_unique()); } diff --git a/src/slic3r/GUI/SceneRaycaster.cpp b/src/slic3r/GUI/SceneRaycaster.cpp index 9e726b7f4b..1e8bb0c82b 100644 --- a/src/slic3r/GUI/SceneRaycaster.cpp +++ b/src/slic3r/GUI/SceneRaycaster.cpp @@ -4,8 +4,6 @@ #include "Camera.hpp" #include "GUI_App.hpp" -#if ENABLE_RAYCAST_PICKING - namespace Slic3r { namespace GUI { @@ -247,5 +245,3 @@ int SceneRaycaster::decode_id(EType type, int id) { return id - base_id(type); } } // namespace GUI } // namespace Slic3r - -#endif // ENABLE_RAYCAST_PICKING diff --git a/src/slic3r/GUI/SceneRaycaster.hpp b/src/slic3r/GUI/SceneRaycaster.hpp index bf8ab2b1bf..df44b1701c 100644 --- a/src/slic3r/GUI/SceneRaycaster.hpp +++ b/src/slic3r/GUI/SceneRaycaster.hpp @@ -1,8 +1,6 @@ #ifndef slic3r_SceneRaycaster_hpp_ #define slic3r_SceneRaycaster_hpp_ -#if ENABLE_RAYCAST_PICKING - #include "MeshUtils.hpp" #include "GLModel.hpp" #include @@ -116,6 +114,4 @@ private: } // namespace GUI } // namespace Slic3r -#endif // ENABLE_RAYCAST_PICKING - #endif // slic3r_SceneRaycaster_hpp_ diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 7caf2d9ea7..500ad814ef 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -613,6 +613,17 @@ bool Selection::contains_any_volume(const std::vector& volume_idxs return false; } +bool Selection::contains_sinking_volumes(bool ignore_modifiers) const +{ + for (const GLVolume* v : *m_volumes) { + if (!ignore_modifiers || !v->is_modifier) { + if (v->is_sinking()) + return true; + } + } + return false; +} + bool Selection::matches(const std::vector& volume_idxs) const { unsigned int count = 0; diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 34b88f1606..6468f6a87d 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -338,6 +338,8 @@ public: bool contains_all_volumes(const std::vector& volume_idxs) const; // returns true if the selection contains at least one of the given indices bool contains_any_volume(const std::vector& volume_idxs) const; + // returns true if the selection contains any sinking volume + bool contains_sinking_volumes(bool ignore_modifiers = true) const; // returns true if the selection contains all and only the given indices bool matches(const std::vector& volume_idxs) const; diff --git a/src/slic3r/GUI/SendSystemInfoDialog.cpp b/src/slic3r/GUI/SendSystemInfoDialog.cpp index 298b3242d5..dfb442d18c 100644 --- a/src/slic3r/GUI/SendSystemInfoDialog.cpp +++ b/src/slic3r/GUI/SendSystemInfoDialog.cpp @@ -504,8 +504,8 @@ static std::string generate_system_info_json() #endif // _WIN32 pt::ptree opengl_node; - opengl_node.put("Version", OpenGLManager::get_gl_info().get_version()); - opengl_node.put("GLSLVersion", OpenGLManager::get_gl_info().get_glsl_version()); + opengl_node.put("Version", OpenGLManager::get_gl_info().get_version_string()); + opengl_node.put("GLSLVersion", OpenGLManager::get_gl_info().get_glsl_version_string()); opengl_node.put("Vendor", OpenGLManager::get_gl_info().get_vendor()); opengl_node.put("Renderer", OpenGLManager::get_gl_info().get_renderer()); // Generate list of OpenGL extensions: diff --git a/src/slic3r/Utils/RaycastManager.cpp b/src/slic3r/Utils/RaycastManager.cpp index 14c76722d9..084cf83a63 100644 --- a/src/slic3r/Utils/RaycastManager.cpp +++ b/src/slic3r/Utils/RaycastManager.cpp @@ -26,11 +26,7 @@ void RaycastManager::actualize(const ModelObject *object, const ISkip *skip) }); if (item == m_raycasters.end()) { // add new raycaster -#if ENABLE_RAYCAST_PICKING auto raycaster = std::make_unique(volume->get_mesh_shared_ptr()); -#else // !ENABLE_RAYCAST_PICKING - auto raycaster = std::make_unique(volume->mesh()); -#endif // ENABLE_RAYCAST_PICKING m_raycasters.emplace_back(std::make_pair(oid, std::move(raycaster))); } else { size_t index = item - m_raycasters.begin(); diff --git a/tests/libslic3r/test_color.cpp b/tests/libslic3r/test_color.cpp index 632691669e..bb35f5e38e 100644 --- a/tests/libslic3r/test_color.cpp +++ b/tests/libslic3r/test_color.cpp @@ -20,20 +20,4 @@ SCENARIO("Color encoding/decoding cycle", "[Color]") { } } -#if !ENABLE_RAYCAST_PICKING -SCENARIO("Color picking encoding/decoding cycle", "[Color]") { - GIVEN("Picking color") { - const ColorRGB src_rgb(static_cast(255), static_cast(127), static_cast(63)); - WHEN("apply encode/decode cycle") { - const unsigned int encoded = picking_encode(src_rgb.r_uchar(), src_rgb.g_uchar(), src_rgb.b_uchar()); - const ColorRGBA res_rgba = picking_decode(encoded); - const bool ret = res_rgba.r_uchar() == src_rgb.r_uchar() && res_rgba.g_uchar() == src_rgb.g_uchar() && res_rgba.b_uchar() == src_rgb.b_uchar(); - THEN("result matches source") { - REQUIRE(ret); - } - } - } -} -#endif // !ENABLE_RAYCAST_PICKING -