Merge remote-tracking branch 'PRIVATE/master' into ys_cut
@ -46,7 +46,7 @@ BreakConstructorInitializersBeforeComma: false
|
|||||||
BreakConstructorInitializers: BeforeComma
|
BreakConstructorInitializers: BeforeComma
|
||||||
BreakAfterJavaFieldAnnotations: false
|
BreakAfterJavaFieldAnnotations: false
|
||||||
BreakStringLiterals: true
|
BreakStringLiterals: true
|
||||||
ColumnLimit: 78
|
ColumnLimit: 140
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
CompactNamespaces: true
|
CompactNamespaces: true
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
BIN
resources/profiles/Creality/ENDER5PRO_thumbnail.png
Normal file
After Width: | Height: | Size: 28 KiB |
3
resources/profiles/Rigid3D.idx
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
min_slic3r_version = 2.6.0-alpha0
|
||||||
|
1.0.0 Initial Rigid3D bundle
|
||||||
|
|
469
resources/profiles/Rigid3D.ini
Normal file
@ -0,0 +1,469 @@
|
|||||||
|
# Print profiles for the Rigid3D printers.
|
||||||
|
|
||||||
|
[vendor]
|
||||||
|
# Vendor name will be shown by the Config Wizard.
|
||||||
|
name = Rigid3D
|
||||||
|
# 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
|
||||||
|
# Where to get the updates from?
|
||||||
|
config_update_url = https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Rigid3D/
|
||||||
|
# changelog_url = https://files.prusa3d.com/?latest=slicer-profiles&lng=%1%
|
||||||
|
|
||||||
|
# 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:Zero2]
|
||||||
|
name = Rigid3D Zero2
|
||||||
|
variants = 0.4
|
||||||
|
technology = FFF
|
||||||
|
family = Zero
|
||||||
|
bed_model = zero_bed.stl
|
||||||
|
bed_texture = zero2_bed.png
|
||||||
|
default_materials = Generic PLA @Rigid3D; Generic PETG @Rigid3D; Generic ABS @Rigid3D; Rigid3D PLA @Rigid3D; Generic Nylon @Rigid3D; Generic FLEX @Rigid3D
|
||||||
|
|
||||||
|
[printer_model:Zero3]
|
||||||
|
name = Rigid3D Zero3
|
||||||
|
variants = 0.4
|
||||||
|
technology = FFF
|
||||||
|
family = Zero
|
||||||
|
bed_model = zero_bed.stl
|
||||||
|
bed_texture = zero3_bed.png
|
||||||
|
default_materials =Generic PLA @Rigid3D; Generic PETG @Rigid3D; Generic ABS @Rigid3D; Rigid3D PLA @Rigid3D; Generic Nylon @Rigid3D; Generic FLEX @Rigid3D
|
||||||
|
|
||||||
|
[printer_model:Mucit]
|
||||||
|
name = Rigid3D Mucit
|
||||||
|
variants = 0.4
|
||||||
|
technology = FFF
|
||||||
|
family = Mucit
|
||||||
|
bed_model = mucit_bed.stl
|
||||||
|
bed_texture = mucit_bed.png
|
||||||
|
default_materials = Generic PLA @Rigid3D; Rigid3D PLA @Rigid3D
|
||||||
|
|
||||||
|
[printer_model:Mucit2]
|
||||||
|
name = Rigid3D Mucit2
|
||||||
|
variants = 0.4
|
||||||
|
technology = FFF
|
||||||
|
family = Mucit
|
||||||
|
bed_model = mucit2_bed.stl
|
||||||
|
bed_texture = mucit2_bed.png
|
||||||
|
default_materials = Generic PLA @Rigid3D; Generic PETG @Rigid3D; Generic ABS @Rigid3D; Rigid3D PLA @Rigid3D; Generic Nylon @Rigid3D; Generic FLEX @Rigid3D
|
||||||
|
|
||||||
|
# All presets starting with asterisk, for example *common*, are intermediate and they will
|
||||||
|
# not make it into the user interface.
|
||||||
|
|
||||||
|
# Common print preset
|
||||||
|
[print:*common*]
|
||||||
|
avoid_crossing_perimeters = 0
|
||||||
|
avoid_crossing_perimeters_max_detour = 0
|
||||||
|
bottom_fill_pattern = monotonic
|
||||||
|
bottom_solid_min_thickness = 0.8
|
||||||
|
bridge_acceleration = 0
|
||||||
|
bridge_angle = 0
|
||||||
|
bridge_flow_ratio = 1
|
||||||
|
bridge_speed = 60
|
||||||
|
brim_separation = 0
|
||||||
|
brim_type = no_brim
|
||||||
|
brim_width = 0
|
||||||
|
clip_multipart_objects = 1
|
||||||
|
compatible_printers =
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/
|
||||||
|
complete_objects = 0
|
||||||
|
default_acceleration = 0
|
||||||
|
dont_support_bridges = 1
|
||||||
|
draft_shield = disabled
|
||||||
|
elefant_foot_compensation = 0
|
||||||
|
ensure_vertical_shell_thickness = 0
|
||||||
|
external_perimeter_extrusion_width = 0.45
|
||||||
|
external_perimeter_speed = 50%
|
||||||
|
external_perimeters_first = 1
|
||||||
|
extra_perimeters = 1
|
||||||
|
extruder_clearance_height = 20
|
||||||
|
extruder_clearance_radius = 20
|
||||||
|
extrusion_width = 0.45
|
||||||
|
fill_angle = 45
|
||||||
|
fill_density = 10%
|
||||||
|
fill_pattern = line
|
||||||
|
first_layer_acceleration = 0
|
||||||
|
first_layer_acceleration_over_raft = 0
|
||||||
|
first_layer_extrusion_width = 0.42
|
||||||
|
first_layer_height = 0.2
|
||||||
|
first_layer_speed = 50%
|
||||||
|
first_layer_speed_over_raft = 30
|
||||||
|
fuzzy_skin = none
|
||||||
|
fuzzy_skin_point_dist = 0.8
|
||||||
|
fuzzy_skin_thickness = 0.3
|
||||||
|
gap_fill_enabled = 1
|
||||||
|
gap_fill_speed = 20
|
||||||
|
gcode_comments = 0
|
||||||
|
gcode_label_objects = 0
|
||||||
|
gcode_resolution = 0.0125
|
||||||
|
gcode_substitutions =
|
||||||
|
infill_acceleration = 0
|
||||||
|
infill_anchor = 2.5
|
||||||
|
infill_anchor_max = 12
|
||||||
|
infill_every_layers = 1
|
||||||
|
infill_extruder = 1
|
||||||
|
infill_extrusion_width = 0.45
|
||||||
|
infill_first = 1
|
||||||
|
infill_only_where_needed = 0
|
||||||
|
infill_overlap = 25%
|
||||||
|
infill_speed = 60
|
||||||
|
inherits =
|
||||||
|
interface_shells = 0
|
||||||
|
ironing = 0
|
||||||
|
ironing_flowrate = 15%
|
||||||
|
ironing_spacing = 0.1
|
||||||
|
ironing_speed = 15
|
||||||
|
ironing_type = top
|
||||||
|
max_print_speed = 80
|
||||||
|
max_volumetric_speed = 0
|
||||||
|
min_skirt_length = 0
|
||||||
|
mmu_segmented_region_max_width = 0
|
||||||
|
notes =
|
||||||
|
only_retract_when_crossing_perimeters = 0
|
||||||
|
ooze_prevention = 0
|
||||||
|
output_filename_format = {input_filename_base}_{layer_height}mm_{initial_filament_type}_{printer_model}_{print_time}.gcode
|
||||||
|
overhangs = 1
|
||||||
|
perimeter_acceleration = 0
|
||||||
|
perimeter_extruder = 1
|
||||||
|
perimeter_extrusion_width = 0.45
|
||||||
|
perimeter_speed = 60
|
||||||
|
perimeters = 2
|
||||||
|
post_process =
|
||||||
|
print_settings_id =
|
||||||
|
raft_contact_distance = 0.1
|
||||||
|
raft_expansion = 1.5
|
||||||
|
raft_first_layer_density = 90%
|
||||||
|
raft_first_layer_expansion = 3
|
||||||
|
raft_layers = 0
|
||||||
|
resolution = 0
|
||||||
|
seam_position = rear
|
||||||
|
single_extruder_multi_material_priming = 1
|
||||||
|
skirt_distance = 6
|
||||||
|
skirt_height = 1
|
||||||
|
skirts = 0
|
||||||
|
slice_closing_radius = 0.049
|
||||||
|
slicing_mode = regular
|
||||||
|
small_perimeter_speed = 15
|
||||||
|
solid_infill_below_area = 70
|
||||||
|
solid_infill_every_layers = 0
|
||||||
|
solid_infill_extruder = 1
|
||||||
|
solid_infill_extrusion_width = 0.45
|
||||||
|
solid_infill_speed = 100%
|
||||||
|
spiral_vase = 0
|
||||||
|
standby_temperature_delta = -5
|
||||||
|
support_material = 0
|
||||||
|
support_material_angle = 0
|
||||||
|
support_material_auto = 1
|
||||||
|
support_material_bottom_contact_distance = 0
|
||||||
|
support_material_bottom_interface_layers = -1
|
||||||
|
support_material_buildplate_only = 0
|
||||||
|
support_material_closing_radius = 2
|
||||||
|
support_material_contact_distance = 0.2
|
||||||
|
support_material_enforce_layers = 0
|
||||||
|
support_material_extruder = 1
|
||||||
|
support_material_extrusion_width = 0.35
|
||||||
|
support_material_interface_contact_loops = 0
|
||||||
|
support_material_interface_extruder = 1
|
||||||
|
support_material_interface_layers = 3
|
||||||
|
support_material_interface_pattern = rectilinear
|
||||||
|
support_material_interface_spacing = 0
|
||||||
|
support_material_interface_speed = 100%
|
||||||
|
support_material_pattern = rectilinear
|
||||||
|
support_material_spacing = 2.5
|
||||||
|
support_material_speed = 60
|
||||||
|
support_material_style = grid
|
||||||
|
support_material_synchronize_layers = 0
|
||||||
|
support_material_threshold = 0
|
||||||
|
support_material_with_sheath = 1
|
||||||
|
support_material_xy_spacing = 50%
|
||||||
|
thick_bridges = 0
|
||||||
|
thin_walls = 1
|
||||||
|
top_fill_pattern = monotonic
|
||||||
|
top_infill_extrusion_width = 0.4
|
||||||
|
top_solid_infill_speed = 100%
|
||||||
|
top_solid_min_thickness = 0.8
|
||||||
|
travel_speed = 80
|
||||||
|
travel_speed_z = 0
|
||||||
|
wipe_tower = 0
|
||||||
|
wipe_tower_bridging = 10
|
||||||
|
wipe_tower_brim_width = 2
|
||||||
|
wipe_tower_no_sparse_layers = 0
|
||||||
|
wipe_tower_rotation_angle = 0
|
||||||
|
wipe_tower_width = 60
|
||||||
|
wipe_tower_x = 180
|
||||||
|
wipe_tower_y = 140
|
||||||
|
xy_size_compensation = 0
|
||||||
|
|
||||||
|
[print:0.06mm - Ultra @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.06
|
||||||
|
bottom_solid_layers = 10
|
||||||
|
top_solid_layers = 14
|
||||||
|
|
||||||
|
[print:0.12mm - Super @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.12
|
||||||
|
bottom_solid_layers = 7
|
||||||
|
top_solid_layers = 7
|
||||||
|
|
||||||
|
[print:0.16mm - Good @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.16
|
||||||
|
bottom_solid_layers = 5
|
||||||
|
top_solid_layers = 5
|
||||||
|
|
||||||
|
[print:0.20mm - Standard @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.20
|
||||||
|
bottom_solid_layers = 4
|
||||||
|
top_solid_layers = 4
|
||||||
|
|
||||||
|
[print:0.24mm - Draft @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.24
|
||||||
|
bottom_solid_layers = 3
|
||||||
|
top_solid_layers = 4
|
||||||
|
|
||||||
|
[print:0.28mm - Low @Rigid3D]
|
||||||
|
inherits = *common*
|
||||||
|
layer_height = 0.28
|
||||||
|
bottom_solid_layers = 3
|
||||||
|
top_solid_layers = 4
|
||||||
|
|
||||||
|
[filament:*common*]
|
||||||
|
disable_fan_first_layers = 3
|
||||||
|
end_filament_gcode = "; Filament-specific end gcode \n;END gcode for filament\n"
|
||||||
|
extrusion_multiplier = 1
|
||||||
|
fan_below_layer_time = 60
|
||||||
|
filament_cooling_final_speed = 3.4
|
||||||
|
filament_cooling_initial_speed = 2.2
|
||||||
|
filament_cooling_moves = 4
|
||||||
|
filament_cost = 0
|
||||||
|
filament_deretract_speed = nil
|
||||||
|
filament_diameter = 1.75
|
||||||
|
filament_minimal_purge_on_wipe_tower = 15
|
||||||
|
filament_notes = ""
|
||||||
|
filament_retract_before_travel = nil
|
||||||
|
filament_retract_before_wipe = nil
|
||||||
|
filament_retract_layer_change = nil
|
||||||
|
filament_retract_length = nil
|
||||||
|
filament_retract_lift = nil
|
||||||
|
filament_retract_lift_above = nil
|
||||||
|
filament_retract_lift_below = nil
|
||||||
|
filament_retract_restart_extra = nil
|
||||||
|
filament_retract_speed = nil
|
||||||
|
filament_settings_id = ""
|
||||||
|
filament_soluble = 0
|
||||||
|
filament_spool_weight = 0
|
||||||
|
filament_wipe = nil
|
||||||
|
min_print_speed = 10
|
||||||
|
slowdown_below_layer_time = 10
|
||||||
|
start_filament_gcode = "; Filament gcode\n"
|
||||||
|
|
||||||
|
[filament:*PLA*]
|
||||||
|
inherits = *common*
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/
|
||||||
|
bridge_fan_speed = 100
|
||||||
|
cooling = 1
|
||||||
|
fan_always_on = 1
|
||||||
|
filament_type = PLA
|
||||||
|
full_fan_speed_layer = 4
|
||||||
|
max_fan_speed = 100
|
||||||
|
min_fan_speed = 100
|
||||||
|
|
||||||
|
[filament:*ABS*]
|
||||||
|
inherits = *common*
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
|
||||||
|
cooling = 1
|
||||||
|
fan_always_on = 0
|
||||||
|
filament_type = ABS
|
||||||
|
max_fan_speed = 0
|
||||||
|
min_fan_speed = 0
|
||||||
|
|
||||||
|
[filament:*PETG*]
|
||||||
|
inherits = *common*
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
|
||||||
|
cooling = 1
|
||||||
|
fan_always_on = 0
|
||||||
|
filament_type = PETG
|
||||||
|
max_fan_speed = 50
|
||||||
|
min_fan_speed = 30
|
||||||
|
|
||||||
|
[filament:*FLEX*]
|
||||||
|
inherits = *common*
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
|
||||||
|
bridge_fan_speed = 100
|
||||||
|
cooling = 1
|
||||||
|
fan_always_on = 1
|
||||||
|
filament_type = FLEX
|
||||||
|
full_fan_speed_layer = 4
|
||||||
|
max_fan_speed = 100
|
||||||
|
min_fan_speed = 100
|
||||||
|
|
||||||
|
[filament:*NYLON*]
|
||||||
|
inherits = *common*
|
||||||
|
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_RIGID3D.*/ and printer_notes=~/.*PRINTER_HAS_HEATEDBED.*/
|
||||||
|
cooling = 1
|
||||||
|
fan_always_on = 0
|
||||||
|
filament_type = NYLON
|
||||||
|
max_fan_speed = 0
|
||||||
|
min_fan_speed = 0
|
||||||
|
|
||||||
|
[filament:Generic PLA @Rigid3D]
|
||||||
|
inherits = *PLA*
|
||||||
|
bed_temperature = 55
|
||||||
|
filament_colour = #FFFF00
|
||||||
|
filament_density = 1.24
|
||||||
|
filament_max_volumetric_speed = 12
|
||||||
|
first_layer_temperature = 215
|
||||||
|
temperature = 215
|
||||||
|
first_layer_bed_temperature = 60
|
||||||
|
|
||||||
|
[filament:Rigid3D PLA @Rigid3D]
|
||||||
|
inherits = *PLA*
|
||||||
|
filament_colour = #FFFF00
|
||||||
|
filament_density = 1.24
|
||||||
|
first_layer_temperature = 210
|
||||||
|
temperature = 205
|
||||||
|
first_layer_bed_temperature = 60
|
||||||
|
bed_temperature = 55
|
||||||
|
filament_max_volumetric_speed = 12
|
||||||
|
|
||||||
|
[filament:Generic ABS @Rigid3D]
|
||||||
|
inherits = *ABS*
|
||||||
|
filament_colour = #49B928
|
||||||
|
filament_density = 1.04
|
||||||
|
first_layer_temperature = 235
|
||||||
|
temperature = 235
|
||||||
|
first_layer_bed_temperature = 100
|
||||||
|
bed_temperature = 100
|
||||||
|
filament_max_volumetric_speed = 8
|
||||||
|
|
||||||
|
[filament:Generic PETG @Rigid3D]
|
||||||
|
inherits = *PETG*
|
||||||
|
filament_colour = #FF8000
|
||||||
|
filament_density = 1.27
|
||||||
|
first_layer_temperature = 240
|
||||||
|
temperature = 240
|
||||||
|
first_layer_bed_temperature = 70
|
||||||
|
bed_temperature = 70
|
||||||
|
filament_max_volumetric_speed = 8
|
||||||
|
|
||||||
|
[filament:Generic FLEX @Rigid3D]
|
||||||
|
inherits = *FLEX*
|
||||||
|
filament_colour = #C80000
|
||||||
|
filament_density = 1.21
|
||||||
|
first_layer_temperature = 225
|
||||||
|
temperature = 225
|
||||||
|
first_layer_bed_temperature = 70
|
||||||
|
bed_temperature = 70
|
||||||
|
filament_max_volumetric_speed = 2.5
|
||||||
|
|
||||||
|
[filament:Generic Nylon @Rigid3D]
|
||||||
|
inherits = *NYLON*
|
||||||
|
filament_colour = #0AF1CE
|
||||||
|
filament_density = 1.12
|
||||||
|
first_layer_temperature = 250
|
||||||
|
temperature = 250
|
||||||
|
first_layer_bed_temperature = 100
|
||||||
|
bed_temperature = 100
|
||||||
|
filament_max_volumetric_speed = 8
|
||||||
|
|
||||||
|
# Common printer preset
|
||||||
|
[printer:*common*]
|
||||||
|
before_layer_gcode = ;BEFORE_LAYER_CHANGE\n;[layer_z]\n\n
|
||||||
|
between_objects_gcode =
|
||||||
|
color_change_gcode = M600
|
||||||
|
default_filament_profile = "Rigid3D PLA @Rigid3D"
|
||||||
|
default_print_profile = "0.20mm - Standard @Rigid3D"
|
||||||
|
deretract_speed = 0
|
||||||
|
extruder_offset = 0x0
|
||||||
|
gcode_flavor = marlin2
|
||||||
|
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]\n\n
|
||||||
|
machine_limits_usage = time_estimate_only
|
||||||
|
machine_max_acceleration_e = 1000
|
||||||
|
machine_max_acceleration_extruding = 500
|
||||||
|
machine_max_acceleration_retracting = 1000
|
||||||
|
machine_max_acceleration_travel = 1000
|
||||||
|
machine_max_acceleration_x = 500
|
||||||
|
machine_max_acceleration_y = 500
|
||||||
|
machine_max_acceleration_z = 100
|
||||||
|
machine_max_feedrate_e = 25
|
||||||
|
machine_max_feedrate_x = 120
|
||||||
|
machine_max_feedrate_y = 120
|
||||||
|
machine_max_feedrate_z = 20
|
||||||
|
machine_max_jerk_e = 5
|
||||||
|
machine_max_jerk_x = 10
|
||||||
|
machine_max_jerk_y = 10
|
||||||
|
machine_max_jerk_z = 0.3
|
||||||
|
machine_min_extruding_rate = 0
|
||||||
|
machine_min_travel_rate = 0
|
||||||
|
max_layer_height = 0.32
|
||||||
|
min_layer_height = 0.05
|
||||||
|
nozzle_diameter = 0.4
|
||||||
|
pause_print_gcode = M0
|
||||||
|
printer_settings_id =
|
||||||
|
printer_technology = FFF
|
||||||
|
printer_variant = 0.4
|
||||||
|
remaining_times = 1
|
||||||
|
retract_before_travel = 2
|
||||||
|
retract_before_wipe = 0%
|
||||||
|
retract_layer_change = 0
|
||||||
|
retract_length = 1
|
||||||
|
retract_length_toolchange = 10
|
||||||
|
retract_lift = 0
|
||||||
|
retract_lift_above = 0
|
||||||
|
retract_lift_below = 0
|
||||||
|
retract_restart_extra = 0
|
||||||
|
retract_restart_extra_toolchange = 0
|
||||||
|
retract_speed = 25
|
||||||
|
silent_mode = 0
|
||||||
|
single_extruder_multi_material = 0
|
||||||
|
template_custom_gcode =
|
||||||
|
thumbnails =
|
||||||
|
toolchange_gcode =
|
||||||
|
use_firmware_retraction = 0
|
||||||
|
use_relative_e_distances = 0
|
||||||
|
use_volumetric_e = 0
|
||||||
|
variable_layer_height = 1
|
||||||
|
wipe = 0
|
||||||
|
z_offset = 0
|
||||||
|
|
||||||
|
[printer:Rigid3D Zero2]
|
||||||
|
inherits = *common*
|
||||||
|
bed_shape = 0x0,200x0,200x200,0x200
|
||||||
|
max_print_height = 190
|
||||||
|
printer_model = Zero2
|
||||||
|
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_RIGID3D\nPRINTER_MODEL_ZERO2\nPRINTER_HAS_HEATEDBED\n
|
||||||
|
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X190.0 Y0.1 Z0.3 F1500.0 E15\nG1 X190 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E30\nG1 Z2.0 F1500.0\nG92 E0\n
|
||||||
|
end_gcode = G1 X0 Y180\nM107\nG91\nG0 Z20\nT0\nG1 E-1\nM104 T0 S0\nG90\nG92 E0\nM140 S0\nM84\nM300 S2093 P150\nM300 S2637 P150\nM300 S3135 P150\nM300 S4186 P150\nM300 S3135 P150\nM300 S2637 P150\nM300 S2793 P150\nM300 S2349 P150\nM300 S1975 P150\nM300 S2093 P450\n
|
||||||
|
|
||||||
|
[printer:Rigid3D Zero3]
|
||||||
|
inherits = *common*
|
||||||
|
bed_shape = 0x0,200x0,200x200,0x200
|
||||||
|
max_print_height = 200
|
||||||
|
printer_model = Zero3
|
||||||
|
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_RIGID3D\nPRINTER_MODEL_ZERO3\nPRINTER_HAS_HEATEDBED\n
|
||||||
|
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X190.0 Y0.1 Z0.3 F1500.0 E15\nG1 X190 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E30\nG1 Z2.0 F1500.0\nG92 E0\n
|
||||||
|
end_gcode = G92 E0\nT0\nG1 F1800 E-2\nG27 P2\nM107\nM104 T0 S0\nM140 S0\nG90\nG92 E0\nM18\n
|
||||||
|
|
||||||
|
[printer:Rigid3D Mucit]
|
||||||
|
inherits = *common*
|
||||||
|
bed_shape = 0x0,150x0,150x150,0x150
|
||||||
|
max_print_height = 150
|
||||||
|
printer_model = Mucit
|
||||||
|
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_RIGID3D\nPRINTER_MODEL_MUCIT\n
|
||||||
|
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X140.0 Y0.1 Z0.3 F1500.0 E10\nG1 X140 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E20\nG1 Z2.0 F1500.0\nG92 E0\n
|
||||||
|
end_gcode = G1 X0 Y140\nM107\nG91\nG0 Z20\nT0\nG1 E-2\nM104 T0 S0\nG90\nG92 E0\nM140 S0\nM84\nM300 S2093 P150\nM300 S2637 P150\nM300 S3135 P150\nM300 S4186 P150\nM300 S3135 P150\nM300 S2637 P150\nM300 S2793 P150\nM300 S2349 P150\nM300 S1975 P150\nM300 S2093 P450\n
|
||||||
|
|
||||||
|
[printer:Rigid3D Mucit2]
|
||||||
|
inherits = *common*
|
||||||
|
bed_shape = 0x0,150x0,150x150,0x150
|
||||||
|
max_print_height = 150
|
||||||
|
printer_model = Mucit2
|
||||||
|
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_RIGID3D\nPRINTER_MODEL_MUCIT2\nPRINTER_HAS_HEATEDBED\n
|
||||||
|
start_gcode = G21\nG92 E0\nG28\nM420 S1\nM107\nG90\nG1 X10.0 Y0.1 Z0.3 F3000.0\nG1 X140.0 Y0.1 Z0.3 F1500.0 E10\nG1 X140 Y0.4 Z0.3 F3000.0\nG1 X10.0 Y0.4 Z0.3 F1500.0 E20\nG1 Z2.0 F1500.0\nG92 E0\n
|
||||||
|
end_gcode = G92 E0\nT0\nG1 F1800 E-2\nG27 P2\nM107\nM104 T0 S0\nM140 S0\nG90\nG92 E0\nM18\n
|
BIN
resources/profiles/Rigid3D/Mucit2_thumbnail.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
resources/profiles/Rigid3D/Mucit_thumbnail.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
resources/profiles/Rigid3D/Zero2_thumbnail.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
resources/profiles/Rigid3D/Zero3_thumbnail.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
resources/profiles/Rigid3D/mucit2_bed.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
resources/profiles/Rigid3D/mucit2_bed.stl
Normal file
BIN
resources/profiles/Rigid3D/mucit_bed.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
resources/profiles/Rigid3D/mucit_bed.stl
Normal file
BIN
resources/profiles/Rigid3D/zero2_bed.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
resources/profiles/Rigid3D/zero3_bed.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
resources/profiles/Rigid3D/zero_bed.stl
Normal file
@ -1,8 +1,6 @@
|
|||||||
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
#ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
||||||
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
#define SRC_LIBSLIC3R_AABBTREELINES_HPP_
|
||||||
|
|
||||||
#include "libslic3r/Point.hpp"
|
|
||||||
#include "libslic3r/EdgeGrid.hpp"
|
|
||||||
#include "libslic3r/AABBTreeIndirect.hpp"
|
#include "libslic3r/AABBTreeIndirect.hpp"
|
||||||
#include "libslic3r/Line.hpp"
|
#include "libslic3r/Line.hpp"
|
||||||
|
|
||||||
|
@ -245,6 +245,8 @@ set(SLIC3R_SOURCES
|
|||||||
SlicingAdaptive.hpp
|
SlicingAdaptive.hpp
|
||||||
Subdivide.cpp
|
Subdivide.cpp
|
||||||
Subdivide.hpp
|
Subdivide.hpp
|
||||||
|
SupportSpotsGenerator.cpp
|
||||||
|
SupportSpotsGenerator.hpp
|
||||||
SupportMaterial.cpp
|
SupportMaterial.cpp
|
||||||
SupportMaterial.hpp
|
SupportMaterial.hpp
|
||||||
Surface.cpp
|
Surface.cpp
|
||||||
@ -277,6 +279,8 @@ set(SLIC3R_SOURCES
|
|||||||
TriangleSelector.hpp
|
TriangleSelector.hpp
|
||||||
TriangleSetSampling.cpp
|
TriangleSetSampling.cpp
|
||||||
TriangleSetSampling.hpp
|
TriangleSetSampling.hpp
|
||||||
|
TriangleSelectorWrapper.cpp
|
||||||
|
TriangleSelectorWrapper.hpp
|
||||||
MTUtils.hpp
|
MTUtils.hpp
|
||||||
Zipper.hpp
|
Zipper.hpp
|
||||||
Zipper.cpp
|
Zipper.cpp
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "libslic3r/format.hpp"
|
#include "libslic3r/format.hpp"
|
||||||
#include "GCodeProcessor.hpp"
|
#include "GCodeProcessor.hpp"
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/case_conv.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/algorithm/string/split.hpp>
|
#include <boost/algorithm/string/split.hpp>
|
||||||
@ -777,8 +778,7 @@ void GCodeProcessorResult::reset() {
|
|||||||
max_print_height = 0.0f;
|
max_print_height = 0.0f;
|
||||||
settings_ids.reset();
|
settings_ids.reset();
|
||||||
extruders_count = 0;
|
extruders_count = 0;
|
||||||
extruder_colors = DEFAULT_EXTRUDER_COLORS;
|
extruder_colors = std::vector<std::string>();
|
||||||
assert(extruder_colors.size() == MIN_EXTRUDERS_COUNT);
|
|
||||||
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
|
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
|
||||||
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
|
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
|
||||||
#if ENABLE_USED_FILAMENT_POST_PROCESS
|
#if ENABLE_USED_FILAMENT_POST_PROCESS
|
||||||
@ -870,6 +870,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||||||
{
|
{
|
||||||
m_parser.apply_config(config);
|
m_parser.apply_config(config);
|
||||||
|
|
||||||
|
m_producer = EProducer::PrusaSlicer;
|
||||||
m_flavor = config.gcode_flavor;
|
m_flavor = config.gcode_flavor;
|
||||||
|
|
||||||
size_t extruders_count = config.nozzle_diameter.values.size();
|
size_t extruders_count = config.nozzle_diameter.values.size();
|
||||||
@ -1093,6 +1094,20 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// With MM setups like Prusa MMU2, the filaments may be expected to be parked at the beginning.
|
||||||
|
// Remember the parking position so the initial load is not included in filament estimate.
|
||||||
|
const ConfigOptionBool* single_extruder_multi_material = config.option<ConfigOptionBool>("single_extruder_multi_material");
|
||||||
|
const ConfigOptionBool* wipe_tower = config.option<ConfigOptionBool>("wipe_tower");
|
||||||
|
const ConfigOptionFloat* parking_pos_retraction = config.option<ConfigOptionFloat>("parking_pos_retraction");
|
||||||
|
const ConfigOptionFloat* extra_loading_move = config.option<ConfigOptionFloat>("extra_loading_move");
|
||||||
|
|
||||||
|
if (single_extruder_multi_material != nullptr && wipe_tower != nullptr && parking_pos_retraction != nullptr && extra_loading_move != nullptr) {
|
||||||
|
if (single_extruder_multi_material->value && m_result.extruders_count > 1 && wipe_tower->value) {
|
||||||
|
m_parking_position = float(parking_pos_retraction->value);
|
||||||
|
m_extra_loading_move = float(extra_loading_move->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool use_machine_limits = false;
|
bool use_machine_limits = false;
|
||||||
const ConfigOptionEnum<MachineLimitsUsage>* machine_limits_usage = config.option<ConfigOptionEnum<MachineLimitsUsage>>("machine_limits_usage");
|
const ConfigOptionEnum<MachineLimitsUsage>* machine_limits_usage = config.option<ConfigOptionEnum<MachineLimitsUsage>>("machine_limits_usage");
|
||||||
if (machine_limits_usage != nullptr)
|
if (machine_limits_usage != nullptr)
|
||||||
@ -1289,6 +1304,7 @@ void GCodeProcessor::reset()
|
|||||||
m_options_z_corrector.reset();
|
m_options_z_corrector.reset();
|
||||||
|
|
||||||
m_spiral_vase_active = false;
|
m_spiral_vase_active = false;
|
||||||
|
m_kissslicer_toolchange_time_correction = 0.0f;
|
||||||
|
|
||||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||||
m_mm3_per_mm_compare.reset();
|
m_mm3_per_mm_compare.reset();
|
||||||
@ -1343,10 +1359,16 @@ void GCodeProcessor::process_file(const std::string& filename, std::function<voi
|
|||||||
config.load_from_gcode_file(filename, ForwardCompatibilitySubstitutionRule::EnableSilent);
|
config.load_from_gcode_file(filename, ForwardCompatibilitySubstitutionRule::EnableSilent);
|
||||||
apply_config(config);
|
apply_config(config);
|
||||||
}
|
}
|
||||||
else if (m_producer == EProducer::Simplify3D)
|
else {
|
||||||
apply_config_simplify3d(filename);
|
m_result.extruder_colors = DEFAULT_EXTRUDER_COLORS;
|
||||||
else if (m_producer == EProducer::SuperSlicer)
|
|
||||||
apply_config_superslicer(filename);
|
if (m_producer == EProducer::Simplify3D)
|
||||||
|
apply_config_simplify3d(filename);
|
||||||
|
else if (m_producer == EProducer::SuperSlicer)
|
||||||
|
apply_config_superslicer(filename);
|
||||||
|
else if (m_producer == EProducer::KissSlicer)
|
||||||
|
apply_config_kissslicer(filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// process gcode
|
// process gcode
|
||||||
@ -1529,6 +1551,82 @@ void GCodeProcessor::apply_config_superslicer(const std::string& filename)
|
|||||||
apply_config(config);
|
apply_config(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GCodeProcessor::apply_config_kissslicer(const std::string& filename)
|
||||||
|
{
|
||||||
|
size_t found_counter = 0;
|
||||||
|
m_parser.parse_file_raw(filename, [this, &found_counter](GCodeReader& reader, const char* begin, const char* end) {
|
||||||
|
auto detect_flavor = [this](const std::string_view comment) {
|
||||||
|
static const std::string search_str = "firmware_type";
|
||||||
|
const size_t pos = comment.find(search_str);
|
||||||
|
if (pos != comment.npos) {
|
||||||
|
std::vector<std::string> elements;
|
||||||
|
boost::split(elements, comment, boost::is_any_of("="));
|
||||||
|
if (elements.size() == 2) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (std::stoi(elements[1]))
|
||||||
|
{
|
||||||
|
default: { break; }
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3: { m_flavor = gcfMarlinLegacy; break; }
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
// invalid data, do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto detect_printer = [this](const std::string_view comment) {
|
||||||
|
static const std::string search_str = "printer_name";
|
||||||
|
const size_t pos = comment.find(search_str);
|
||||||
|
if (pos != comment.npos) {
|
||||||
|
std::vector<std::string> elements;
|
||||||
|
boost::split(elements, comment, boost::is_any_of("="));
|
||||||
|
if (elements.size() == 2) {
|
||||||
|
elements[1] = boost::to_upper_copy(elements[1]);
|
||||||
|
if (boost::contains(elements[1], "MK2.5") || boost::contains(elements[1], "MK3"))
|
||||||
|
m_kissslicer_toolchange_time_correction = 18.0f; // MMU2
|
||||||
|
else if (boost::contains(elements[1], "MK2"))
|
||||||
|
m_kissslicer_toolchange_time_correction = 5.0f; // MMU
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
begin = skip_whitespaces(begin, end);
|
||||||
|
if (begin != end) {
|
||||||
|
if (*begin == ';') {
|
||||||
|
// Comment.
|
||||||
|
begin = skip_whitespaces(++begin, end);
|
||||||
|
end = remove_eols(begin, end);
|
||||||
|
if (begin != end) {
|
||||||
|
const std::string_view comment(begin, end - begin);
|
||||||
|
if (detect_flavor(comment) || detect_printer(comment))
|
||||||
|
++found_counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we got the data,
|
||||||
|
// force early exit to avoid parsing the entire file
|
||||||
|
if (found_counter == 2)
|
||||||
|
m_parser.quit_parsing();
|
||||||
|
}
|
||||||
|
else if (*begin == 'M' || *begin == 'G')
|
||||||
|
// the header has been fully parsed, quit search
|
||||||
|
m_parser.quit_parsing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
m_parser.reset();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<float> GCodeProcessor::get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const
|
std::vector<float> GCodeProcessor::get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const
|
||||||
{
|
{
|
||||||
return (mode < PrintEstimatedStatistics::ETimeMode::Count) ?
|
return (mode < PrintEstimatedStatistics::ETimeMode::Count) ?
|
||||||
@ -2559,7 +2657,7 @@ bool GCodeProcessor::process_bambustudio_tags(const std::string_view comment)
|
|||||||
bool GCodeProcessor::detect_producer(const std::string_view comment)
|
bool GCodeProcessor::detect_producer(const std::string_view comment)
|
||||||
{
|
{
|
||||||
for (const auto& [id, search_string] : Producers) {
|
for (const auto& [id, search_string] : Producers) {
|
||||||
size_t pos = comment.find(search_string);
|
const size_t pos = comment.find(search_string);
|
||||||
if (pos != comment.npos) {
|
if (pos != comment.npos) {
|
||||||
m_producer = id;
|
m_producer = id;
|
||||||
BOOST_LOG_TRIVIAL(info) << "Detected gcode producer: " << search_string;
|
BOOST_LOG_TRIVIAL(info) << "Detected gcode producer: " << search_string;
|
||||||
@ -3615,10 +3713,12 @@ void GCodeProcessor::process_T(const std::string_view command)
|
|||||||
// T-1 is a valid gcode line for RepRap Firmwares (used to deselects all tools) see https://github.com/prusa3d/PrusaSlicer/issues/5677
|
// T-1 is a valid gcode line for RepRap Firmwares (used to deselects all tools) see https://github.com/prusa3d/PrusaSlicer/issues/5677
|
||||||
if ((m_flavor != gcfRepRapFirmware && m_flavor != gcfRepRapSprinter) || eid != -1)
|
if ((m_flavor != gcfRepRapFirmware && m_flavor != gcfRepRapSprinter) || eid != -1)
|
||||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange (" << command << ").";
|
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange (" << command << ").";
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
unsigned char id = static_cast<unsigned char>(eid);
|
unsigned char id = static_cast<unsigned char>(eid);
|
||||||
if (m_extruder_id != id) {
|
if (m_extruder_id != id) {
|
||||||
if (id >= m_result.extruder_colors.size())
|
if (((m_producer == EProducer::PrusaSlicer || m_producer == EProducer::Slic3rPE || m_producer == EProducer::Slic3r) && id >= m_result.extruders_count) ||
|
||||||
|
((m_producer != EProducer::PrusaSlicer && m_producer != EProducer::Slic3rPE && m_producer != EProducer::Slic3r) && id >= m_result.extruder_colors.size()))
|
||||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange, maybe from a custom gcode.";
|
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange, maybe from a custom gcode.";
|
||||||
else {
|
else {
|
||||||
unsigned char old_extruder_id = m_extruder_id;
|
unsigned char old_extruder_id = m_extruder_id;
|
||||||
@ -3631,6 +3731,8 @@ void GCodeProcessor::process_T(const std::string_view command)
|
|||||||
float extra_time = get_filament_unload_time(static_cast<size_t>(old_extruder_id));
|
float extra_time = get_filament_unload_time(static_cast<size_t>(old_extruder_id));
|
||||||
m_time_processor.extruder_unloaded = false;
|
m_time_processor.extruder_unloaded = false;
|
||||||
extra_time += get_filament_load_time(static_cast<size_t>(m_extruder_id));
|
extra_time += get_filament_load_time(static_cast<size_t>(m_extruder_id));
|
||||||
|
if (m_producer == EProducer::KissSlicer && m_flavor == gcfMarlinLegacy)
|
||||||
|
extra_time += m_kissslicer_toolchange_time_correction;
|
||||||
simulate_st_synchronize(extra_time);
|
simulate_st_synchronize(extra_time);
|
||||||
|
|
||||||
m_result.extruders_count = std::max<size_t>(m_result.extruders_count, m_extruder_id + 1);
|
m_result.extruders_count = std::max<size_t>(m_result.extruders_count, m_extruder_id + 1);
|
||||||
|
@ -575,6 +575,7 @@ namespace Slic3r {
|
|||||||
OptionsZCorrector m_options_z_corrector;
|
OptionsZCorrector m_options_z_corrector;
|
||||||
size_t m_last_default_color_id;
|
size_t m_last_default_color_id;
|
||||||
bool m_spiral_vase_active;
|
bool m_spiral_vase_active;
|
||||||
|
float m_kissslicer_toolchange_time_correction;
|
||||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
|
std::chrono::time_point<std::chrono::high_resolution_clock> m_start_time;
|
||||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||||
@ -648,6 +649,7 @@ namespace Slic3r {
|
|||||||
void apply_config(const DynamicPrintConfig& config);
|
void apply_config(const DynamicPrintConfig& config);
|
||||||
void apply_config_simplify3d(const std::string& filename);
|
void apply_config_simplify3d(const std::string& filename);
|
||||||
void apply_config_superslicer(const std::string& filename);
|
void apply_config_superslicer(const std::string& filename);
|
||||||
|
void apply_config_kissslicer(const std::string& filename);
|
||||||
void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled);
|
void process_gcode_line(const GCodeReader::GCodeLine& line, bool producers_enabled);
|
||||||
|
|
||||||
// Process tags embedded into comments
|
// Process tags embedded into comments
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "SeamPlacer.hpp"
|
#include "SeamPlacer.hpp"
|
||||||
|
|
||||||
|
#include "Point.hpp"
|
||||||
|
#include "libslic3r.h"
|
||||||
#include "tbb/parallel_for.h"
|
#include "tbb/parallel_for.h"
|
||||||
#include "tbb/blocked_range.h"
|
#include "tbb/blocked_range.h"
|
||||||
#include "tbb/parallel_reduce.h"
|
#include "tbb/parallel_reduce.h"
|
||||||
@ -642,8 +644,8 @@ void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po,
|
|||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug)
|
BOOST_LOG_TRIVIAL(debug)
|
||||||
<< "SeamPlacer: decimate: start";
|
<< "SeamPlacer: decimate: start";
|
||||||
its_short_edge_collpase(triangle_set, 25000);
|
its_short_edge_collpase(triangle_set, SeamPlacer::fast_decimation_triangle_count_target);
|
||||||
its_short_edge_collpase(negative_volumes_set, 25000);
|
its_short_edge_collpase(negative_volumes_set, SeamPlacer::fast_decimation_triangle_count_target);
|
||||||
|
|
||||||
size_t negative_volumes_start_index = triangle_set.indices.size();
|
size_t negative_volumes_start_index = triangle_set.indices.size();
|
||||||
its_merge(triangle_set, negative_volumes_set);
|
its_merge(triangle_set, negative_volumes_set);
|
||||||
@ -729,8 +731,9 @@ void gather_enforcers_blockers(GlobalModelInfo &result, const PrintObject *po) {
|
|||||||
struct SeamComparator {
|
struct SeamComparator {
|
||||||
SeamPosition setup;
|
SeamPosition setup;
|
||||||
float angle_importance;
|
float angle_importance;
|
||||||
explicit SeamComparator(SeamPosition setup) :
|
Vec2f rear_attractor;
|
||||||
setup(setup) {
|
explicit SeamComparator(SeamPosition setup, const Vec2f& rear_attractor = Vec2f::Zero()) :
|
||||||
|
setup(setup), rear_attractor(rear_attractor) {
|
||||||
angle_importance =
|
angle_importance =
|
||||||
setup == spNearest ? SeamPlacer::angle_importance_nearest : SeamPlacer::angle_importance_aligned;
|
setup == spNearest ? SeamPlacer::angle_importance_nearest : SeamPlacer::angle_importance_aligned;
|
||||||
}
|
}
|
||||||
@ -761,8 +764,9 @@ struct SeamComparator {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setup == SeamPosition::spRear && a.position.y() != b.position.y()) {
|
if (setup == SeamPosition::spRear) {
|
||||||
return a.position.y() > b.position.y();
|
return (a.position.head<2>() - rear_attractor).squaredNorm() <
|
||||||
|
(b.position.head<2>() - rear_attractor).squaredNorm();
|
||||||
}
|
}
|
||||||
|
|
||||||
float distance_penalty_a = 0.0f;
|
float distance_penalty_a = 0.0f;
|
||||||
@ -824,7 +828,8 @@ struct SeamComparator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (setup == SeamPosition::spRear) {
|
if (setup == SeamPosition::spRear) {
|
||||||
return a.position.y() + SeamPlacer::seam_align_score_tolerance * 5.0f > b.position.y();
|
return (a.position.head<2>() - rear_attractor).squaredNorm() - a.perimeter.flow_width <
|
||||||
|
(b.position.head<2>() - rear_attractor).squaredNorm();
|
||||||
}
|
}
|
||||||
|
|
||||||
float penalty_a = a.overhang + a.visibility
|
float penalty_a = a.overhang + a.visibility
|
||||||
@ -1452,7 +1457,9 @@ void SeamPlacer::init(const Print &print, std::function<void(void)> throw_if_can
|
|||||||
for (const PrintObject *po : print.objects()) {
|
for (const PrintObject *po : print.objects()) {
|
||||||
throw_if_canceled_func();
|
throw_if_canceled_func();
|
||||||
SeamPosition configured_seam_preference = po->config().seam_position.value;
|
SeamPosition configured_seam_preference = po->config().seam_position.value;
|
||||||
SeamComparator comparator { configured_seam_preference };
|
Vec2f rear_attractor = unscaled(po->bounding_box().center()).cast<float>() +
|
||||||
|
1.5f * Vec2f(0.0f, unscale<float>(po->bounding_box().max.y()));
|
||||||
|
SeamComparator comparator{configured_seam_preference, rear_attractor};
|
||||||
|
|
||||||
{
|
{
|
||||||
GlobalModelInfo global_model_info { };
|
GlobalModelInfo global_model_info { };
|
||||||
|
@ -110,6 +110,7 @@ class SeamPlacer {
|
|||||||
public:
|
public:
|
||||||
// Number of samples generated on the mesh. There are sqr_rays_per_sample_point*sqr_rays_per_sample_point rays casted from each samples
|
// Number of samples generated on the mesh. There are sqr_rays_per_sample_point*sqr_rays_per_sample_point rays casted from each samples
|
||||||
static constexpr size_t raycasting_visibility_samples_count = 30000;
|
static constexpr size_t raycasting_visibility_samples_count = 30000;
|
||||||
|
static constexpr size_t fast_decimation_triangle_count_target = 16000;
|
||||||
//square of number of rays per sample point
|
//square of number of rays per sample point
|
||||||
static constexpr size_t sqr_rays_per_sample_point = 5;
|
static constexpr size_t sqr_rays_per_sample_point = 5;
|
||||||
|
|
||||||
|
@ -924,6 +924,66 @@ void PresetCollection::save_current_preset(const std::string &new_name, bool det
|
|||||||
this->get_selected_preset().save();
|
this->get_selected_preset().save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Preset& PresetCollection::get_preset_with_name(const std::string& new_name, const Preset* initial_preset)
|
||||||
|
{
|
||||||
|
// 1) Find the preset with a new_name or create a new one,
|
||||||
|
// initialize it with the preset_to config.
|
||||||
|
auto it = this->find_preset_internal(new_name);
|
||||||
|
if (it != m_presets.end() && it->name == new_name) {
|
||||||
|
// Preset with the same name found.
|
||||||
|
Preset& preset = *it;
|
||||||
|
if (!preset.is_default && !preset.is_external && !preset.is_system && initial_preset->name != new_name) {
|
||||||
|
// Overwriting an existing preset if it isn't default/external/system or isn't an initial_preset
|
||||||
|
preset.config = initial_preset->config;
|
||||||
|
// The newly saved preset can be activated -> make it visible.
|
||||||
|
preset.is_visible = true;
|
||||||
|
}
|
||||||
|
return preset;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string selected_preset_name = this->get_selected_preset_name();
|
||||||
|
|
||||||
|
// Creating a new preset.
|
||||||
|
Preset& preset = *m_presets.insert(it, *initial_preset);
|
||||||
|
std::string& inherits = preset.inherits();
|
||||||
|
std::string old_name = preset.name;
|
||||||
|
preset.name = new_name;
|
||||||
|
preset.file = this->path_from_name(new_name);
|
||||||
|
preset.vendor = nullptr;
|
||||||
|
preset.alias.clear();
|
||||||
|
preset.renamed_from.clear();
|
||||||
|
if (preset.is_system) {
|
||||||
|
// Inheriting from a system preset.
|
||||||
|
inherits = old_name;
|
||||||
|
}
|
||||||
|
else if (inherits.empty()) {
|
||||||
|
// Inheriting from a user preset. Link the new preset to the old preset.
|
||||||
|
// inherits = old_name;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Inherited from a user preset. Just maintain the "inherited" flag,
|
||||||
|
// meaning it will inherit from either the system preset, or the inherited user preset.
|
||||||
|
}
|
||||||
|
preset.is_default = false;
|
||||||
|
preset.is_system = false;
|
||||||
|
preset.is_external = false;
|
||||||
|
// The newly saved preset can be activated -> make it visible.
|
||||||
|
preset.is_visible = true;
|
||||||
|
// Just system presets have aliases
|
||||||
|
preset.alias.clear();
|
||||||
|
|
||||||
|
// sort printers and get new it
|
||||||
|
std::sort(m_presets.begin(), m_presets.end());
|
||||||
|
|
||||||
|
// set initial preset selection
|
||||||
|
this->select_preset_by_name(selected_preset_name, true);
|
||||||
|
|
||||||
|
it = this->find_preset_internal(new_name);
|
||||||
|
assert(it != m_presets.end());
|
||||||
|
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
bool PresetCollection::delete_current_preset()
|
bool PresetCollection::delete_current_preset()
|
||||||
{
|
{
|
||||||
const Preset &selected = this->get_selected_preset();
|
const Preset &selected = this->get_selected_preset();
|
||||||
@ -947,6 +1007,11 @@ bool PresetCollection::delete_current_preset()
|
|||||||
|
|
||||||
bool PresetCollection::delete_preset(const std::string& name)
|
bool PresetCollection::delete_preset(const std::string& name)
|
||||||
{
|
{
|
||||||
|
if (name == this->get_selected_preset().name)
|
||||||
|
return delete_current_preset();
|
||||||
|
|
||||||
|
const std::string selected_preset_name = this->get_selected_preset_name();
|
||||||
|
|
||||||
auto it = this->find_preset_internal(name);
|
auto it = this->find_preset_internal(name);
|
||||||
|
|
||||||
const Preset& preset = *it;
|
const Preset& preset = *it;
|
||||||
@ -957,6 +1022,10 @@ bool PresetCollection::delete_preset(const std::string& name)
|
|||||||
boost::nowide::remove(preset.file.c_str());
|
boost::nowide::remove(preset.file.c_str());
|
||||||
}
|
}
|
||||||
m_presets.erase(it);
|
m_presets.erase(it);
|
||||||
|
|
||||||
|
// update selected preset
|
||||||
|
this->select_preset_by_name(selected_preset_name, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,6 +341,10 @@ public:
|
|||||||
// All presets are marked as not modified and the new preset is activated.
|
// All presets are marked as not modified and the new preset is activated.
|
||||||
void save_current_preset(const std::string &new_name, bool detach = false);
|
void save_current_preset(const std::string &new_name, bool detach = false);
|
||||||
|
|
||||||
|
// Find the preset with a new_name or create a new one,
|
||||||
|
// initialize it with the initial_preset config.
|
||||||
|
Preset& get_preset_with_name(const std::string& new_name, const Preset* initial_preset);
|
||||||
|
|
||||||
// Delete the current preset, activate the first visible preset.
|
// Delete the current preset, activate the first visible preset.
|
||||||
// returns true if the preset was deleted successfully.
|
// returns true if the preset was deleted successfully.
|
||||||
bool delete_current_preset();
|
bool delete_current_preset();
|
||||||
|
@ -425,16 +425,24 @@ void PresetBundle::load_installed_printers(const AppConfig &config)
|
|||||||
preset.set_visible_from_appconfig(config);
|
preset.set_visible_from_appconfig(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& PresetBundle::get_preset_name_by_alias( const Preset::Type& preset_type, const std::string& alias) const
|
PresetCollection& PresetBundle::get_presets(Preset::Type type)
|
||||||
|
{
|
||||||
|
assert(type >= Preset::TYPE_PRINT && type <= Preset::TYPE_PRINTER);
|
||||||
|
|
||||||
|
return type == Preset::TYPE_PRINT ? prints :
|
||||||
|
type == Preset::TYPE_SLA_PRINT ? sla_prints :
|
||||||
|
type == Preset::TYPE_FILAMENT ? filaments :
|
||||||
|
type == Preset::TYPE_SLA_MATERIAL ? sla_materials : printers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::string& PresetBundle::get_preset_name_by_alias( const Preset::Type& preset_type, const std::string& alias)
|
||||||
{
|
{
|
||||||
// there are not aliases for Printers profiles
|
// there are not aliases for Printers profiles
|
||||||
if (preset_type == Preset::TYPE_PRINTER || preset_type == Preset::TYPE_INVALID)
|
if (preset_type == Preset::TYPE_PRINTER || preset_type == Preset::TYPE_INVALID)
|
||||||
return alias;
|
return alias;
|
||||||
|
|
||||||
const PresetCollection& presets = preset_type == Preset::TYPE_PRINT ? prints :
|
const PresetCollection& presets = get_presets(preset_type);
|
||||||
preset_type == Preset::TYPE_SLA_PRINT ? sla_prints :
|
|
||||||
preset_type == Preset::TYPE_FILAMENT ? filaments :
|
|
||||||
sla_materials;
|
|
||||||
|
|
||||||
return presets.get_preset_name_by_alias(alias);
|
return presets.get_preset_name_by_alias(alias);
|
||||||
}
|
}
|
||||||
@ -442,10 +450,7 @@ const std::string& PresetBundle::get_preset_name_by_alias( const Preset::Type& p
|
|||||||
void PresetBundle::save_changes_for_preset(const std::string& new_name, Preset::Type type,
|
void PresetBundle::save_changes_for_preset(const std::string& new_name, Preset::Type type,
|
||||||
const std::vector<std::string>& unselected_options)
|
const std::vector<std::string>& unselected_options)
|
||||||
{
|
{
|
||||||
PresetCollection& presets = type == Preset::TYPE_PRINT ? prints :
|
PresetCollection& presets = get_presets(type);
|
||||||
type == Preset::TYPE_SLA_PRINT ? sla_prints :
|
|
||||||
type == Preset::TYPE_FILAMENT ? filaments :
|
|
||||||
type == Preset::TYPE_SLA_MATERIAL ? sla_materials : printers;
|
|
||||||
|
|
||||||
// if we want to save just some from selected options
|
// if we want to save just some from selected options
|
||||||
if (!unselected_options.empty()) {
|
if (!unselected_options.empty()) {
|
||||||
@ -468,6 +473,49 @@ void PresetBundle::save_changes_for_preset(const std::string& new_name, Preset::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PresetBundle::transfer_and_save(Preset::Type type, const std::string& preset_from_name, const std::string& preset_to_name,
|
||||||
|
const std::string& preset_new_name, const std::vector<std::string>& options)
|
||||||
|
{
|
||||||
|
if (options.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PresetCollection& presets = get_presets(type);
|
||||||
|
|
||||||
|
const Preset* preset_to = presets.find_preset(preset_to_name, false, false);
|
||||||
|
if (!preset_to)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Find the preset with a new_name or create a new one,
|
||||||
|
// initialize it with the preset_to config.
|
||||||
|
Preset& preset = presets.get_preset_with_name(preset_new_name, preset_to);
|
||||||
|
if (preset.is_default || preset.is_external || preset.is_system)
|
||||||
|
// Cannot overwrite the default preset.
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Apply options from the preset_from_name.
|
||||||
|
const Preset* preset_from = presets.find_preset(preset_from_name, false, false);
|
||||||
|
if (!preset_from)
|
||||||
|
return false;
|
||||||
|
preset.config.apply_only(preset_from->config, options);
|
||||||
|
|
||||||
|
// Store new_name preset to disk.
|
||||||
|
preset.save();
|
||||||
|
|
||||||
|
// Mark the print & filament enabled if they are compatible with the currently selected preset.
|
||||||
|
// If saving the preset changes compatibility with other presets, keep the now incompatible dependent presets selected, however with a "red flag" icon showing that they are no more compatible.
|
||||||
|
update_compatible(PresetSelectCompatibleType::Never);
|
||||||
|
|
||||||
|
if (type == Preset::TYPE_PRINTER)
|
||||||
|
copy_bed_model_and_texture_if_needed(preset.config);
|
||||||
|
|
||||||
|
if (type == Preset::TYPE_FILAMENT) {
|
||||||
|
// synchronize the first filament presets.
|
||||||
|
set_filament_preset(0, filaments.get_selected_preset_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void PresetBundle::load_installed_filaments(AppConfig &config)
|
void PresetBundle::load_installed_filaments(AppConfig &config)
|
||||||
{
|
{
|
||||||
if (! config.has_section(AppConfig::SECTION_FILAMENTS)) {
|
if (! config.has_section(AppConfig::SECTION_FILAMENTS)) {
|
||||||
|
@ -54,6 +54,8 @@ public:
|
|||||||
// extruders.size() should be the same as printers.get_edited_preset().config.nozzle_diameter.size()
|
// extruders.size() should be the same as printers.get_edited_preset().config.nozzle_diameter.size()
|
||||||
std::vector<std::string> filament_presets;
|
std::vector<std::string> filament_presets;
|
||||||
|
|
||||||
|
PresetCollection& get_presets(Preset::Type preset_type);
|
||||||
|
|
||||||
// The project configuration values are kept separated from the print/filament/printer preset,
|
// The project configuration values are kept separated from the print/filament/printer preset,
|
||||||
// they are being serialized / deserialized from / to the .amf, .3mf, .config, .gcode,
|
// they are being serialized / deserialized from / to the .amf, .3mf, .config, .gcode,
|
||||||
// and they are being used by slicing core.
|
// and they are being used by slicing core.
|
||||||
@ -142,11 +144,15 @@ public:
|
|||||||
// If the "vendor" section is missing, enable all models and variants of the particular vendor.
|
// If the "vendor" section is missing, enable all models and variants of the particular vendor.
|
||||||
void load_installed_printers(const AppConfig &config);
|
void load_installed_printers(const AppConfig &config);
|
||||||
|
|
||||||
const std::string& get_preset_name_by_alias(const Preset::Type& preset_type, const std::string& alias) const;
|
const std::string& get_preset_name_by_alias(const Preset::Type& preset_type, const std::string& alias);
|
||||||
|
|
||||||
// Save current preset of a provided type under a new name. If the name is different from the old one,
|
// Save current preset of a provided type under a new name. If the name is different from the old one,
|
||||||
// Unselected option would be reverted to the beginning values
|
// Unselected option would be reverted to the beginning values
|
||||||
void save_changes_for_preset(const std::string& new_name, Preset::Type type, const std::vector<std::string>& unselected_options);
|
void save_changes_for_preset(const std::string& new_name, Preset::Type type, const std::vector<std::string>& unselected_options);
|
||||||
|
// Transfer options form preset_from_name preset to preset_to_name preset and save preset_to_name preset as new new_name preset
|
||||||
|
// Return false, if new preset wasn't saved
|
||||||
|
bool transfer_and_save(Preset::Type type, const std::string& preset_from_name, const std::string& preset_to_name,
|
||||||
|
const std::string& new_name, const std::vector<std::string>& options);
|
||||||
|
|
||||||
static const char *PRUSA_BUNDLE;
|
static const char *PRUSA_BUNDLE;
|
||||||
private:
|
private:
|
||||||
|
@ -825,6 +825,8 @@ void Print::process()
|
|||||||
obj->infill();
|
obj->infill();
|
||||||
for (PrintObject *obj : m_objects)
|
for (PrintObject *obj : m_objects)
|
||||||
obj->ironing();
|
obj->ironing();
|
||||||
|
for (PrintObject *obj : m_objects)
|
||||||
|
obj->generate_support_spots();
|
||||||
for (PrintObject *obj : m_objects)
|
for (PrintObject *obj : m_objects)
|
||||||
obj->generate_support_material();
|
obj->generate_support_material();
|
||||||
if (this->set_started(psWipeTower)) {
|
if (this->set_started(psWipeTower)) {
|
||||||
|
@ -61,7 +61,7 @@ enum PrintStep : unsigned int {
|
|||||||
|
|
||||||
enum PrintObjectStep : unsigned int {
|
enum PrintObjectStep : unsigned int {
|
||||||
posSlice, posPerimeters, posPrepareInfill,
|
posSlice, posPerimeters, posPrepareInfill,
|
||||||
posInfill, posIroning, posSupportMaterial, posCount,
|
posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posCount,
|
||||||
};
|
};
|
||||||
|
|
||||||
// A PrintRegion object represents a group of volumes to print
|
// A PrintRegion object represents a group of volumes to print
|
||||||
@ -381,6 +381,7 @@ private:
|
|||||||
void prepare_infill();
|
void prepare_infill();
|
||||||
void infill();
|
void infill();
|
||||||
void ironing();
|
void ironing();
|
||||||
|
void generate_support_spots();
|
||||||
void generate_support_material();
|
void generate_support_material();
|
||||||
|
|
||||||
void slice_volumes();
|
void slice_volumes();
|
||||||
|
@ -1195,8 +1195,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
update_apply_status(false);
|
update_apply_status(false);
|
||||||
}
|
}
|
||||||
// Invalidate just the supports step.
|
// Invalidate just the supports step.
|
||||||
for (const PrintObjectStatus &print_object_status : print_objects_range)
|
for (const PrintObjectStatus &print_object_status : print_objects_range) {
|
||||||
|
update_apply_status(print_object_status.print_object->invalidate_step(posSupportSpotsSearch));
|
||||||
update_apply_status(print_object_status.print_object->invalidate_step(posSupportMaterial));
|
update_apply_status(print_object_status.print_object->invalidate_step(posSupportMaterial));
|
||||||
|
}
|
||||||
if (supports_differ) {
|
if (supports_differ) {
|
||||||
// Copy just the support volumes.
|
// Copy just the support volumes.
|
||||||
model_volume_list_update_supports(model_object, model_object_new);
|
model_volume_list_update_supports(model_object, model_object_new);
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#include "Fill/FillAdaptive.hpp"
|
#include "Fill/FillAdaptive.hpp"
|
||||||
#include "Fill/FillLightning.hpp"
|
#include "Fill/FillLightning.hpp"
|
||||||
#include "Format/STL.hpp"
|
#include "Format/STL.hpp"
|
||||||
|
#include "SupportSpotsGenerator.hpp"
|
||||||
|
#include "TriangleSelectorWrapper.hpp"
|
||||||
|
#include "format.hpp"
|
||||||
|
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
@ -394,6 +397,65 @@ void PrintObject::ironing()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
std::vector<size_t> problematic_layers = SupportSpotsGenerator::quick_search(this);
|
||||||
|
if (!problematic_layers.empty()) {
|
||||||
|
std::cout << "Object needs supports" << std::endl;
|
||||||
|
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
|
||||||
|
L("Supportable issues found. Consider enabling supports for this object"));
|
||||||
|
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
|
||||||
|
L("Supportable issues found. Consider enabling supports for this object"));
|
||||||
|
for (size_t index = 0; index < std::min(problematic_layers.size(), size_t(4)); ++index) {
|
||||||
|
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL,
|
||||||
|
format(L("Layer with issues: %1%"), problematic_layers[index] + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void PrintObject::generate_support_spots()
|
||||||
|
{
|
||||||
|
if (this->set_started(posSupportSpotsSearch)) {
|
||||||
|
BOOST_LOG_TRIVIAL(debug)
|
||||||
|
<< "Searching support spots - start";
|
||||||
|
m_print->set_status(75, L("Searching support spots"));
|
||||||
|
if (this->m_config.support_material && !this->m_config.support_material_auto &&
|
||||||
|
std::all_of(this->model_object()->volumes.begin(), this->model_object()->volumes.end(),
|
||||||
|
[](const ModelVolume* mv){return mv->supported_facets.empty();})
|
||||||
|
) {
|
||||||
|
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values};
|
||||||
|
SupportSpotsGenerator::Issues issues = SupportSpotsGenerator::full_search(this, params);
|
||||||
|
auto obj_transform = this->trafo_centered();
|
||||||
|
for (ModelVolume *model_volume : this->model_object()->volumes) {
|
||||||
|
if (model_volume->is_model_part()) {
|
||||||
|
Transform3d mesh_transformation = obj_transform * model_volume->get_matrix();
|
||||||
|
Transform3d inv_transform = mesh_transformation.inverse();
|
||||||
|
TriangleSelectorWrapper selector { model_volume->mesh(), mesh_transformation};
|
||||||
|
|
||||||
|
for (const SupportSpotsGenerator::SupportPoint &support_point : issues.support_points) {
|
||||||
|
Vec3f point = Vec3f(inv_transform.cast<float>() * support_point.position);
|
||||||
|
Vec3f origin = Vec3f(
|
||||||
|
inv_transform.cast<float>() * Vec3f(support_point.position.x(), support_point.position.y(), 0.0f));
|
||||||
|
selector.enforce_spot(point, origin, support_point.spot_radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
model_volume->supported_facets.set(selector.selector);
|
||||||
|
#if 0 //DEBUG export
|
||||||
|
indexed_triangle_set copy = model_volume->mesh().its;
|
||||||
|
its_transform(copy, obj_transform * model_transformation);
|
||||||
|
its_write_obj(copy,
|
||||||
|
debug_out_path(("model"+std::to_string(model_volume->id().id)+".obj").c_str()).c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_print->throw_if_canceled();
|
||||||
|
BOOST_LOG_TRIVIAL(debug)
|
||||||
|
<< "Searching support spots - end";
|
||||||
|
this->set_done(posSupportSpotsSearch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PrintObject::generate_support_material()
|
void PrintObject::generate_support_material()
|
||||||
{
|
{
|
||||||
if (this->set_started(posSupportMaterial)) {
|
if (this->set_started(posSupportMaterial)) {
|
||||||
|
@ -98,6 +98,7 @@ void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_
|
|||||||
//shuffle the faces and traverse in random order, this MASSIVELY improves the quality of the result
|
//shuffle the faces and traverse in random order, this MASSIVELY improves the quality of the result
|
||||||
std::shuffle(face_indices.begin(), face_indices.end(), generator);
|
std::shuffle(face_indices.begin(), face_indices.end(), generator);
|
||||||
|
|
||||||
|
int allowed_face_removals = int(face_indices.size()) - int(target_triangle_count);
|
||||||
for (const size_t &face_idx : face_indices) {
|
for (const size_t &face_idx : face_indices) {
|
||||||
if (face_removal_flags[face_idx]) {
|
if (face_removal_flags[face_idx]) {
|
||||||
// if face already removed from previous collapses, skip (each collapse removes two triangles [at least] )
|
// if face already removed from previous collapses, skip (each collapse removes two triangles [at least] )
|
||||||
@ -130,10 +131,13 @@ void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_
|
|||||||
// remove faces
|
// remove faces
|
||||||
remove_face(face_idx, neighbor_to_remove_face_idx);
|
remove_face(face_idx, neighbor_to_remove_face_idx);
|
||||||
remove_face(neighbor_to_remove_face_idx, face_idx);
|
remove_face(neighbor_to_remove_face_idx, face_idx);
|
||||||
|
allowed_face_removals-=2;
|
||||||
|
|
||||||
// break. this triangle is done
|
// break. this triangle is done
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allowed_face_removals <= 0) { break; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter face_indices, remove those that have been collapsed
|
// filter face_indices, remove those that have been collapsed
|
||||||
|
1257
src/libslic3r/SupportSpotsGenerator.cpp
Normal file
82
src/libslic3r/SupportSpotsGenerator.hpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#ifndef SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
|
||||||
|
#define SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
|
||||||
|
|
||||||
|
#include "libslic3r/Print.hpp"
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
namespace SupportSpotsGenerator {
|
||||||
|
|
||||||
|
struct Params {
|
||||||
|
Params(const std::vector<std::string> &filament_types) {
|
||||||
|
if (filament_types.size() > 1) {
|
||||||
|
BOOST_LOG_TRIVIAL(warning)
|
||||||
|
<< "SupportSpotsGenerator does not currently handle different materials properly, only first will be used";
|
||||||
|
}
|
||||||
|
if (filament_types.empty() || filament_types[0].empty()) {
|
||||||
|
BOOST_LOG_TRIVIAL(error)
|
||||||
|
<< "SupportSpotsGenerator error: empty filament_type";
|
||||||
|
filament_type = std::string("PLA");
|
||||||
|
} else {
|
||||||
|
filament_type = filament_types[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
|
||||||
|
const float bridge_distance = 12.0f; //mm
|
||||||
|
const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (1 + this factor * (curvature / PI) )
|
||||||
|
const float overhang_angle_deg = 80.0f;
|
||||||
|
const std::pair<float,float> malformation_angle_span_deg = std::pair<float, float> { 45.0f, 80.0f };
|
||||||
|
|
||||||
|
const float min_distance_between_support_points = 3.0f; //mm
|
||||||
|
const float support_points_interface_radius = 1.5f; // mm
|
||||||
|
const float connections_min_considerable_area = 1.5f; //mm^2
|
||||||
|
const float small_parts_threshold = 5.0f; //mm^3
|
||||||
|
const float small_parts_support_points_interface_radius = 3.0f; // mm
|
||||||
|
|
||||||
|
std::string filament_type;
|
||||||
|
const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position.
|
||||||
|
const float max_acceleration = 9 * 1000.0f; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the jerk phase, so the usual machine limits are too low)
|
||||||
|
const double filament_density = 1.25e-3f; // g/mm^3 ; Common filaments are very lightweight, so precise number is not that important
|
||||||
|
const double material_yield_strength = 33.0f * 1e6f; // (g*mm/s^2)/mm^2; 33 MPa is yield strength of ABS, which has the lowest yield strength from common materials.
|
||||||
|
const float standard_extruder_conflict_force = 20.0f * gravity_constant; // force that can occasionally push the model due to various factors (filament leaks, small curling, ... );
|
||||||
|
const float malformations_additive_conflict_extruder_force = 300.0f * gravity_constant; // for areas with possible high layered curled filaments
|
||||||
|
|
||||||
|
// MPa * 1e^6 = (g*mm/s^2)/mm^2 = g/(mm*s^2); yield strength of the bed surface
|
||||||
|
double get_bed_adhesion_yield_strength() const {
|
||||||
|
if (filament_type == "PLA") {
|
||||||
|
return 0.018 * 1e6;
|
||||||
|
} else if (filament_type == "PET" || filament_type == "PETG") {
|
||||||
|
return 0.3 * 1e6;
|
||||||
|
} else { //PLA default value - defensive approach, PLA has quite low adhesion
|
||||||
|
return 0.018 * 1e6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//just return PLA adhesion value as value for supports
|
||||||
|
double get_support_spots_adhesion_strength() const {
|
||||||
|
return 0.018f * 1e6;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SupportPoint {
|
||||||
|
SupportPoint(const Vec3f &position, float force, float spot_radius, const Vec3f &direction);
|
||||||
|
Vec3f position;
|
||||||
|
float force;
|
||||||
|
float spot_radius;
|
||||||
|
Vec3f direction;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Issues {
|
||||||
|
std::vector<SupportPoint> support_points;
|
||||||
|
};
|
||||||
|
|
||||||
|
// std::vector<size_t> quick_search(const PrintObject *po, const Params ¶ms);
|
||||||
|
Issues full_search(const PrintObject *po, const Params ¶ms);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_ */
|
46
src/libslic3r/TriangleSelectorWrapper.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include "TriangleSelectorWrapper.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
TriangleSelectorWrapper::TriangleSelectorWrapper(const TriangleMesh &mesh, const Transform3d& mesh_transform) :
|
||||||
|
mesh(mesh), mesh_transform(mesh_transform), selector(mesh), triangles_tree(
|
||||||
|
AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set(mesh.its.vertices, mesh.its.indices)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriangleSelectorWrapper::enforce_spot(const Vec3f &point, const Vec3f &origin, float radius) {
|
||||||
|
std::vector<igl::Hit> hits;
|
||||||
|
Vec3f dir = (point - origin).normalized();
|
||||||
|
if (AABBTreeIndirect::intersect_ray_all_hits(mesh.its.vertices, mesh.its.indices, triangles_tree,
|
||||||
|
Vec3d(origin.cast<double>()),
|
||||||
|
Vec3d(dir.cast<double>()),
|
||||||
|
hits)) {
|
||||||
|
for (int hit_idx = hits.size() - 1; hit_idx >= 0; --hit_idx) {
|
||||||
|
const igl::Hit &hit = hits[hit_idx];
|
||||||
|
Vec3f pos = origin + dir * hit.t;
|
||||||
|
Vec3f face_normal = its_face_normal(mesh.its, hit.id);
|
||||||
|
if ((point - pos).norm() < radius && face_normal.dot(dir) < 0) {
|
||||||
|
std::unique_ptr<TriangleSelector::Cursor> cursor = std::make_unique<TriangleSelector::Sphere>(
|
||||||
|
pos, origin, radius, this->mesh_transform, TriangleSelector::ClippingPlane { });
|
||||||
|
selector.select_patch(hit.id, std::move(cursor), EnforcerBlockerType::ENFORCER, Transform3d::Identity(),
|
||||||
|
true, 0.0f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t hit_idx_out;
|
||||||
|
Vec3f hit_point_out;
|
||||||
|
float dist = AABBTreeIndirect::squared_distance_to_indexed_triangle_set(mesh.its.vertices, mesh.its.indices,
|
||||||
|
triangles_tree, point, hit_idx_out, hit_point_out);
|
||||||
|
if (dist < radius) {
|
||||||
|
std::unique_ptr<TriangleSelector::Cursor> cursor = std::make_unique<TriangleSelector::Sphere>(
|
||||||
|
point, origin, radius, this->mesh_transform, TriangleSelector::ClippingPlane { });
|
||||||
|
selector.select_patch(hit_idx_out, std::move(cursor), EnforcerBlockerType::ENFORCER,
|
||||||
|
Transform3d::Identity(),
|
||||||
|
true, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
31
src/libslic3r/TriangleSelectorWrapper.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#ifndef SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_
|
||||||
|
#define SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_
|
||||||
|
|
||||||
|
#include "TriangleSelector.hpp"
|
||||||
|
#include "Model.hpp"
|
||||||
|
#include "AABBTreeIndirect.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
//NOTE: We need to replace the FacetsAnnotation struct for support storage (or extend/add another)
|
||||||
|
// Problems: Does not support negative volumes, strange usage for supports computed from extrusion -
|
||||||
|
// expensively converted back to triangles and then sliced again.
|
||||||
|
// Another problem is weird and very limited interface when painting supports via algorithms
|
||||||
|
|
||||||
|
|
||||||
|
class TriangleSelectorWrapper {
|
||||||
|
public:
|
||||||
|
const TriangleMesh &mesh;
|
||||||
|
const Transform3d& mesh_transform;
|
||||||
|
TriangleSelector selector;
|
||||||
|
AABBTreeIndirect::Tree<3, float> triangles_tree;
|
||||||
|
|
||||||
|
TriangleSelectorWrapper(const TriangleMesh &mesh, const Transform3d& mesh_transform);
|
||||||
|
|
||||||
|
void enforce_spot(const Vec3f &point, const Vec3f& origin, float radius);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SRC_LIBSLIC3R_TRIANGLESELECTORWRAPPER_HPP_ */
|
@ -738,7 +738,7 @@ void BackgroundSlicingProcess::prepare_upload()
|
|||||||
|
|
||||||
ThumbnailsList thumbnails = this->render_thumbnails(
|
ThumbnailsList thumbnails = this->render_thumbnails(
|
||||||
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, true, true});
|
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, true, true});
|
||||||
m_sla_print->export_print(source_path.string(),thumbnails, m_upload_job.upload_data.upload_path.string());
|
m_sla_print->export_print(source_path.string(),thumbnails, m_upload_job.upload_data.upload_path.filename().string());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_print->set_status(100, (boost::format(_utf8(L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"))) % m_upload_job.printhost->get_host()).str());
|
m_print->set_status(100, (boost::format(_utf8(L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"))) % m_upload_job.printhost->get_host()).str());
|
||||||
|
@ -2564,9 +2564,9 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||||||
bool check_unsaved_preset_changes = page_welcome->reset_user_profile();
|
bool check_unsaved_preset_changes = page_welcome->reset_user_profile();
|
||||||
if (check_unsaved_preset_changes)
|
if (check_unsaved_preset_changes)
|
||||||
header = _L("All user presets will be deleted.");
|
header = _L("All user presets will be deleted.");
|
||||||
int act_btns = UnsavedChangesDialog::ActionButtons::KEEP;
|
int act_btns = ActionButtons::KEEP;
|
||||||
if (!check_unsaved_preset_changes)
|
if (!check_unsaved_preset_changes)
|
||||||
act_btns |= UnsavedChangesDialog::ActionButtons::SAVE;
|
act_btns |= ActionButtons::SAVE;
|
||||||
|
|
||||||
// Install bundles from resources if needed:
|
// Install bundles from resources if needed:
|
||||||
std::vector<std::string> install_bundles;
|
std::vector<std::string> install_bundles;
|
||||||
|
@ -3860,14 +3860,16 @@ void GCodeViewer::render_legend(float& legend_height)
|
|||||||
|
|
||||||
if (m_view_type == EViewType::Tool) {
|
if (m_view_type == EViewType::Tool) {
|
||||||
// calculate used filaments data
|
// calculate used filaments data
|
||||||
|
used_filaments_m = std::vector<double>(m_extruders_count, 0.0);
|
||||||
|
used_filaments_g = std::vector<double>(m_extruders_count, 0.0);
|
||||||
for (size_t extruder_id : m_extruder_ids) {
|
for (size_t extruder_id : m_extruder_ids) {
|
||||||
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end())
|
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end())
|
||||||
continue;
|
continue;
|
||||||
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
|
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
|
||||||
|
|
||||||
auto [used_filament_m, used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
|
auto [used_filament_m, used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
|
||||||
used_filaments_m.push_back(used_filament_m);
|
used_filaments_m[extruder_id] = used_filament_m;
|
||||||
used_filaments_g.push_back(used_filament_g);
|
used_filaments_g[extruder_id] = used_filament_g;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string longest_used_filament_string;
|
std::string longest_used_filament_string;
|
||||||
@ -4000,11 +4002,10 @@ void GCodeViewer::render_legend(float& legend_height)
|
|||||||
#endif // ENABLE_PREVIEW_LAYER_TIME
|
#endif // ENABLE_PREVIEW_LAYER_TIME
|
||||||
case EViewType::Tool: {
|
case EViewType::Tool: {
|
||||||
// shows only extruders actually used
|
// shows only extruders actually used
|
||||||
size_t i = 0;
|
|
||||||
for (unsigned char extruder_id : m_extruder_ids) {
|
for (unsigned char extruder_id : m_extruder_ids) {
|
||||||
append_item(EItemType::Rect, m_tool_colors[extruder_id], _u8L("Extruder") + " " + std::to_string(extruder_id + 1),
|
if (used_filaments_m[extruder_id] > 0.0 && used_filaments_g[extruder_id] > 0.0)
|
||||||
true, "", 0.0f, 0.0f, offsets, used_filaments_m[i], used_filaments_g[i]);
|
append_item(EItemType::Rect, m_tool_colors[extruder_id], _u8L("Extruder") + " " + std::to_string(extruder_id + 1),
|
||||||
++i;
|
true, "", 0.0f, 0.0f, offsets, used_filaments_m[extruder_id], used_filaments_g[extruder_id]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -834,14 +834,14 @@ void GLCanvas3D::Labels::render(const std::vector<const ModelInstance*>& sorted_
|
|||||||
imgui.begin(owner.title, ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
imgui.begin(owner.title, ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
|
||||||
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
|
ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
|
||||||
float win_w = ImGui::GetWindowWidth();
|
float win_w = ImGui::GetWindowWidth();
|
||||||
float label_len = imgui.calc_text_size(owner.label).x;
|
float label_len = ImGui::CalcTextSize(owner.label.c_str()).x;
|
||||||
ImGui::SetCursorPosX(0.5f * (win_w - label_len));
|
ImGui::SetCursorPosX(0.5f * (win_w - label_len));
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
imgui.text(owner.label);
|
imgui.text(owner.label);
|
||||||
|
|
||||||
if (!owner.print_order.empty()) {
|
if (!owner.print_order.empty()) {
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
float po_len = imgui.calc_text_size(owner.print_order).x;
|
float po_len = ImGui::CalcTextSize(owner.print_order.c_str()).x;
|
||||||
ImGui::SetCursorPosX(0.5f * (win_w - po_len));
|
ImGui::SetCursorPosX(0.5f * (win_w - po_len));
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
imgui.text(owner.print_order);
|
imgui.text(owner.print_order);
|
||||||
@ -4185,7 +4185,7 @@ void GLCanvas3D::handle_sidebar_focus_event(const std::string& opt_key, bool foc
|
|||||||
|
|
||||||
void GLCanvas3D::handle_layers_data_focus_event(const t_layer_height_range range, const EditorType type)
|
void GLCanvas3D::handle_layers_data_focus_event(const t_layer_height_range range, const EditorType type)
|
||||||
{
|
{
|
||||||
std::string field = "layer_" + std::to_string(type) + "_" + std::to_string(range.first) + "_" + std::to_string(range.second);
|
std::string field = "layer_" + std::to_string(type) + "_" + float_to_string_decimal_point(range.first) + "_" + float_to_string_decimal_point(range.second);
|
||||||
handle_sidebar_focus_event(field, true);
|
handle_sidebar_focus_event(field, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ namespace GUI {
|
|||||||
GLModel::Geometry init_data;
|
GLModel::Geometry init_data;
|
||||||
#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES
|
#if ENABLE_GL_CORE_PROFILE || ENABLE_OPENGL_ES
|
||||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P4 };
|
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P4 };
|
||||||
init_data.reserve_vertices(8);
|
init_data.reserve_vertices(5);
|
||||||
init_data.reserve_indices(8);
|
init_data.reserve_indices(8);
|
||||||
#else
|
#else
|
||||||
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2 };
|
init_data.format = { GLModel::Geometry::EPrimitiveType::LineLoop, GLModel::Geometry::EVertexLayout::P2 };
|
||||||
@ -187,25 +187,19 @@ namespace GUI {
|
|||||||
|
|
||||||
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
|
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
|
||||||
perimeter += width;
|
perimeter += width;
|
||||||
init_data.add_vertex(Vec4f(right, bottom, 0.0f, perimeter));
|
|
||||||
|
|
||||||
init_data.add_vertex(Vec4f(right, bottom, 0.0f, perimeter));
|
init_data.add_vertex(Vec4f(right, bottom, 0.0f, perimeter));
|
||||||
perimeter += height;
|
perimeter += height;
|
||||||
init_data.add_vertex(Vec4f(right, top, 0.0f, perimeter));
|
|
||||||
|
|
||||||
init_data.add_vertex(Vec4f(right, top, 0.0f, perimeter));
|
init_data.add_vertex(Vec4f(right, top, 0.0f, perimeter));
|
||||||
perimeter += width;
|
perimeter += width;
|
||||||
init_data.add_vertex(Vec4f(left, top, 0.0f, perimeter));
|
|
||||||
|
|
||||||
init_data.add_vertex(Vec4f(left, top, 0.0f, perimeter));
|
init_data.add_vertex(Vec4f(left, top, 0.0f, perimeter));
|
||||||
perimeter += height;
|
perimeter += height;
|
||||||
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
|
init_data.add_vertex(Vec4f(left, bottom, 0.0f, perimeter));
|
||||||
|
|
||||||
// indices
|
// indices
|
||||||
init_data.add_line(0, 1);
|
init_data.add_line(0, 1);
|
||||||
|
init_data.add_line(1, 2);
|
||||||
init_data.add_line(2, 3);
|
init_data.add_line(2, 3);
|
||||||
init_data.add_line(4, 5);
|
init_data.add_line(3, 4);
|
||||||
init_data.add_line(6, 7);
|
|
||||||
#else
|
#else
|
||||||
init_data.add_vertex(Vec2f(left, bottom));
|
init_data.add_vertex(Vec2f(left, bottom));
|
||||||
init_data.add_vertex(Vec2f(right, bottom));
|
init_data.add_vertex(Vec2f(right, bottom));
|
||||||
|
@ -2521,9 +2521,9 @@ bool GUI_App::check_and_save_current_preset_changes(const wxString& caption, con
|
|||||||
{
|
{
|
||||||
if (has_current_preset_changes()) {
|
if (has_current_preset_changes()) {
|
||||||
const std::string app_config_key = remember_choice ? "default_action_on_close_application" : "";
|
const std::string app_config_key = remember_choice ? "default_action_on_close_application" : "";
|
||||||
int act_buttons = UnsavedChangesDialog::ActionButtons::SAVE;
|
int act_buttons = ActionButtons::SAVE;
|
||||||
if (dont_save_insted_of_discard)
|
if (dont_save_insted_of_discard)
|
||||||
act_buttons |= UnsavedChangesDialog::ActionButtons::DONT_SAVE;
|
act_buttons |= ActionButtons::DONT_SAVE;
|
||||||
UnsavedChangesDialog dlg(caption, header, app_config_key, act_buttons);
|
UnsavedChangesDialog dlg(caption, header, app_config_key, act_buttons);
|
||||||
std::string act = app_config_key.empty() ? "none" : wxGetApp().app_config->get(app_config_key);
|
std::string act = app_config_key.empty() ? "none" : wxGetApp().app_config->get(app_config_key);
|
||||||
if (act == "none" && dlg.ShowModal() == wxID_CANCEL)
|
if (act == "none" && dlg.ShowModal() == wxID_CANCEL)
|
||||||
@ -2540,8 +2540,7 @@ bool GUI_App::check_and_save_current_preset_changes(const wxString& caption, con
|
|||||||
// synchronize config.ini with the current selections.
|
// synchronize config.ini with the current selections.
|
||||||
preset_bundle->export_selections(*app_config);
|
preset_bundle->export_selections(*app_config);
|
||||||
|
|
||||||
MessageDialog(nullptr, _L_PLURAL("The preset modifications are successfully saved",
|
MessageDialog(nullptr, dlg.msg_success_saved_modifications(dlg.get_names_and_types().size())).ShowModal();
|
||||||
"The presets modifications are successfully saved", dlg.get_names_and_types().size())).ShowModal();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2601,8 +2600,7 @@ bool GUI_App::check_and_keep_current_preset_changes(const wxString& caption, con
|
|||||||
// synchronize config.ini with the current selections.
|
// synchronize config.ini with the current selections.
|
||||||
preset_bundle->export_selections(*app_config);
|
preset_bundle->export_selections(*app_config);
|
||||||
|
|
||||||
wxString text = _L_PLURAL("The preset modifications are successfully saved",
|
wxString text = dlg.msg_success_saved_modifications(preset_names_and_types.size());
|
||||||
"The presets modifications are successfully saved", preset_names_and_types.size());
|
|
||||||
if (!is_called_from_configwizard)
|
if (!is_called_from_configwizard)
|
||||||
text += "\n\n" + _L("For new project all modifications will be reseted");
|
text += "\n\n" + _L("For new project all modifications will be reseted");
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||||
#include "slic3r/GUI/format.hpp"
|
#include "slic3r/GUI/format.hpp"
|
||||||
#include "slic3r/Utils/UndoRedo.hpp"
|
#include "slic3r/Utils/UndoRedo.hpp"
|
||||||
|
#include "libslic3r/Print.hpp"
|
||||||
|
#include "slic3r/GUI/MsgDialog.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
@ -39,6 +41,8 @@ bool GLGizmoFdmSupports::on_init()
|
|||||||
{
|
{
|
||||||
m_shortcut_key = WXK_CONTROL_L;
|
m_shortcut_key = WXK_CONTROL_L;
|
||||||
|
|
||||||
|
m_desc["auto_generate"] = _L("Auto-generate supports");
|
||||||
|
m_desc["generating"] = _L("Generating supports...");
|
||||||
m_desc["clipping_of_view"] = _L("Clipping of view") + ": ";
|
m_desc["clipping_of_view"] = _L("Clipping of view") + ": ";
|
||||||
m_desc["reset_direction"] = _L("Reset direction");
|
m_desc["reset_direction"] = _L("Reset direction");
|
||||||
m_desc["cursor_size"] = _L("Brush size") + ": ";
|
m_desc["cursor_size"] = _L("Brush size") + ": ";
|
||||||
@ -91,7 +95,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
|||||||
if (! m_c->selection_info()->model_object())
|
if (! m_c->selection_info()->model_object())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const float approx_height = m_imgui->scaled(23.f);
|
const float approx_height = m_imgui->scaled(25.f);
|
||||||
y = std::min(y, bottom_limit - approx_height);
|
y = std::min(y, bottom_limit - approx_height);
|
||||||
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
m_imgui->set_next_window_pos(x, y, ImGuiCond_Always);
|
||||||
|
|
||||||
@ -153,6 +157,15 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
|||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
|
if (waiting_for_autogenerated_supports) {
|
||||||
|
m_imgui->text(m_desc.at("generating"));
|
||||||
|
} else {
|
||||||
|
bool generate = m_imgui->button(m_desc.at("auto_generate"));
|
||||||
|
if (generate)
|
||||||
|
auto_generate();
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
float position_before_text_y = ImGui::GetCursorPos().y;
|
float position_before_text_y = ImGui::GetCursorPos().y;
|
||||||
ImGui::AlignTextToFramePadding();
|
ImGui::AlignTextToFramePadding();
|
||||||
m_imgui->text_wrapped(m_desc["highlight_by_angle"] + ":", autoset_slider_label_max_width);
|
m_imgui->text_wrapped(m_desc["highlight_by_angle"] + ":", autoset_slider_label_max_width);
|
||||||
@ -319,6 +332,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
|||||||
}
|
}
|
||||||
|
|
||||||
update_model_object();
|
update_model_object();
|
||||||
|
this->waiting_for_autogenerated_supports = false;
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,9 +380,54 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block)
|
|||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
||||||
: _L("Add supports by angle"));
|
: _L("Add supports by angle"));
|
||||||
update_model_object();
|
update_model_object();
|
||||||
|
this->waiting_for_autogenerated_supports = false;
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLGizmoFdmSupports::data_changed()
|
||||||
|
{
|
||||||
|
GLGizmoPainterBase::data_changed();
|
||||||
|
if (! m_c->selection_info())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
|
if (mo && this->waiting_for_autogenerated_supports) {
|
||||||
|
get_data_from_backend();
|
||||||
|
} else {
|
||||||
|
this->waiting_for_autogenerated_supports = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFdmSupports::get_data_from_backend()
|
||||||
|
{
|
||||||
|
if (! has_backend_supports())
|
||||||
|
return;
|
||||||
|
ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
|
|
||||||
|
// find the respective PrintObject, we need a pointer to it
|
||||||
|
for (const PrintObject* po : m_parent.fff_print()->objects()) {
|
||||||
|
if (po->model_object()->id() == mo->id()) {
|
||||||
|
std::unordered_map<size_t, const ModelVolume*> mvs;
|
||||||
|
for (const ModelVolume* mv : po->model_object()->volumes) {
|
||||||
|
if (mv->is_model_part()) {
|
||||||
|
mvs.emplace(mv->id().id, mv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int mesh_id = -1.0f;
|
||||||
|
for (ModelVolume* mv : mo->volumes){
|
||||||
|
if (mv->is_model_part()){
|
||||||
|
mesh_id++;
|
||||||
|
mv->supported_facets.assign(mvs[mv->id().id]->supported_facets);
|
||||||
|
m_triangle_selectors[mesh_id]->deserialize(mv->supported_facets.get_data(), true);
|
||||||
|
m_triangle_selectors[mesh_id]->request_update_render_data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->waiting_for_autogenerated_supports = false;
|
||||||
|
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||||
|
m_parent.set_as_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoFdmSupports::update_model_object() const
|
void GLGizmoFdmSupports::update_model_object() const
|
||||||
@ -391,8 +450,6 @@ void GLGizmoFdmSupports::update_model_object() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoFdmSupports::update_from_model_object()
|
void GLGizmoFdmSupports::update_from_model_object()
|
||||||
{
|
{
|
||||||
wxBusyCursor wait;
|
wxBusyCursor wait;
|
||||||
@ -417,6 +474,58 @@ void GLGizmoFdmSupports::update_from_model_object()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLGizmoFdmSupports::has_backend_supports() const
|
||||||
|
{
|
||||||
|
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
|
if (! mo)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// find PrintObject with this ID
|
||||||
|
for (const PrintObject* po : m_parent.fff_print()->objects()) {
|
||||||
|
if (po->model_object()->id() == mo->id())
|
||||||
|
return po->is_step_done(posSupportSpotsSearch);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFdmSupports::reslice_FDM_supports(bool postpone_error_messages) const {
|
||||||
|
wxGetApp().CallAfter(
|
||||||
|
[this, postpone_error_messages]() {
|
||||||
|
wxGetApp().plater()->reslice_FFF_until_step(posSupportSpotsSearch,
|
||||||
|
*m_c->selection_info()->model_object(), postpone_error_messages);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLGizmoFdmSupports::auto_generate()
|
||||||
|
{
|
||||||
|
ModelObject *mo = m_c->selection_info()->model_object();
|
||||||
|
bool not_painted = std::all_of(mo->volumes.begin(), mo->volumes.end(), [](const ModelVolume* vol){
|
||||||
|
return vol->type() != ModelVolumeType::MODEL_PART || vol->supported_facets.empty();
|
||||||
|
});
|
||||||
|
|
||||||
|
MessageDialog dlg(GUI::wxGetApp().plater(),
|
||||||
|
_L("Autogeneration will erase all currently painted areas.") + "\n\n" +
|
||||||
|
_L("Are you sure you want to do it?") + "\n",
|
||||||
|
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||||
|
|
||||||
|
if (not_painted || dlg.ShowModal() == wxID_YES) {
|
||||||
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Autogenerate support points"));
|
||||||
|
int mesh_id = -1.0f;
|
||||||
|
for (ModelVolume *mv : mo->volumes) {
|
||||||
|
if (mv->is_model_part()) {
|
||||||
|
mesh_id++;
|
||||||
|
mv->supported_facets.reset();
|
||||||
|
m_triangle_selectors[mesh_id]->reset();
|
||||||
|
m_triangle_selectors[mesh_id]->request_update_render_data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mo->config.set("support_material", true);
|
||||||
|
mo->config.set("support_material_auto", false);
|
||||||
|
this->waiting_for_autogenerated_supports = true;
|
||||||
|
wxGetApp().CallAfter([this]() { reslice_FDM_supports(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PainterGizmoType GLGizmoFdmSupports::get_painter_type() const
|
PainterGizmoType GLGizmoFdmSupports::get_painter_type() const
|
||||||
|
@ -26,6 +26,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool on_init() override;
|
bool on_init() override;
|
||||||
|
void data_changed() override;
|
||||||
|
|
||||||
void update_model_object() const override;
|
void update_model_object() const override;
|
||||||
void update_from_model_object() override;
|
void update_from_model_object() override;
|
||||||
@ -39,6 +40,13 @@ private:
|
|||||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
// 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.
|
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||||
std::map<std::string, wxString> m_desc;
|
std::map<std::string, wxString> m_desc;
|
||||||
|
|
||||||
|
|
||||||
|
bool waiting_for_autogenerated_supports = false;
|
||||||
|
bool has_backend_supports() const;
|
||||||
|
void reslice_FDM_supports(bool postpone_error_messages = false) const;
|
||||||
|
void auto_generate();
|
||||||
|
void get_data_from_backend();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -277,8 +277,51 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||||||
|
|
||||||
preferences_dialog = new PreferencesDialog(this);
|
preferences_dialog = new PreferencesDialog(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind events from DiffDlg
|
||||||
|
|
||||||
|
bind_diff_dialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainFrame::bind_diff_dialog()
|
||||||
|
{
|
||||||
|
auto get_tab = [](Preset::Type type) {
|
||||||
|
Tab* null_tab = nullptr;
|
||||||
|
for (Tab* tab : wxGetApp().tabs_list)
|
||||||
|
if (tab->type() == type)
|
||||||
|
return tab;
|
||||||
|
return null_tab;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto transfer = [this, get_tab](Preset::Type type) {
|
||||||
|
get_tab(type)->transfer_options(diff_dialog.get_left_preset_name(type),
|
||||||
|
diff_dialog.get_right_preset_name(type),
|
||||||
|
diff_dialog.get_selected_options(type));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto update_presets = [this, get_tab](Preset::Type type) {
|
||||||
|
get_tab(type)->update_preset_choice();
|
||||||
|
m_plater->sidebar().update_presets(type);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto process_options = [this](std::function<void(Preset::Type)> process) {
|
||||||
|
const Preset::Type diff_dlg_type = diff_dialog.view_type();
|
||||||
|
if (diff_dlg_type == Preset::TYPE_INVALID) {
|
||||||
|
for (const Preset::Type& type : diff_dialog.printer_technology() == ptFFF ?
|
||||||
|
std::initializer_list<Preset::Type>{Preset::TYPE_PRINTER, Preset::TYPE_PRINT, Preset::TYPE_FILAMENT} :
|
||||||
|
std::initializer_list<Preset::Type>{ Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL } )
|
||||||
|
process(type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
process(diff_dlg_type);
|
||||||
|
};
|
||||||
|
|
||||||
|
diff_dialog.Bind(EVT_DIFF_DIALOG_TRANSFER, [this, process_options, transfer](SimpleEvent&) { process_options(transfer); });
|
||||||
|
|
||||||
|
diff_dialog.Bind(EVT_DIFF_DIALOG_UPDATE_PRESETS,[this, process_options, update_presets](SimpleEvent&) { process_options(update_presets); });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MSW_DARK_MODE
|
#ifdef _MSW_DARK_MODE
|
||||||
static wxString pref() { return " [ "; }
|
static wxString pref() { return " [ "; }
|
||||||
static wxString suff() { return " ] "; }
|
static wxString suff() { return " ] "; }
|
||||||
@ -2130,9 +2173,6 @@ void MainFrame::add_to_recent_projects(const wxString& filename)
|
|||||||
|
|
||||||
void MainFrame::technology_changed()
|
void MainFrame::technology_changed()
|
||||||
{
|
{
|
||||||
// upadte DiffDlg
|
|
||||||
diff_dialog.update_presets();
|
|
||||||
|
|
||||||
// update menu titles
|
// update menu titles
|
||||||
PrinterTechnology pt = plater()->printer_technology();
|
PrinterTechnology pt = plater()->printer_technology();
|
||||||
if (int id = m_menubar->FindMenu(pt == ptFFF ? _L("Material Settings") : _L("Filament Settings")); id != wxNOT_FOUND)
|
if (int id = m_menubar->FindMenu(pt == ptFFF ? _L("Material Settings") : _L("Filament Settings")); id != wxNOT_FOUND)
|
||||||
|
@ -107,6 +107,7 @@ class MainFrame : public DPIFrame
|
|||||||
bool can_delete() const;
|
bool can_delete() const;
|
||||||
bool can_delete_all() const;
|
bool can_delete_all() const;
|
||||||
bool can_reslice() const;
|
bool can_reslice() const;
|
||||||
|
void bind_diff_dialog();
|
||||||
|
|
||||||
// MenuBar items changeable in respect to printer technology
|
// MenuBar items changeable in respect to printer technology
|
||||||
enum MenuItems
|
enum MenuItems
|
||||||
|
@ -1609,7 +1609,8 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi
|
|||||||
|
|
||||||
m_mainframe.Raise();
|
m_mainframe.Raise();
|
||||||
m_mainframe.select_tab(size_t(0));
|
m_mainframe.select_tab(size_t(0));
|
||||||
m_plater.select_view_3D("3D");
|
if (wxGetApp().is_editor())
|
||||||
|
m_plater.select_view_3D("3D");
|
||||||
bool res = m_plater.load_files(filenames);
|
bool res = m_plater.load_files(filenames);
|
||||||
m_mainframe.update_title();
|
m_mainframe.update_title();
|
||||||
return res;
|
return res;
|
||||||
@ -5347,10 +5348,9 @@ void Plater::new_project()
|
|||||||
(saved_project == wxID_YES ? _L("You can keep presets modifications to the new project or discard them") :
|
(saved_project == wxID_YES ? _L("You can keep presets modifications to the new project or discard them") :
|
||||||
_L("You can keep presets modifications to the new project, discard them or save changes as new presets.\n"
|
_L("You can keep presets modifications to the new project, discard them or save changes as new presets.\n"
|
||||||
"Note, if changes will be saved then new project wouldn't keep them"));
|
"Note, if changes will be saved then new project wouldn't keep them"));
|
||||||
using ab = UnsavedChangesDialog::ActionButtons;
|
int act_buttons = ActionButtons::KEEP;
|
||||||
int act_buttons = ab::KEEP;
|
|
||||||
if (saved_project == wxID_NO)
|
if (saved_project == wxID_NO)
|
||||||
act_buttons |= ab::SAVE;
|
act_buttons |= ActionButtons::SAVE;
|
||||||
if (!wxGetApp().check_and_keep_current_preset_changes(_L("Creating a new project"), header, act_buttons))
|
if (!wxGetApp().check_and_keep_current_preset_changes(_L("Creating a new project"), header, act_buttons))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@
|
|||||||
#include "../Utils/UndoRedo.hpp"
|
#include "../Utils/UndoRedo.hpp"
|
||||||
#include "BitmapCache.hpp"
|
#include "BitmapCache.hpp"
|
||||||
#include "PhysicalPrinterDialog.hpp"
|
#include "PhysicalPrinterDialog.hpp"
|
||||||
#include "SavePresetDialog.hpp"
|
|
||||||
#include "MsgDialog.hpp"
|
#include "MsgDialog.hpp"
|
||||||
|
|
||||||
// A workaround for a set of issues related to text fitting into gtk widgets:
|
// A workaround for a set of issues related to text fitting into gtk widgets:
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/stattext.h>
|
#include <wx/stattext.h>
|
||||||
#include <wx/textctrl.h>
|
#include <wx/textctrl.h>
|
||||||
#include <wx/wupdlock.h>
|
|
||||||
|
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
|
|
||||||
@ -22,25 +21,23 @@ using Slic3r::GUI::format_wxstr;
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
#define BORDER_W 10
|
constexpr auto BORDER_W = 10;
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
// SavePresetDialog::Item
|
// SavePresetDialog::Item
|
||||||
//-----------------------------------------------
|
//-----------------------------------------------
|
||||||
|
|
||||||
SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent):
|
std::string SavePresetDialog::Item::get_init_preset_name(const std::string &suffix)
|
||||||
m_type(type),
|
|
||||||
m_parent(parent)
|
|
||||||
{
|
{
|
||||||
Tab* tab = wxGetApp().get_tab(m_type);
|
PresetBundle* preset_bundle = m_parent->get_preset_bundle();
|
||||||
assert(tab);
|
if (!preset_bundle)
|
||||||
m_presets = tab->get_presets();
|
preset_bundle = wxGetApp().preset_bundle;
|
||||||
|
m_presets = &preset_bundle->get_presets(m_type);
|
||||||
|
|
||||||
const Preset& sel_preset = m_presets->get_selected_preset();
|
const Preset& sel_preset = m_presets->get_selected_preset();
|
||||||
std::string preset_name = sel_preset.is_default ? "Untitled" :
|
std::string preset_name = sel_preset.is_default ? "Untitled" :
|
||||||
sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() :
|
sel_preset.is_system ? (boost::format(("%1% - %2%")) % sel_preset.name % suffix).str() :
|
||||||
sel_preset.name;
|
sel_preset.name;
|
||||||
|
|
||||||
// if name contains extension
|
// if name contains extension
|
||||||
if (boost::iends_with(preset_name, ".ini")) {
|
if (boost::iends_with(preset_name, ".ini")) {
|
||||||
@ -48,18 +45,11 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBox
|
|||||||
preset_name.resize(len);
|
preset_name.resize(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> values;
|
return preset_name;
|
||||||
for (const Preset& preset : *m_presets) {
|
}
|
||||||
if (preset.is_default || preset.is_system || preset.is_external)
|
|
||||||
continue;
|
|
||||||
values.push_back(preset.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string label_str = m_parent->is_for_rename() ?_utf8(L("Rename %s to:")) : _utf8(L("Save %s as:"));
|
|
||||||
wxStaticText* label_top = new wxStaticText(m_parent, wxID_ANY, from_u8((boost::format(label_str) % into_u8(tab->title())).str()));
|
|
||||||
|
|
||||||
m_valid_bmp = new wxStaticBitmap(m_parent, wxID_ANY, *get_bmp_bundle("tick_mark"));
|
|
||||||
|
|
||||||
|
void SavePresetDialog::Item::init_input_name_ctrl(wxBoxSizer *input_name_sizer, const std::string preset_name)
|
||||||
|
{
|
||||||
if (m_parent->is_for_rename()) {
|
if (m_parent->is_for_rename()) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
long style = wxBORDER_SIMPLE;
|
long style = wxBORDER_SIMPLE;
|
||||||
@ -68,10 +58,19 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBox
|
|||||||
#endif
|
#endif
|
||||||
m_text_ctrl = new wxTextCtrl(m_parent, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxSize(35 * wxGetApp().em_unit(), -1), style);
|
m_text_ctrl = new wxTextCtrl(m_parent, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxSize(35 * wxGetApp().em_unit(), -1), style);
|
||||||
m_text_ctrl->Bind(wxEVT_TEXT, [this](wxCommandEvent&) { update(); });
|
m_text_ctrl->Bind(wxEVT_TEXT, [this](wxCommandEvent&) { update(); });
|
||||||
|
|
||||||
|
input_name_sizer->Add(m_text_ctrl,1, wxEXPAND, BORDER_W);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
std::vector<std::string> values;
|
||||||
|
for (const Preset&preset : *m_presets) {
|
||||||
|
if (preset.is_default || preset.is_system || preset.is_external)
|
||||||
|
continue;
|
||||||
|
values.push_back(preset.name);
|
||||||
|
}
|
||||||
|
|
||||||
m_combo = new wxComboBox(m_parent, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxSize(35 * wxGetApp().em_unit(), -1));
|
m_combo = new wxComboBox(m_parent, wxID_ANY, from_u8(preset_name), wxDefaultPosition, wxSize(35 * wxGetApp().em_unit(), -1));
|
||||||
for (const std::string& value : values)
|
for (const std::string&value : values)
|
||||||
m_combo->Append(from_u8(value));
|
m_combo->Append(from_u8(value));
|
||||||
|
|
||||||
m_combo->Bind(wxEVT_TEXT, [this](wxCommandEvent&) { update(); });
|
m_combo->Bind(wxEVT_TEXT, [this](wxCommandEvent&) { update(); });
|
||||||
@ -80,20 +79,34 @@ SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBox
|
|||||||
// So process wxEVT_COMBOBOX too
|
// So process wxEVT_COMBOBOX too
|
||||||
m_combo->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) { update(); });
|
m_combo->Bind(wxEVT_COMBOBOX, [this](wxCommandEvent&) { update(); });
|
||||||
#endif //__WXOSX__
|
#endif //__WXOSX__
|
||||||
}
|
|
||||||
|
|
||||||
m_valid_label = new wxStaticText(m_parent, wxID_ANY, "");
|
input_name_sizer->Add(m_combo, 1, wxEXPAND, BORDER_W);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString SavePresetDialog::Item::get_top_label_text() const
|
||||||
|
{
|
||||||
|
const std::string label_str = m_parent->is_for_rename() ?_u8L("Rename %s to:") : _u8L("Save %s as:");
|
||||||
|
Tab* tab = wxGetApp().get_tab(m_type);
|
||||||
|
return from_u8((boost::format(label_str) % into_u8(tab->title())).str());
|
||||||
|
}
|
||||||
|
|
||||||
|
SavePresetDialog::Item::Item(Preset::Type type, const std::string& suffix, wxBoxSizer* sizer, SavePresetDialog* parent):
|
||||||
|
m_type(type),
|
||||||
|
m_parent(parent),
|
||||||
|
m_valid_bmp(new wxStaticBitmap(m_parent, wxID_ANY, *get_bmp_bundle("tick_mark"))),
|
||||||
|
m_valid_label(new wxStaticText(m_parent, wxID_ANY, ""))
|
||||||
|
{
|
||||||
m_valid_label->SetFont(wxGetApp().bold_font());
|
m_valid_label->SetFont(wxGetApp().bold_font());
|
||||||
|
|
||||||
wxBoxSizer* combo_sizer = new wxBoxSizer(wxHORIZONTAL);
|
wxStaticText* label_top = new wxStaticText(m_parent, wxID_ANY, get_top_label_text());
|
||||||
combo_sizer->Add(m_valid_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W);
|
|
||||||
if (m_parent->is_for_rename())
|
wxBoxSizer* input_name_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
combo_sizer->Add(m_text_ctrl,1, wxEXPAND, BORDER_W);
|
input_name_sizer->Add(m_valid_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W);
|
||||||
else
|
init_input_name_ctrl(input_name_sizer, get_init_preset_name(suffix));
|
||||||
combo_sizer->Add(m_combo, 1, wxEXPAND, BORDER_W);
|
|
||||||
|
|
||||||
sizer->Add(label_top, 0, wxEXPAND | wxTOP| wxBOTTOM, BORDER_W);
|
sizer->Add(label_top, 0, wxEXPAND | wxTOP| wxBOTTOM, BORDER_W);
|
||||||
sizer->Add(combo_sizer, 0, wxEXPAND | wxBOTTOM, BORDER_W);
|
sizer->Add(input_name_sizer,0, wxEXPAND | wxBOTTOM, BORDER_W);
|
||||||
sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT, 3*BORDER_W);
|
sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT, 3*BORDER_W);
|
||||||
|
|
||||||
if (m_type == Preset::TYPE_PRINTER)
|
if (m_type == Preset::TYPE_PRINTER)
|
||||||
@ -107,7 +120,7 @@ void SavePresetDialog::Item::update()
|
|||||||
bool rename = m_parent->is_for_rename();
|
bool rename = m_parent->is_for_rename();
|
||||||
m_preset_name = into_u8(rename ? m_text_ctrl->GetValue() : m_combo->GetValue());
|
m_preset_name = into_u8(rename ? m_text_ctrl->GetValue() : m_combo->GetValue());
|
||||||
|
|
||||||
m_valid_type = Valid;
|
m_valid_type = ValidationType::Valid;
|
||||||
wxString info_line;
|
wxString info_line;
|
||||||
|
|
||||||
const char* unusable_symbols = "<>[]:/\\|?*\"";
|
const char* unusable_symbols = "<>[]:/\\|?*\"";
|
||||||
@ -117,44 +130,45 @@ void SavePresetDialog::Item::update()
|
|||||||
if (m_preset_name.find_first_of(unusable_symbols[i]) != std::string::npos) {
|
if (m_preset_name.find_first_of(unusable_symbols[i]) != std::string::npos) {
|
||||||
info_line = _L("The supplied name is not valid;") + "\n" +
|
info_line = _L("The supplied name is not valid;") + "\n" +
|
||||||
_L("the following characters are not allowed:") + " " + unusable_symbols;
|
_L("the following characters are not allowed:") + " " + unusable_symbols;
|
||||||
m_valid_type = NoValid;
|
m_valid_type = ValidationType::NoValid;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_valid_type == Valid && m_preset_name.find(unusable_suffix) != std::string::npos) {
|
if (m_valid_type == ValidationType::Valid && m_preset_name.find(unusable_suffix) != std::string::npos) {
|
||||||
info_line = _L("The supplied name is not valid;") + "\n" +
|
info_line = _L("The supplied name is not valid;") + "\n" +
|
||||||
_L("the following suffix is not allowed:") + "\n\t" +
|
_L("the following suffix is not allowed:") + "\n\t" +
|
||||||
from_u8(PresetCollection::get_suffix_modified());
|
from_u8(PresetCollection::get_suffix_modified());
|
||||||
m_valid_type = NoValid;
|
m_valid_type = ValidationType::NoValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_valid_type == Valid && m_preset_name == "- default -") {
|
if (m_valid_type == ValidationType::Valid && m_preset_name == "- default -") {
|
||||||
info_line = _L("The supplied name is not available.");
|
info_line = _L("The supplied name is not available.");
|
||||||
m_valid_type = NoValid;
|
m_valid_type = ValidationType::NoValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Preset* existing = m_presets->find_preset(m_preset_name, false);
|
const Preset* existing = m_presets->find_preset(m_preset_name, false);
|
||||||
if (m_valid_type == Valid && existing && (existing->is_default || existing->is_system)) {
|
if (m_valid_type == ValidationType::Valid && existing && (existing->is_default || existing->is_system)) {
|
||||||
info_line = rename ? _L("The supplied name is used for a system profile.") :
|
info_line = rename ? _L("The supplied name is used for a system profile.") :
|
||||||
_L("Cannot overwrite a system profile.");
|
_L("Cannot overwrite a system profile.");
|
||||||
m_valid_type = NoValid;
|
m_valid_type = ValidationType::NoValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_valid_type == Valid && existing && (existing->is_external)) {
|
if (m_valid_type == ValidationType::Valid && existing && (existing->is_external)) {
|
||||||
info_line = rename ? _L("The supplied name is used for a external profile.") :
|
info_line = rename ? _L("The supplied name is used for a external profile.") :
|
||||||
_L("Cannot overwrite an external profile.");
|
_L("Cannot overwrite an external profile.");
|
||||||
m_valid_type = NoValid;
|
m_valid_type = ValidationType::NoValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_valid_type == Valid && existing)
|
if (m_valid_type == ValidationType::Valid && existing)
|
||||||
{
|
{
|
||||||
if (m_preset_name == m_presets->get_selected_preset_name()) {
|
if (m_preset_name == m_presets->get_selected_preset_name()) {
|
||||||
if (!rename && m_presets->get_edited_preset().is_dirty)
|
if (!rename && m_presets->get_edited_preset().is_dirty ||
|
||||||
info_line = _L("Just save preset modifications");
|
m_parent->get_preset_bundle()) // means that we save modifications from the DiffDialog
|
||||||
|
info_line = _L("Save preset modifications to existing user profile");
|
||||||
else
|
else
|
||||||
info_line = _L("Nothing changed");
|
info_line = _L("Nothing changed");
|
||||||
m_valid_type = Valid;
|
m_valid_type = ValidationType::Valid;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (existing->is_compatible)
|
if (existing->is_compatible)
|
||||||
@ -162,31 +176,31 @@ void SavePresetDialog::Item::update()
|
|||||||
else
|
else
|
||||||
info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists and is incompatible with selected printer.")) % m_preset_name).str());
|
info_line = from_u8((boost::format(_u8L("Preset with name \"%1%\" already exists and is incompatible with selected printer.")) % m_preset_name).str());
|
||||||
info_line += "\n" + _L("Note: This preset will be replaced after saving");
|
info_line += "\n" + _L("Note: This preset will be replaced after saving");
|
||||||
m_valid_type = Warning;
|
m_valid_type = ValidationType::Warning;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_valid_type == Valid && m_preset_name.empty()) {
|
if (m_valid_type == ValidationType::Valid && m_preset_name.empty()) {
|
||||||
info_line = _L("The name cannot be empty.");
|
info_line = _L("The name cannot be empty.");
|
||||||
m_valid_type = NoValid;
|
m_valid_type = ValidationType::NoValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_valid_type == Valid && m_preset_name.find_first_of(' ') == 0) {
|
if (m_valid_type == ValidationType::Valid && m_preset_name.find_first_of(' ') == 0) {
|
||||||
info_line = _L("The name cannot start with space character.");
|
info_line = _L("The name cannot start with space character.");
|
||||||
m_valid_type = NoValid;
|
m_valid_type = ValidationType::NoValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_valid_type == Valid && m_preset_name.find_last_of(' ') == m_preset_name.length()-1) {
|
if (m_valid_type == ValidationType::Valid && m_preset_name.find_last_of(' ') == m_preset_name.length()-1) {
|
||||||
info_line = _L("The name cannot end with space character.");
|
info_line = _L("The name cannot end with space character.");
|
||||||
m_valid_type = NoValid;
|
m_valid_type = ValidationType::NoValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_valid_type == Valid && m_presets->get_preset_name_by_alias(m_preset_name) != m_preset_name) {
|
if (m_valid_type == ValidationType::Valid && m_presets->get_preset_name_by_alias(m_preset_name) != m_preset_name) {
|
||||||
info_line = _L("The name cannot be the same as a preset alias name.");
|
info_line = _L("The name cannot be the same as a preset alias name.");
|
||||||
m_valid_type = NoValid;
|
m_valid_type = ValidationType::NoValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_parent->get_info_line_extention().IsEmpty() && m_valid_type != NoValid)
|
if (!m_parent->get_info_line_extention().IsEmpty() && m_valid_type != ValidationType::NoValid)
|
||||||
info_line += "\n\n" + m_parent->get_info_line_extention();
|
info_line += "\n\n" + m_parent->get_info_line_extention();
|
||||||
|
|
||||||
m_valid_label->SetLabel(info_line);
|
m_valid_label->SetLabel(info_line);
|
||||||
@ -202,14 +216,14 @@ void SavePresetDialog::Item::update()
|
|||||||
|
|
||||||
void SavePresetDialog::Item::update_valid_bmp()
|
void SavePresetDialog::Item::update_valid_bmp()
|
||||||
{
|
{
|
||||||
std::string bmp_name = m_valid_type == Warning ? "exclamation" :
|
std::string bmp_name = m_valid_type == ValidationType::Warning ? "exclamation" :
|
||||||
m_valid_type == NoValid ? "cross" : "tick_mark" ;
|
m_valid_type == ValidationType::NoValid ? "cross" : "tick_mark" ;
|
||||||
m_valid_bmp->SetBitmap(*get_bmp_bundle(bmp_name));
|
m_valid_bmp->SetBitmap(*get_bmp_bundle(bmp_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SavePresetDialog::Item::accept()
|
void SavePresetDialog::Item::accept()
|
||||||
{
|
{
|
||||||
if (m_valid_type == Warning)
|
if (m_valid_type == ValidationType::Warning)
|
||||||
m_presets->delete_preset(m_preset_name);
|
m_presets->delete_preset(m_preset_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,8 +238,9 @@ SavePresetDialog::SavePresetDialog(wxWindow* parent, Preset::Type type, std::str
|
|||||||
build(std::vector<Preset::Type>{type}, suffix);
|
build(std::vector<Preset::Type>{type}, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
SavePresetDialog::SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix)
|
SavePresetDialog::SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix, PresetBundle* preset_bundle/* = nullptr*/)
|
||||||
: DPIDialog(parent, wxID_ANY, _L("Save presets"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER)
|
: DPIDialog(parent, wxID_ANY, _L("Save presets"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING | wxRESIZE_BORDER),
|
||||||
|
m_preset_bundle(preset_bundle)
|
||||||
{
|
{
|
||||||
build(types, suffix);
|
build(types, suffix);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ class SavePresetDialog : public DPIDialog
|
|||||||
|
|
||||||
struct Item
|
struct Item
|
||||||
{
|
{
|
||||||
enum ValidationType
|
enum class ValidationType
|
||||||
{
|
{
|
||||||
Valid,
|
Valid,
|
||||||
NoValid,
|
NoValid,
|
||||||
@ -41,15 +41,15 @@ class SavePresetDialog : public DPIDialog
|
|||||||
void update_valid_bmp();
|
void update_valid_bmp();
|
||||||
void accept();
|
void accept();
|
||||||
|
|
||||||
bool is_valid() const { return m_valid_type != NoValid; }
|
bool is_valid() const { return m_valid_type != ValidationType::NoValid; }
|
||||||
Preset::Type type() const { return m_type; }
|
Preset::Type type() const { return m_type; }
|
||||||
std::string preset_name() const { return m_preset_name; }
|
std::string preset_name() const { return m_preset_name; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Preset::Type m_type;
|
Preset::Type m_type;
|
||||||
ValidationType m_valid_type;
|
|
||||||
std::string m_preset_name;
|
std::string m_preset_name;
|
||||||
|
|
||||||
|
ValidationType m_valid_type {ValidationType::NoValid};
|
||||||
SavePresetDialog* m_parent {nullptr};
|
SavePresetDialog* m_parent {nullptr};
|
||||||
wxStaticBitmap* m_valid_bmp {nullptr};
|
wxStaticBitmap* m_valid_bmp {nullptr};
|
||||||
wxComboBox* m_combo {nullptr};
|
wxComboBox* m_combo {nullptr};
|
||||||
@ -58,7 +58,11 @@ class SavePresetDialog : public DPIDialog
|
|||||||
|
|
||||||
PresetCollection* m_presets {nullptr};
|
PresetCollection* m_presets {nullptr};
|
||||||
|
|
||||||
void update();
|
std::string get_init_preset_name(const std::string &suffix);
|
||||||
|
void init_input_name_ctrl(wxBoxSizer *input_name_sizer, std::string preset_name);
|
||||||
|
wxString get_top_label_text() const ;
|
||||||
|
|
||||||
|
void update();
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Item*> m_items;
|
std::vector<Item*> m_items;
|
||||||
@ -73,19 +77,22 @@ class SavePresetDialog : public DPIDialog
|
|||||||
bool m_use_for_rename{false};
|
bool m_use_for_rename{false};
|
||||||
wxString m_info_line_extention{wxEmptyString};
|
wxString m_info_line_extention{wxEmptyString};
|
||||||
|
|
||||||
|
PresetBundle* m_preset_bundle{ nullptr };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
const wxString& get_info_line_extention() { return m_info_line_extention; }
|
const wxString& get_info_line_extention() { return m_info_line_extention; }
|
||||||
|
|
||||||
SavePresetDialog(wxWindow* parent, Preset::Type type, std::string suffix = "");
|
SavePresetDialog(wxWindow* parent, Preset::Type type, std::string suffix = "");
|
||||||
SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix = "");
|
SavePresetDialog(wxWindow* parent, std::vector<Preset::Type> types, std::string suffix = "", PresetBundle* preset_bundle = nullptr);
|
||||||
SavePresetDialog(wxWindow* parent, Preset::Type type, bool rename, const wxString& info_line_extention);
|
SavePresetDialog(wxWindow* parent, Preset::Type type, bool rename, const wxString& info_line_extention);
|
||||||
~SavePresetDialog();
|
~SavePresetDialog() override;
|
||||||
|
|
||||||
void AddItem(Preset::Type type, const std::string& suffix);
|
void AddItem(Preset::Type type, const std::string& suffix);
|
||||||
|
|
||||||
std::string get_name();
|
PresetBundle* get_preset_bundle() const { return m_preset_bundle; }
|
||||||
std::string get_name(Preset::Type type);
|
std::string get_name();
|
||||||
|
std::string get_name(Preset::Type type);
|
||||||
|
|
||||||
bool enable_ok_btn() const;
|
bool enable_ok_btn() const;
|
||||||
void add_info_for_edit_ph_printer(wxBoxSizer *sizer);
|
void add_info_for_edit_ph_printer(wxBoxSizer *sizer);
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/exception/diagnostic_information.hpp>
|
||||||
|
|
||||||
#include "wxExtensions.hpp"
|
#include "wxExtensions.hpp"
|
||||||
#include "PresetComboBoxes.hpp"
|
#include "PresetComboBoxes.hpp"
|
||||||
#include <wx/wupdlock.h>
|
#include <wx/wupdlock.h>
|
||||||
@ -39,21 +41,20 @@
|
|||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include "format.hpp"
|
#include "format.hpp"
|
||||||
#include "PhysicalPrinterDialog.hpp"
|
|
||||||
#include "UnsavedChangesDialog.hpp"
|
#include "UnsavedChangesDialog.hpp"
|
||||||
#include "SavePresetDialog.hpp"
|
#include "SavePresetDialog.hpp"
|
||||||
#include "MsgDialog.hpp"
|
#include "MsgDialog.hpp"
|
||||||
#include "Notebook.hpp"
|
#include "Notebook.hpp"
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <commctrl.h>
|
#include <CommCtrl.h>
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
Tab::Tab(wxBookCtrlBase* parent, const wxString& title, Preset::Type type) :
|
Tab::Tab(wxBookCtrlBase* parent, const wxString& title, Preset::Type type) :
|
||||||
m_parent(parent), m_title(title), m_type(type)
|
m_parent(parent), m_type(type), m_title(title)
|
||||||
{
|
{
|
||||||
Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL/*, name*/);
|
Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL/*, name*/);
|
||||||
this->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
this->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||||
@ -1183,9 +1184,9 @@ void Tab::activate_option(const std::string& opt_key, const wxString& category)
|
|||||||
m_highlighter.init(get_custom_ctrl_with_blinking_ptr(opt_key));
|
m_highlighter.init(get_custom_ctrl_with_blinking_ptr(opt_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tab::cache_config_diff(const std::vector<std::string>& selected_options)
|
void Tab::cache_config_diff(const std::vector<std::string>& selected_options, const DynamicPrintConfig* config/* = nullptr*/)
|
||||||
{
|
{
|
||||||
m_cache_config.apply_only(m_presets->get_edited_preset().config, selected_options);
|
m_cache_config.apply_only(config ? *config : m_presets->get_edited_preset().config, selected_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tab::apply_config_from_cache()
|
void Tab::apply_config_from_cache()
|
||||||
@ -3185,7 +3186,8 @@ void Tab::update_btns_enabling()
|
|||||||
const Preset& preset = m_presets->get_edited_preset();
|
const Preset& preset = m_presets->get_edited_preset();
|
||||||
m_btn_delete_preset->Show((m_type == Preset::TYPE_PRINTER && m_preset_bundle->physical_printers.has_selection())
|
m_btn_delete_preset->Show((m_type == Preset::TYPE_PRINTER && m_preset_bundle->physical_printers.has_selection())
|
||||||
|| (!preset.is_default && !preset.is_system));
|
|| (!preset.is_default && !preset.is_system));
|
||||||
m_btn_rename_preset->Show(!preset.is_default && !preset.is_system && !m_presets_choice->is_selected_physical_printer());
|
m_btn_rename_preset->Show(!preset.is_default && !preset.is_system && !preset.is_external &&
|
||||||
|
!wxGetApp().preset_bundle->physical_printers.has_selection());
|
||||||
|
|
||||||
if (m_btn_edit_ph_printer)
|
if (m_btn_edit_ph_printer)
|
||||||
m_btn_edit_ph_printer->SetToolTip( m_preset_bundle->physical_printers.has_selection() ?
|
m_btn_edit_ph_printer->SetToolTip( m_preset_bundle->physical_printers.has_selection() ?
|
||||||
@ -3583,6 +3585,32 @@ void Tab::compare_preset()
|
|||||||
wxGetApp().mainframe->diff_dialog.show(m_type);
|
wxGetApp().mainframe->diff_dialog.show(m_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tab::transfer_options(const std::string &name_from, const std::string &name_to, std::vector<std::string> options)
|
||||||
|
{
|
||||||
|
if (options.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Preset* preset_from = m_presets->find_preset(name_from);
|
||||||
|
Preset* preset_to = m_presets->find_preset(name_to);
|
||||||
|
|
||||||
|
if (m_type == Preset::TYPE_PRINTER) {
|
||||||
|
auto it = std::find(options.begin(), options.end(), "extruders_count");
|
||||||
|
if (it != options.end()) {
|
||||||
|
// erase "extruders_count" option from the list
|
||||||
|
options.erase(it);
|
||||||
|
// cache the extruders count
|
||||||
|
static_cast<TabPrinter*>(this)->cache_extruder_cnt(&preset_from->config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cache_config_diff(options, &preset_from->config);
|
||||||
|
|
||||||
|
if (name_to != m_presets->get_edited_preset().name )
|
||||||
|
select_preset(preset_to->name);
|
||||||
|
|
||||||
|
apply_config_from_cache();
|
||||||
|
load_current_preset();
|
||||||
|
}
|
||||||
|
|
||||||
// Save the current preset into file.
|
// Save the current preset into file.
|
||||||
// This removes the "dirty" flag of the preset, possibly creates a new preset under a new name,
|
// This removes the "dirty" flag of the preset, possibly creates a new preset under a new name,
|
||||||
// and activates the new preset.
|
// and activates the new preset.
|
||||||
@ -3674,12 +3702,11 @@ void Tab::rename_preset()
|
|||||||
if (m_presets_choice->is_selected_physical_printer())
|
if (m_presets_choice->is_selected_physical_printer())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Preset& selected_preset = m_presets->get_selected_preset();
|
|
||||||
wxString msg;
|
wxString msg;
|
||||||
|
|
||||||
if (m_type == Preset::TYPE_PRINTER && !m_preset_bundle->physical_printers.empty()) {
|
if (m_type == Preset::TYPE_PRINTER && !m_preset_bundle->physical_printers.empty()) {
|
||||||
// Check preset for rename in physical printers
|
// Check preset for rename in physical printers
|
||||||
std::vector<std::string> ph_printers = m_preset_bundle->physical_printers.get_printers_with_preset(selected_preset.name);
|
std::vector<std::string> ph_printers = m_preset_bundle->physical_printers.get_printers_with_preset(m_presets->get_selected_preset().name);
|
||||||
if (!ph_printers.empty()) {
|
if (!ph_printers.empty()) {
|
||||||
msg += _L_PLURAL("The physical printer below is based on the preset, you are going to rename.",
|
msg += _L_PLURAL("The physical printer below is based on the preset, you are going to rename.",
|
||||||
"The physical printers below are based on the preset, you are going to rename.", ph_printers.size());
|
"The physical printers below are based on the preset, you are going to rename.", ph_printers.size());
|
||||||
@ -3696,31 +3723,51 @@ void Tab::rename_preset()
|
|||||||
SavePresetDialog dlg(m_parent, m_type, true, msg);
|
SavePresetDialog dlg(m_parent, m_type, true, msg);
|
||||||
if (dlg.ShowModal() != wxID_OK)
|
if (dlg.ShowModal() != wxID_OK)
|
||||||
return;
|
return;
|
||||||
std::string new_name = into_u8(dlg.get_name());
|
|
||||||
|
|
||||||
|
const std::string new_name = into_u8(dlg.get_name());
|
||||||
if (new_name.empty() || new_name == m_presets->get_selected_preset().name)
|
if (new_name.empty() || new_name == m_presets->get_selected_preset().name)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// rename selected and edited presets
|
// Note: selected preset can be changed, if in SavePresetDialog was selected name of existing preset
|
||||||
|
Preset& selected_preset = m_presets->get_selected_preset();
|
||||||
|
Preset& edited_preset = m_presets->get_edited_preset();
|
||||||
|
|
||||||
std::string old_name = selected_preset.name;
|
const std::string old_name = selected_preset.name;
|
||||||
std::string old_file_name = selected_preset.file;
|
const std::string old_file_name = selected_preset.file;
|
||||||
|
|
||||||
selected_preset.name = new_name;
|
assert(old_name == edited_preset.name);
|
||||||
boost::replace_last(selected_preset.file, old_name, new_name);
|
|
||||||
|
|
||||||
Preset& edited_preset = m_presets->get_edited_preset();
|
using namespace boost;
|
||||||
edited_preset.name = new_name;
|
try {
|
||||||
boost::replace_last(edited_preset.file, old_name, new_name);
|
// rename selected and edited presets
|
||||||
|
|
||||||
// rename file with renamed preset configuration
|
selected_preset.name = new_name;
|
||||||
boost::filesystem::rename(old_file_name, selected_preset.file);
|
replace_last(selected_preset.file, old_name, new_name);
|
||||||
|
|
||||||
// rename selected preset in printers, if it's needed
|
edited_preset.name = new_name;
|
||||||
if (!msg.IsEmpty())
|
replace_last(edited_preset.file, old_name, new_name);
|
||||||
m_preset_bundle->physical_printers.rename_preset_in_printers(old_name, new_name);
|
|
||||||
|
// rename file with renamed preset configuration
|
||||||
|
|
||||||
|
filesystem::rename(old_file_name, selected_preset.file);
|
||||||
|
|
||||||
|
// rename selected preset in printers, if it's needed
|
||||||
|
|
||||||
|
if (!msg.IsEmpty())
|
||||||
|
m_preset_bundle->physical_printers.rename_preset_in_printers(old_name, new_name);
|
||||||
|
}
|
||||||
|
catch (const exception& ex) {
|
||||||
|
const std::string exception = diagnostic_information(ex);
|
||||||
|
printf("Can't rename a preset : %s", exception.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort presets after renaming
|
||||||
|
std::sort(m_presets->begin(), m_presets->end());
|
||||||
|
// update selection
|
||||||
|
m_presets->select_preset_by_name(new_name, true);
|
||||||
|
|
||||||
m_presets_choice->update();
|
m_presets_choice->update();
|
||||||
|
on_presets_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called for a currently selected preset.
|
// Called for a currently selected preset.
|
||||||
@ -4267,12 +4314,15 @@ wxSizer* TabPrinter::create_bed_shape_widget(wxWindow* parent)
|
|||||||
return sizer;
|
return sizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabPrinter::cache_extruder_cnt()
|
void TabPrinter::cache_extruder_cnt(const DynamicPrintConfig* config/* = nullptr*/)
|
||||||
{
|
{
|
||||||
if (m_presets->get_edited_preset().printer_technology() == ptSLA)
|
const DynamicPrintConfig& cached_config = config ? *config : m_presets->get_edited_preset().config;
|
||||||
|
if (Preset::printer_technology(cached_config) == ptSLA)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_cache_extruder_count = m_extruders_count;
|
// get extruders count
|
||||||
|
auto* nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(cached_config.option("nozzle_diameter"));
|
||||||
|
m_cache_extruder_count = nozzle_diameter->values.size(); //m_extruders_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TabPrinter::apply_extruder_cnt_from_cache()
|
bool TabPrinter::apply_extruder_cnt_from_cache()
|
||||||
@ -4282,6 +4332,7 @@ bool TabPrinter::apply_extruder_cnt_from_cache()
|
|||||||
|
|
||||||
if (m_cache_extruder_count > 0) {
|
if (m_cache_extruder_count > 0) {
|
||||||
m_presets->get_edited_preset().set_num_extruders(m_cache_extruder_count);
|
m_presets->get_edited_preset().set_num_extruders(m_cache_extruder_count);
|
||||||
|
// extruders_count_changed(m_cache_extruder_count);
|
||||||
m_cache_extruder_count = 0;
|
m_cache_extruder_count = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -322,6 +322,7 @@ public:
|
|||||||
void OnKeyDown(wxKeyEvent& event);
|
void OnKeyDown(wxKeyEvent& event);
|
||||||
|
|
||||||
void compare_preset();
|
void compare_preset();
|
||||||
|
void transfer_options(const std::string&name_from, const std::string&name_to, std::vector<std::string> options);
|
||||||
void save_preset(std::string name = std::string(), bool detach = false);
|
void save_preset(std::string name = std::string(), bool detach = false);
|
||||||
void rename_preset();
|
void rename_preset();
|
||||||
void delete_preset();
|
void delete_preset();
|
||||||
@ -374,7 +375,7 @@ public:
|
|||||||
|
|
||||||
void update_wiping_button_visibility();
|
void update_wiping_button_visibility();
|
||||||
void activate_option(const std::string& opt_key, const wxString& category);
|
void activate_option(const std::string& opt_key, const wxString& category);
|
||||||
void cache_config_diff(const std::vector<std::string>& selected_options);
|
void cache_config_diff(const std::vector<std::string>& selected_options, const DynamicPrintConfig* config = nullptr);
|
||||||
void apply_config_from_cache();
|
void apply_config_from_cache();
|
||||||
|
|
||||||
const std::map<wxString, std::string>& get_category_icon_map() { return m_category_icon; }
|
const std::map<wxString, std::string>& get_category_icon_map() { return m_category_icon; }
|
||||||
@ -503,7 +504,7 @@ public:
|
|||||||
bool supports_printer_technology(const PrinterTechnology /* tech */) const override { return true; }
|
bool supports_printer_technology(const PrinterTechnology /* tech */) const override { return true; }
|
||||||
|
|
||||||
wxSizer* create_bed_shape_widget(wxWindow* parent);
|
wxSizer* create_bed_shape_widget(wxWindow* parent);
|
||||||
void cache_extruder_cnt();
|
void cache_extruder_cnt(const DynamicPrintConfig* config = nullptr);
|
||||||
bool apply_extruder_cnt_from_cache();
|
bool apply_extruder_cnt_from_cache();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <boost/nowide/convert.hpp>
|
|
||||||
|
|
||||||
#include <wx/tokenzr.h>
|
#include <wx/tokenzr.h>
|
||||||
|
|
||||||
@ -22,10 +21,6 @@
|
|||||||
#include "MainFrame.hpp"
|
#include "MainFrame.hpp"
|
||||||
#include "MsgDialog.hpp"
|
#include "MsgDialog.hpp"
|
||||||
|
|
||||||
//#define FTS_FUZZY_MATCH_IMPLEMENTATION
|
|
||||||
//#include "fts_fuzzy_match.h"
|
|
||||||
|
|
||||||
#include "BitmapCache.hpp"
|
|
||||||
#include "PresetComboBoxes.hpp"
|
#include "PresetComboBoxes.hpp"
|
||||||
|
|
||||||
using boost::optional;
|
using boost::optional;
|
||||||
@ -40,6 +35,10 @@ namespace Slic3r {
|
|||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
|
wxDEFINE_EVENT(EVT_DIFF_DIALOG_TRANSFER, SimpleEvent);
|
||||||
|
wxDEFINE_EVENT(EVT_DIFF_DIALOG_UPDATE_PRESETS, SimpleEvent);
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// ModelNode: a node inside DiffModel
|
// ModelNode: a node inside DiffModel
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -104,8 +103,8 @@ ModelNode::ModelNode(ModelNode* parent, const wxString& text, const std::string&
|
|||||||
ModelNode::ModelNode(ModelNode* parent, const wxString& text) :
|
ModelNode::ModelNode(ModelNode* parent, const wxString& text) :
|
||||||
m_parent_win(parent->m_parent_win),
|
m_parent_win(parent->m_parent_win),
|
||||||
m_parent(parent),
|
m_parent(parent),
|
||||||
m_text(text),
|
m_icon_name("dot_small"),
|
||||||
m_icon_name("dot_small")
|
m_text(text)
|
||||||
{
|
{
|
||||||
UpdateIcons();
|
UpdateIcons();
|
||||||
}
|
}
|
||||||
@ -135,12 +134,12 @@ ModelNode::ModelNode(ModelNode* parent, const wxString& text, const wxString& ol
|
|||||||
m_old_color(old_value.StartsWith("#") ? old_value : ""),
|
m_old_color(old_value.StartsWith("#") ? old_value : ""),
|
||||||
m_mod_color(mod_value.StartsWith("#") ? mod_value : ""),
|
m_mod_color(mod_value.StartsWith("#") ? mod_value : ""),
|
||||||
m_new_color(new_value.StartsWith("#") ? new_value : ""),
|
m_new_color(new_value.StartsWith("#") ? new_value : ""),
|
||||||
m_container(false),
|
|
||||||
m_text(text),
|
|
||||||
m_icon_name("empty"),
|
m_icon_name("empty"),
|
||||||
|
m_text(text),
|
||||||
m_old_value(old_value),
|
m_old_value(old_value),
|
||||||
m_mod_value(mod_value),
|
m_mod_value(mod_value),
|
||||||
m_new_value(new_value)
|
m_new_value(new_value),
|
||||||
|
m_container(false)
|
||||||
{
|
{
|
||||||
// check if old/new_value is color
|
// check if old/new_value is color
|
||||||
if (m_old_color.IsEmpty()) {
|
if (m_old_color.IsEmpty()) {
|
||||||
@ -505,7 +504,7 @@ unsigned int DiffModel::GetChildren(const wxDataViewItem& parent, wxDataViewItem
|
|||||||
for (const std::unique_ptr<ModelNode>& child : children)
|
for (const std::unique_ptr<ModelNode>& child : children)
|
||||||
array.Add(wxDataViewItem((void*)child.get()));
|
array.Add(wxDataViewItem((void*)child.get()));
|
||||||
|
|
||||||
return array.size();
|
return array.Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -591,7 +590,7 @@ void DiffModel::Clear()
|
|||||||
|
|
||||||
static std::string get_pure_opt_key(std::string opt_key)
|
static std::string get_pure_opt_key(std::string opt_key)
|
||||||
{
|
{
|
||||||
int pos = opt_key.find("#");
|
const int pos = opt_key.find("#");
|
||||||
if (pos > 0)
|
if (pos > 0)
|
||||||
boost::erase_tail(opt_key, opt_key.size() - pos);
|
boost::erase_tail(opt_key, opt_key.size() - pos);
|
||||||
return opt_key;
|
return opt_key;
|
||||||
@ -1337,6 +1336,12 @@ void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* pres
|
|||||||
searcher.sort_options_by_label();
|
searcher.sort_options_by_label();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxString UnsavedChangesDialog::msg_success_saved_modifications(size_t saved_presets_cnt)
|
||||||
|
{
|
||||||
|
return _L_PLURAL("The preset modifications are successfully saved",
|
||||||
|
"The presets modifications are successfully saved", static_cast<unsigned int>(saved_presets_cnt));
|
||||||
|
}
|
||||||
|
|
||||||
void UnsavedChangesDialog::on_dpi_changed(const wxRect& suggested_rect)
|
void UnsavedChangesDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||||
{
|
{
|
||||||
int em = em_unit();
|
int em = em_unit();
|
||||||
@ -1380,7 +1385,7 @@ FullCompareDialog::FullCompareDialog(const wxString& option_name, const wxString
|
|||||||
|
|
||||||
wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(2, has_new_value_column ? 3 : 2, 1, 0);
|
wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(2, has_new_value_column ? 3 : 2, 1, 0);
|
||||||
grid_sizer->SetFlexibleDirection(wxBOTH);
|
grid_sizer->SetFlexibleDirection(wxBOTH);
|
||||||
for (size_t col = 0 ; col < grid_sizer->GetCols(); col++)
|
for (int col = 0 ; col < grid_sizer->GetCols(); col++)
|
||||||
grid_sizer->AddGrowableCol(col, 1);
|
grid_sizer->AddGrowableCol(col, 1);
|
||||||
grid_sizer->AddGrowableRow(1,1);
|
grid_sizer->AddGrowableRow(1,1);
|
||||||
|
|
||||||
@ -1472,34 +1477,11 @@ static std::string get_selection(PresetComboBox* preset_combo)
|
|||||||
return into_u8(preset_combo->GetString(preset_combo->GetSelection()));
|
return into_u8(preset_combo->GetString(preset_combo->GetSelection()));
|
||||||
}
|
}
|
||||||
|
|
||||||
DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe)
|
void DiffPresetDialog::create_presets_sizer()
|
||||||
: DPIDialog(mainframe, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
|
||||||
m_pr_technology(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology())
|
|
||||||
{
|
{
|
||||||
#if defined(__WXMSW__)
|
m_presets_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
// ys_FIXME! temporary workaround for correct font scaling
|
|
||||||
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
|
|
||||||
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
|
|
||||||
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
|
||||||
#endif // __WXMSW__
|
|
||||||
|
|
||||||
int border = 10;
|
for (auto new_type : { Preset::TYPE_PRINT, Preset::TYPE_SLA_PRINT, Preset::TYPE_FILAMENT, Preset::TYPE_SLA_MATERIAL, Preset::TYPE_PRINTER })
|
||||||
int em = em_unit();
|
|
||||||
|
|
||||||
assert(wxGetApp().preset_bundle);
|
|
||||||
|
|
||||||
m_preset_bundle_left = std::make_unique<PresetBundle>(*wxGetApp().preset_bundle);
|
|
||||||
m_preset_bundle_right = std::make_unique<PresetBundle>(*wxGetApp().preset_bundle);
|
|
||||||
|
|
||||||
m_top_info_line = new wxStaticText(this, wxID_ANY, _L("Select presets to compare"));
|
|
||||||
m_top_info_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold());
|
|
||||||
|
|
||||||
m_bottom_info_line = new wxStaticText(this, wxID_ANY, "");
|
|
||||||
m_bottom_info_line->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold());
|
|
||||||
|
|
||||||
wxBoxSizer* presets_sizer = new wxBoxSizer(wxVERTICAL);
|
|
||||||
|
|
||||||
for (auto new_type : { Preset::TYPE_PRINT, Preset::TYPE_FILAMENT, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL, Preset::TYPE_PRINTER })
|
|
||||||
{
|
{
|
||||||
const PresetCollection* collection = get_preset_collection(new_type);
|
const PresetCollection* collection = get_preset_collection(new_type);
|
||||||
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
@ -1507,15 +1489,16 @@ DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe)
|
|||||||
PresetComboBox* presets_right;
|
PresetComboBox* presets_right;
|
||||||
ScalableButton* equal_bmp = new ScalableButton(this, wxID_ANY, "equal");
|
ScalableButton* equal_bmp = new ScalableButton(this, wxID_ANY, "equal");
|
||||||
|
|
||||||
auto add_preset_combobox = [collection, sizer, new_type, em, this](PresetComboBox** cb_, PresetBundle* preset_bundle) {
|
auto add_preset_combobox = [collection, sizer, new_type, this](PresetComboBox** cb_, PresetBundle* preset_bundle) {
|
||||||
*cb_ = new PresetComboBox(this, new_type, wxSize(em * 35, -1), preset_bundle);
|
*cb_ = new PresetComboBox(this, new_type, wxSize(em_unit() * 35, -1), preset_bundle);
|
||||||
PresetComboBox* cb = (*cb_);
|
PresetComboBox*cb = (*cb_);
|
||||||
cb->show_modif_preset_separately();
|
cb->show_modif_preset_separately();
|
||||||
cb->set_selection_changed_function([this, new_type, preset_bundle, cb](int selection) {
|
cb->set_selection_changed_function([this, new_type, preset_bundle, cb](int selection) {
|
||||||
if (m_view_type == Preset::TYPE_INVALID) {
|
std::string preset_name = Preset::remove_suffix_modified(cb->GetString(selection).ToUTF8().data());
|
||||||
std::string preset_name = cb->GetString(selection).ToUTF8().data();
|
if (m_view_type == Preset::TYPE_INVALID)
|
||||||
update_compatibility(preset_name, new_type, preset_bundle);
|
update_compatibility(preset_name, new_type, preset_bundle);
|
||||||
}
|
// update selection inside of related presets
|
||||||
|
preset_bundle->get_presets(new_type).select_preset_by_name(preset_name, true);
|
||||||
update_tree();
|
update_tree();
|
||||||
});
|
});
|
||||||
if (collection->get_selected_idx() != (size_t)-1)
|
if (collection->get_selected_idx() != (size_t)-1)
|
||||||
@ -1527,7 +1510,7 @@ DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe)
|
|||||||
add_preset_combobox(&presets_left, m_preset_bundle_left.get());
|
add_preset_combobox(&presets_left, m_preset_bundle_left.get());
|
||||||
sizer->Add(equal_bmp, 0, wxRIGHT | wxLEFT | wxALIGN_CENTER_VERTICAL, 5);
|
sizer->Add(equal_bmp, 0, wxRIGHT | wxLEFT | wxALIGN_CENTER_VERTICAL, 5);
|
||||||
add_preset_combobox(&presets_right, m_preset_bundle_right.get());
|
add_preset_combobox(&presets_right, m_preset_bundle_right.get());
|
||||||
presets_sizer->Add(sizer, 1, wxTOP, 5);
|
m_presets_sizer->Add(sizer, 1, wxTOP, 5);
|
||||||
equal_bmp->Show(new_type == Preset::TYPE_PRINTER);
|
equal_bmp->Show(new_type == Preset::TYPE_PRINTER);
|
||||||
|
|
||||||
m_preset_combos.push_back({ presets_left, equal_bmp, presets_right });
|
m_preset_combos.push_back({ presets_left, equal_bmp, presets_right });
|
||||||
@ -1540,7 +1523,10 @@ DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe)
|
|||||||
update_tree();
|
update_tree();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiffPresetDialog::create_show_all_presets_chb()
|
||||||
|
{
|
||||||
m_show_all_presets = new wxCheckBox(this, wxID_ANY, _L("Show all presets (including incompatible)"));
|
m_show_all_presets = new wxCheckBox(this, wxID_ANY, _L("Show all presets (including incompatible)"));
|
||||||
m_show_all_presets->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) {
|
m_show_all_presets->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) {
|
||||||
bool show_all = m_show_all_presets->GetValue();
|
bool show_all = m_show_all_presets->GetValue();
|
||||||
@ -1553,26 +1539,171 @@ DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe)
|
|||||||
if (m_view_type == Preset::TYPE_INVALID)
|
if (m_view_type == Preset::TYPE_INVALID)
|
||||||
update_tree();
|
update_tree();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
m_tree = new DiffViewCtrl(this, wxSize(em * 65, em * 40));
|
void DiffPresetDialog::create_info_lines()
|
||||||
|
{
|
||||||
|
const wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold();
|
||||||
|
|
||||||
|
m_top_info_line = new wxStaticText(this, wxID_ANY, _L("Select presets to compare"));
|
||||||
|
m_top_info_line->SetFont(font);
|
||||||
|
|
||||||
|
m_bottom_info_line = new wxStaticText(this, wxID_ANY, "");
|
||||||
|
m_bottom_info_line->SetFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiffPresetDialog::create_tree()
|
||||||
|
{
|
||||||
|
m_tree = new DiffViewCtrl(this, wxSize(em_unit() * 65, em_unit() * 40));
|
||||||
|
m_tree->AppendToggleColumn_(L"\u2714", DiffModel::colToggle, wxLinux ? 9 : 6);
|
||||||
m_tree->AppendBmpTextColumn("", DiffModel::colIconText, 35);
|
m_tree->AppendBmpTextColumn("", DiffModel::colIconText, 35);
|
||||||
m_tree->AppendBmpTextColumn(_L("Left Preset Value"), DiffModel::colOldValue, 15);
|
m_tree->AppendBmpTextColumn(_L("Left Preset Value"), DiffModel::colOldValue, 15);
|
||||||
m_tree->AppendBmpTextColumn(_L("Right Preset Value"),DiffModel::colModValue, 15);
|
m_tree->AppendBmpTextColumn(_L("Right Preset Value"),DiffModel::colModValue, 15);
|
||||||
m_tree->Hide();
|
m_tree->Hide();
|
||||||
|
m_tree->GetColumn(DiffModel::colToggle)->SetHidden(true);
|
||||||
|
}
|
||||||
|
|
||||||
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
|
void DiffPresetDialog::create_buttons()
|
||||||
|
{
|
||||||
|
wxFont font = this->GetFont().Scaled(1.4f);
|
||||||
|
m_buttons = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
|
||||||
topSizer->Add(m_top_info_line, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, 2 * border);
|
auto show_in_bottom_info = [this](const wxString& ext_line, wxMouseEvent& e) {
|
||||||
topSizer->Add(presets_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border);
|
m_bottom_info_line->SetLabel(ext_line);
|
||||||
topSizer->Add(m_show_all_presets, 0, wxEXPAND | wxALL, border);
|
m_bottom_info_line->Show(true);
|
||||||
topSizer->Add(m_tree, 1, wxEXPAND | wxALL, border);
|
Layout();
|
||||||
topSizer->Add(m_bottom_info_line, 0, wxEXPAND | wxALL, 2 * border);
|
e.Skip();
|
||||||
|
};
|
||||||
|
|
||||||
this->SetMinSize(wxSize(80 * em, 30 * em));
|
// Transfer
|
||||||
|
m_transfer_btn = new ScalableButton(this, wxID_ANY, "paste_menu", _L("Transfer"), wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, 24);
|
||||||
|
m_transfer_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { button_event(Action::Transfer);});
|
||||||
|
|
||||||
|
|
||||||
|
auto enable_transfer = [this](const Preset::Type& type) {
|
||||||
|
const Preset& main_edited_preset = get_preset_collection(type, wxGetApp().preset_bundle)->get_edited_preset();
|
||||||
|
if (main_edited_preset.is_dirty)
|
||||||
|
return main_edited_preset.name == get_right_preset_name(type);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
m_transfer_btn->Bind(wxEVT_UPDATE_UI, [this, enable_transfer](wxUpdateUIEvent& evt) {
|
||||||
|
bool enable = m_tree->has_selection();
|
||||||
|
if (enable) {
|
||||||
|
if (m_view_type == Preset::TYPE_INVALID) {
|
||||||
|
for (const Preset::Type& type : (m_pr_technology == ptFFF ? std::initializer_list<Preset::Type>{Preset::TYPE_PRINTER, Preset::TYPE_PRINT, Preset::TYPE_FILAMENT} :
|
||||||
|
std::initializer_list<Preset::Type>{ Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL }))
|
||||||
|
if (!enable_transfer(type)) {
|
||||||
|
enable = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
enable = enable_transfer(m_view_type);
|
||||||
|
}
|
||||||
|
evt.Enable(enable);
|
||||||
|
});
|
||||||
|
m_transfer_btn->Bind(wxEVT_ENTER_WINDOW, [this, show_in_bottom_info](wxMouseEvent& e) {
|
||||||
|
show_in_bottom_info(_L("Transfer the selected options from left preset to the right.\n"
|
||||||
|
"Note: New modified presets will be selected in setting stabs after close this dialog."), e); });
|
||||||
|
|
||||||
|
// Save
|
||||||
|
m_save_btn = new ScalableButton(this, wxID_ANY, "save", _L("Save"), wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, 24);
|
||||||
|
m_save_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { button_event(Action::Save); });
|
||||||
|
m_save_btn->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(m_tree->has_selection()); });
|
||||||
|
m_save_btn->Bind(wxEVT_ENTER_WINDOW, [this, show_in_bottom_info](wxMouseEvent& e) {
|
||||||
|
show_in_bottom_info(_L("Save the selected options from left preset to the right."), e); });
|
||||||
|
|
||||||
|
// Cancel
|
||||||
|
m_cancel_btn = new ScalableButton(this, wxID_CANCEL, "cross", _L("Cancel"), wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, 24);
|
||||||
|
m_cancel_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { button_event(Action::Discard);});
|
||||||
|
|
||||||
|
for (ScalableButton* btn : { m_transfer_btn, m_save_btn, m_cancel_btn }) {
|
||||||
|
btn->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& e) { update_bottom_info(); Layout(); e.Skip(); });
|
||||||
|
m_buttons->Add(btn, 1, wxLEFT, 5);
|
||||||
|
btn->SetFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buttons->Show(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiffPresetDialog::create_edit_sizer()
|
||||||
|
{
|
||||||
|
// Add check box for the edit mode
|
||||||
|
m_use_for_transfer = new wxCheckBox(this, wxID_ANY, _L("Transfer values from left to right"));
|
||||||
|
m_use_for_transfer->SetToolTip(_L("If enabled, this dialog can be used for transver selected values from left to right preset."));
|
||||||
|
m_use_for_transfer->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent&) {
|
||||||
|
bool use = m_use_for_transfer->GetValue();
|
||||||
|
m_tree->GetColumn(DiffModel::colToggle)->SetHidden(!use);
|
||||||
|
if (m_tree->IsShown()) {
|
||||||
|
m_buttons->Show(use);
|
||||||
|
Fit();
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
this->Layout();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add Buttons
|
||||||
|
create_buttons();
|
||||||
|
|
||||||
|
// Create and fill edit sizer
|
||||||
|
m_edit_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
m_edit_sizer->Add(m_use_for_transfer, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 5);
|
||||||
|
m_edit_sizer->AddSpacer(em_unit() * 10);
|
||||||
|
m_edit_sizer->Add(m_buttons, 1, wxLEFT, 5);
|
||||||
|
m_edit_sizer->Show(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiffPresetDialog::complete_dialog_creation()
|
||||||
|
{
|
||||||
|
wxBoxSizer*topSizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
|
||||||
|
int border = 10;
|
||||||
|
topSizer->Add(m_top_info_line, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, 2 * border);
|
||||||
|
topSizer->Add(m_presets_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border);
|
||||||
|
topSizer->Add(m_show_all_presets, 0, wxEXPAND | wxALL, border);
|
||||||
|
topSizer->Add(m_tree, 1, wxEXPAND | wxALL, border);
|
||||||
|
topSizer->Add(m_bottom_info_line, 0, wxEXPAND | wxALL, 2 * border);
|
||||||
|
topSizer->Add(m_edit_sizer, 0, wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT, 2 * border);
|
||||||
|
|
||||||
|
this->SetMinSize(wxSize(80 * em_unit(), 30 * em_unit()));
|
||||||
this->SetSizer(topSizer);
|
this->SetSizer(topSizer);
|
||||||
topSizer->SetSizeHints(this);
|
topSizer->SetSizeHints(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe)
|
||||||
|
: DPIDialog(mainframe, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||||
|
m_pr_technology(wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology())
|
||||||
|
{
|
||||||
|
#if defined(__WXMSW__)
|
||||||
|
// ys_FIXME! temporary workaround for correct font scaling
|
||||||
|
// Because of from wxWidgets 3.1.3 auto rescaling is implemented for the Fonts,
|
||||||
|
// From the very beginning set dialog font to the wxSYS_DEFAULT_GUI_FONT
|
||||||
|
this->SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||||
|
#endif // __WXMSW__
|
||||||
|
|
||||||
|
// Init bundles
|
||||||
|
|
||||||
|
assert(wxGetApp().preset_bundle);
|
||||||
|
|
||||||
|
m_preset_bundle_left = std::make_unique<PresetBundle>(*wxGetApp().preset_bundle);
|
||||||
|
m_preset_bundle_right = std::make_unique<PresetBundle>(*wxGetApp().preset_bundle);
|
||||||
|
|
||||||
|
// Create UI items
|
||||||
|
|
||||||
|
create_info_lines();
|
||||||
|
|
||||||
|
create_presets_sizer();
|
||||||
|
|
||||||
|
create_show_all_presets_chb();
|
||||||
|
|
||||||
|
create_tree();
|
||||||
|
|
||||||
|
create_edit_sizer();
|
||||||
|
|
||||||
|
complete_dialog_creation();
|
||||||
|
}
|
||||||
|
|
||||||
void DiffPresetDialog::update_controls_visibility(Preset::Type type /* = Preset::TYPE_INVALID*/)
|
void DiffPresetDialog::update_controls_visibility(Preset::Type type /* = Preset::TYPE_INVALID*/)
|
||||||
{
|
{
|
||||||
for (auto preset_combos : m_preset_combos) {
|
for (auto preset_combos : m_preset_combos) {
|
||||||
@ -1598,6 +1729,8 @@ void DiffPresetDialog::update_bundles_from_app()
|
|||||||
{
|
{
|
||||||
*m_preset_bundle_left = *wxGetApp().preset_bundle;
|
*m_preset_bundle_left = *wxGetApp().preset_bundle;
|
||||||
*m_preset_bundle_right = *wxGetApp().preset_bundle;
|
*m_preset_bundle_right = *wxGetApp().preset_bundle;
|
||||||
|
|
||||||
|
m_pr_technology = m_preset_bundle_left.get()->printers.get_edited_preset().printer_technology();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiffPresetDialog::show(Preset::Type type /* = Preset::TYPE_INVALID*/)
|
void DiffPresetDialog::show(Preset::Type type /* = Preset::TYPE_INVALID*/)
|
||||||
@ -1618,11 +1751,10 @@ void DiffPresetDialog::show(Preset::Type type /* = Preset::TYPE_INVALID*/)
|
|||||||
Show();
|
Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiffPresetDialog::update_presets(Preset::Type type)
|
void DiffPresetDialog::update_presets(Preset::Type type, bool update_preset_bundles_from_app/* = true */)
|
||||||
{
|
{
|
||||||
m_pr_technology = m_preset_bundle_left.get()->printers.get_edited_preset().printer_technology();
|
if (update_preset_bundles_from_app)
|
||||||
|
update_bundles_from_app();
|
||||||
update_bundles_from_app();
|
|
||||||
update_controls_visibility(type);
|
update_controls_visibility(type);
|
||||||
|
|
||||||
if (type == Preset::TYPE_INVALID)
|
if (type == Preset::TYPE_INVALID)
|
||||||
@ -1645,9 +1777,20 @@ void DiffPresetDialog::update_presets(Preset::Type type)
|
|||||||
update_tree();
|
update_tree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiffPresetDialog::update_bottom_info(wxString bottom_info)
|
||||||
|
{
|
||||||
|
if (m_tree->has_long_strings())
|
||||||
|
bottom_info = _L("Some fields are too long to fit. Right mouse click reveals the full text.");
|
||||||
|
|
||||||
|
const bool show_bottom_info = !m_tree->IsShown() || m_tree->has_long_strings();
|
||||||
|
if (show_bottom_info)
|
||||||
|
m_bottom_info_line->SetLabel(bottom_info);
|
||||||
|
m_bottom_info_line->Show(show_bottom_info);
|
||||||
|
}
|
||||||
|
|
||||||
void DiffPresetDialog::update_tree()
|
void DiffPresetDialog::update_tree()
|
||||||
{
|
{
|
||||||
// update searcher befofre update of tree
|
// update searcher before update of tree
|
||||||
wxGetApp().sidebar().check_and_update_searcher();
|
wxGetApp().sidebar().check_and_update_searcher();
|
||||||
Search::OptionsSearcher& searcher = wxGetApp().sidebar().get_searcher();
|
Search::OptionsSearcher& searcher = wxGetApp().sidebar().get_searcher();
|
||||||
searcher.sort_options_by_key();
|
searcher.sort_options_by_key();
|
||||||
@ -1740,16 +1883,14 @@ void DiffPresetDialog::update_tree()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_tree->has_long_strings())
|
|
||||||
bottom_info = _L("Some fields are too long to fit. Right mouse click reveals the full text.");
|
|
||||||
|
|
||||||
bool tree_was_shown = m_tree->IsShown();
|
bool tree_was_shown = m_tree->IsShown();
|
||||||
m_tree->Show(show_tree);
|
m_tree->Show(show_tree);
|
||||||
|
|
||||||
bool show_bottom_info = !show_tree || m_tree->has_long_strings();
|
bool can_transfer_options = m_view_type == Preset::TYPE_INVALID || get_left_preset_name(m_view_type) != get_right_preset_name(m_view_type);
|
||||||
if (show_bottom_info)
|
m_edit_sizer->Show(show_tree && can_transfer_options);
|
||||||
m_bottom_info_line->SetLabel(bottom_info);
|
m_buttons->Show(m_edit_sizer->IsShown(size_t(0)) && m_use_for_transfer->GetValue());
|
||||||
m_bottom_info_line->Show(show_bottom_info);
|
|
||||||
|
update_bottom_info(bottom_info);
|
||||||
|
|
||||||
if (tree_was_shown == m_tree->IsShown())
|
if (tree_was_shown == m_tree->IsShown())
|
||||||
Layout();
|
Layout();
|
||||||
@ -1802,6 +1943,10 @@ void DiffPresetDialog::on_sys_color_changed()
|
|||||||
preset_combos.equal_bmp->sys_color_changed();
|
preset_combos.equal_bmp->sys_color_changed();
|
||||||
preset_combos.presets_right->sys_color_changed();
|
preset_combos.presets_right->sys_color_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (ScalableButton* btn : { m_transfer_btn, m_save_btn, m_cancel_btn })
|
||||||
|
btn->sys_color_changed();
|
||||||
|
|
||||||
// msw_rescale updates just icons, so use it
|
// msw_rescale updates just icons, so use it
|
||||||
m_tree->Rescale();
|
m_tree->Rescale();
|
||||||
Refresh();
|
Refresh();
|
||||||
@ -1865,6 +2010,90 @@ void DiffPresetDialog::update_compatibility(const std::string& preset_name, Pres
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DiffPresetDialog::save()
|
||||||
|
{
|
||||||
|
presets_to_save.clear();
|
||||||
|
|
||||||
|
std::vector<Preset::Type> types_for_save;
|
||||||
|
|
||||||
|
for (const Preset::Type& type : m_pr_technology == ptFFF ? std::initializer_list<Preset::Type>{Preset::TYPE_PRINTER, Preset::TYPE_PRINT, Preset::TYPE_FILAMENT} :
|
||||||
|
std::initializer_list<Preset::Type>{Preset::TYPE_PRINTER, Preset::TYPE_SLA_PRINT, Preset::TYPE_SLA_MATERIAL })
|
||||||
|
if (!m_tree->options(type, true).empty()) {
|
||||||
|
types_for_save.emplace_back(type);
|
||||||
|
presets_to_save.emplace_back(PresetToSave{ type, get_left_preset_name(type), get_right_preset_name(type), get_right_preset_name(type) });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!types_for_save.empty()) {
|
||||||
|
SavePresetDialog save_dlg(this, types_for_save, _u8L("Modified"), m_preset_bundle_right.get());
|
||||||
|
if (save_dlg.ShowModal() != wxID_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto& preset : presets_to_save) {
|
||||||
|
const std::string& name = save_dlg.get_name(preset.type);
|
||||||
|
if (!name.empty())
|
||||||
|
preset.new_name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> DiffPresetDialog::get_options_to_save(Preset::Type type)
|
||||||
|
{
|
||||||
|
auto options = m_tree->options(type, true);
|
||||||
|
|
||||||
|
// erase "inherits" option from the list if it exists there
|
||||||
|
if (const auto it = std::find(options.begin(), options.end(), "inherits"); it != options.end())
|
||||||
|
options.erase(it);
|
||||||
|
|
||||||
|
if (type == Preset::TYPE_PRINTER) {
|
||||||
|
// erase "extruders_count" option from the list if it exists there
|
||||||
|
if (const auto it = std::find(options.begin(), options.end(), "extruders_count"); it != options.end())
|
||||||
|
options.erase(it);
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiffPresetDialog::button_event(Action act)
|
||||||
|
{
|
||||||
|
if (act == Action::Save) {
|
||||||
|
if (save()) {
|
||||||
|
size_t saved_cnt = 0;
|
||||||
|
for (const auto& preset : presets_to_save)
|
||||||
|
if (wxGetApp().preset_bundle->transfer_and_save(preset.type, preset.from_name, preset.to_name, preset.new_name, get_options_to_save(preset.type)))
|
||||||
|
saved_cnt++;
|
||||||
|
|
||||||
|
if (saved_cnt > 0) {
|
||||||
|
MessageDialog(this, UnsavedChangesDialog::msg_success_saved_modifications(saved_cnt)).ShowModal();
|
||||||
|
update_bundles_from_app();
|
||||||
|
for (const auto& preset : presets_to_save) {
|
||||||
|
m_preset_bundle_left->get_presets(preset.type).select_preset_by_name(preset.from_name, true);
|
||||||
|
m_preset_bundle_right->get_presets(preset.type).select_preset_by_name(preset.new_name, true);
|
||||||
|
}
|
||||||
|
update_presets(m_view_type, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Hide();
|
||||||
|
if (act == Action::Transfer)
|
||||||
|
wxPostEvent(this, SimpleEvent(EVT_DIFF_DIALOG_TRANSFER));
|
||||||
|
else if (!presets_to_save.empty())
|
||||||
|
wxPostEvent(this, SimpleEvent(EVT_DIFF_DIALOG_UPDATE_PRESETS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DiffPresetDialog::get_left_preset_name(Preset::Type type)
|
||||||
|
{
|
||||||
|
PresetComboBox* cb = m_preset_combos[int(type - Preset::TYPE_PRINT)].presets_left;
|
||||||
|
return Preset::remove_suffix_modified(get_selection(cb));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DiffPresetDialog::get_right_preset_name(Preset::Type type)
|
||||||
|
{
|
||||||
|
PresetComboBox* cb = m_preset_combos[int(type - Preset::TYPE_PRINT)].presets_right;
|
||||||
|
return Preset::remove_suffix_modified(get_selection(cb));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r::GUI
|
} // namespace Slic3r::GUI
|
||||||
|
@ -15,6 +15,9 @@ class wxStaticText;
|
|||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI{
|
namespace GUI{
|
||||||
|
|
||||||
|
wxDECLARE_EVENT(EVT_DIFF_DIALOG_TRANSFER, SimpleEvent);
|
||||||
|
wxDECLARE_EVENT(EVT_DIFF_DIALOG_UPDATE_PRESETS, SimpleEvent);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// ModelNode: a node inside DiffModel
|
// ModelNode: a node inside DiffModel
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -103,7 +106,7 @@ public:
|
|||||||
ModelNode* GetParent() { return m_parent; }
|
ModelNode* GetParent() { return m_parent; }
|
||||||
ModelNodePtrArray& GetChildren() { return m_children; }
|
ModelNodePtrArray& GetChildren() { return m_children; }
|
||||||
ModelNode* GetNthChild(unsigned int n) { return m_children[n].get(); }
|
ModelNode* GetNthChild(unsigned int n) { return m_children[n].get(); }
|
||||||
unsigned int GetChildCount() const { return m_children.size(); }
|
unsigned int GetChildCount() const { return (unsigned int)(m_children.size()); }
|
||||||
|
|
||||||
void Append(std::unique_ptr<ModelNode> child) { m_children.emplace_back(std::move(child)); }
|
void Append(std::unique_ptr<ModelNode> child) { m_children.emplace_back(std::move(child)); }
|
||||||
|
|
||||||
@ -154,7 +157,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
DiffModel(wxWindow* parent);
|
DiffModel(wxWindow* parent);
|
||||||
~DiffModel() {}
|
~DiffModel() override = default;
|
||||||
|
|
||||||
void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; }
|
void SetAssociatedControl(wxDataViewCtrl* ctrl) { m_ctrl = ctrl; }
|
||||||
|
|
||||||
@ -242,6 +245,20 @@ public:
|
|||||||
std::vector<std::string> selected_options();
|
std::vector<std::string> selected_options();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Discard and Cancel buttons are always but next buttons are optional
|
||||||
|
enum ActionButtons {
|
||||||
|
TRANSFER = 1,
|
||||||
|
KEEP = 2,
|
||||||
|
SAVE = 4,
|
||||||
|
DONT_SAVE = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Action {
|
||||||
|
Undef,
|
||||||
|
Transfer,
|
||||||
|
Discard,
|
||||||
|
Save
|
||||||
|
};
|
||||||
|
|
||||||
//------------------------------------------
|
//------------------------------------------
|
||||||
// UnsavedChangesDialog
|
// UnsavedChangesDialog
|
||||||
@ -262,13 +279,6 @@ class UnsavedChangesDialog : public DPIDialog
|
|||||||
|
|
||||||
std::string m_app_config_key;
|
std::string m_app_config_key;
|
||||||
|
|
||||||
enum class Action {
|
|
||||||
Undef,
|
|
||||||
Transfer,
|
|
||||||
Discard,
|
|
||||||
Save
|
|
||||||
};
|
|
||||||
|
|
||||||
static constexpr char ActTransfer[] = "transfer";
|
static constexpr char ActTransfer[] = "transfer";
|
||||||
static constexpr char ActDiscard[] = "discard";
|
static constexpr char ActDiscard[] = "discard";
|
||||||
static constexpr char ActSave[] = "save";
|
static constexpr char ActSave[] = "save";
|
||||||
@ -281,19 +291,12 @@ class UnsavedChangesDialog : public DPIDialog
|
|||||||
int m_buttons { ActionButtons::TRANSFER | ActionButtons::SAVE };
|
int m_buttons { ActionButtons::TRANSFER | ActionButtons::SAVE };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Discard and Cancel buttons are always but next buttons are optional
|
|
||||||
enum ActionButtons {
|
|
||||||
TRANSFER = 1,
|
|
||||||
KEEP = 2,
|
|
||||||
SAVE = 4,
|
|
||||||
DONT_SAVE = 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
// show unsaved changes when preset is switching
|
// show unsaved changes when preset is switching
|
||||||
UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset = std::string());
|
UnsavedChangesDialog(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset = std::string());
|
||||||
// show unsaved changes for all another cases
|
// show unsaved changes for all another cases
|
||||||
UnsavedChangesDialog(const wxString& caption, const wxString& header, const std::string& app_config_key, int act_buttons);
|
UnsavedChangesDialog(const wxString& caption, const wxString& header, const std::string& app_config_key, int act_buttons);
|
||||||
~UnsavedChangesDialog() {}
|
~UnsavedChangesDialog() override = default;
|
||||||
|
|
||||||
void build(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header = "");
|
void build(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header = "");
|
||||||
void update(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header);
|
void update(Preset::Type type, PresetCollection* dependent_presets, const std::string& new_selected_preset, const wxString& header);
|
||||||
@ -318,6 +321,8 @@ public:
|
|||||||
std::vector<std::string> get_selected_options() { return m_tree->selected_options(); }
|
std::vector<std::string> get_selected_options() { return m_tree->selected_options(); }
|
||||||
bool has_unselected_options() { return m_tree->has_unselected_options(); }
|
bool has_unselected_options() { return m_tree->has_unselected_options(); }
|
||||||
|
|
||||||
|
static wxString msg_success_saved_modifications(size_t saved_presets_cnt);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||||
void on_sys_color_changed() override;
|
void on_sys_color_changed() override;
|
||||||
@ -332,7 +337,7 @@ class FullCompareDialog : public wxDialog
|
|||||||
public:
|
public:
|
||||||
FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& mod_value, const wxString& new_value,
|
FullCompareDialog(const wxString& option_name, const wxString& old_value, const wxString& mod_value, const wxString& new_value,
|
||||||
const wxString& old_value_header, const wxString& mod_value_header, const wxString& new_value_header);
|
const wxString& old_value_header, const wxString& mod_value_header, const wxString& new_value_header);
|
||||||
~FullCompareDialog() {}
|
~FullCompareDialog() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -342,19 +347,39 @@ public:
|
|||||||
class DiffPresetDialog : public DPIDialog
|
class DiffPresetDialog : public DPIDialog
|
||||||
{
|
{
|
||||||
DiffViewCtrl* m_tree { nullptr };
|
DiffViewCtrl* m_tree { nullptr };
|
||||||
|
wxBoxSizer* m_presets_sizer { nullptr };
|
||||||
wxStaticText* m_top_info_line { nullptr };
|
wxStaticText* m_top_info_line { nullptr };
|
||||||
wxStaticText* m_bottom_info_line { nullptr };
|
wxStaticText* m_bottom_info_line { nullptr };
|
||||||
wxCheckBox* m_show_all_presets { nullptr };
|
wxCheckBox* m_show_all_presets { nullptr };
|
||||||
|
wxCheckBox* m_use_for_transfer { nullptr };
|
||||||
|
ScalableButton* m_transfer_btn { nullptr };
|
||||||
|
ScalableButton* m_save_btn { nullptr };
|
||||||
|
ScalableButton* m_cancel_btn { nullptr };
|
||||||
|
wxBoxSizer* m_buttons { nullptr };
|
||||||
|
wxBoxSizer* m_edit_sizer { nullptr };
|
||||||
|
|
||||||
Preset::Type m_view_type { Preset::TYPE_INVALID };
|
Preset::Type m_view_type { Preset::TYPE_INVALID };
|
||||||
PrinterTechnology m_pr_technology;
|
PrinterTechnology m_pr_technology;
|
||||||
std::unique_ptr<PresetBundle> m_preset_bundle_left;
|
std::unique_ptr<PresetBundle> m_preset_bundle_left;
|
||||||
std::unique_ptr<PresetBundle> m_preset_bundle_right;
|
std::unique_ptr<PresetBundle> m_preset_bundle_right;
|
||||||
|
|
||||||
void update_tree();
|
void create_buttons();
|
||||||
void update_bundles_from_app();
|
void create_edit_sizer();
|
||||||
void update_controls_visibility(Preset::Type type = Preset::TYPE_INVALID);
|
void complete_dialog_creation();
|
||||||
void update_compatibility(const std::string& preset_name, Preset::Type type, PresetBundle* preset_bundle);
|
void create_presets_sizer();
|
||||||
|
void create_info_lines();
|
||||||
|
void create_tree();
|
||||||
|
void create_show_all_presets_chb();
|
||||||
|
|
||||||
|
void update_bottom_info(wxString bottom_info = "");
|
||||||
|
void update_tree();
|
||||||
|
void update_bundles_from_app();
|
||||||
|
void update_controls_visibility(Preset::Type type = Preset::TYPE_INVALID);
|
||||||
|
void update_compatibility(const std::string& preset_name, Preset::Type type, PresetBundle* preset_bundle);
|
||||||
|
|
||||||
|
std::vector<std::string> get_options_to_save(Preset::Type type);
|
||||||
|
void button_event(Action act);
|
||||||
|
bool save();
|
||||||
|
|
||||||
struct DiffPresets
|
struct DiffPresets
|
||||||
{
|
{
|
||||||
@ -365,12 +390,31 @@ class DiffPresetDialog : public DPIDialog
|
|||||||
|
|
||||||
std::vector<DiffPresets> m_preset_combos;
|
std::vector<DiffPresets> m_preset_combos;
|
||||||
|
|
||||||
public:
|
// attributes witch are used for save preset
|
||||||
DiffPresetDialog(MainFrame* mainframe);
|
struct PresetToSave
|
||||||
~DiffPresetDialog() {}
|
{
|
||||||
|
Preset::Type type;
|
||||||
|
std::string from_name;
|
||||||
|
std::string to_name;
|
||||||
|
std::string new_name;
|
||||||
|
};
|
||||||
|
|
||||||
void show(Preset::Type type = Preset::TYPE_INVALID);
|
std::vector<PresetToSave> presets_to_save;
|
||||||
void update_presets(Preset::Type type = Preset::TYPE_INVALID);
|
|
||||||
|
public:
|
||||||
|
DiffPresetDialog(MainFrame*mainframe);
|
||||||
|
~DiffPresetDialog() override = default;
|
||||||
|
|
||||||
|
void show(Preset::Type type = Preset::TYPE_INVALID);
|
||||||
|
void update_presets(Preset::Type type = Preset::TYPE_INVALID, bool update_preset_bundles_from_app = true);
|
||||||
|
|
||||||
|
Preset::Type view_type() const { return m_view_type; }
|
||||||
|
PrinterTechnology printer_technology() const { return m_pr_technology; }
|
||||||
|
|
||||||
|
std::string get_left_preset_name(Preset::Type type);
|
||||||
|
std::string get_right_preset_name(Preset::Type type);
|
||||||
|
|
||||||
|
std::vector<std::string> get_selected_options(Preset::Type type) const { return std::move(m_tree->options(type, true)); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||||
|