Merge branch 'master' of https://github.com/prusa3d/Slic3r into scene_manipulators

This commit is contained in:
Enrico Turri 2018-07-18 08:29:11 +02:00
commit eb95e29be6
32 changed files with 1010 additions and 422 deletions

View File

@ -535,7 +535,11 @@ sub new {
fil_mm3 => L("Used Filament (mm³)"), fil_mm3 => L("Used Filament (mm³)"),
fil_g => L("Used Filament (g)"), fil_g => L("Used Filament (g)"),
cost => L("Cost"), cost => L("Cost"),
time => L("Estimated printing time"), #==========================================================================================================================================
normal_time => L("Estimated printing time (normal mode)"),
# default_time => L("Estimated printing time (default mode)"),
#==========================================================================================================================================
silent_time => L("Estimated printing time (silent mode)"),
); );
while (my $field = shift @info) { while (my $field = shift @info) {
my $label = shift @info; my $label = shift @info;
@ -1617,7 +1621,11 @@ sub on_export_completed {
$self->{"print_info_cost"}->SetLabel(sprintf("%.2f" , $self->{print}->total_cost)); $self->{"print_info_cost"}->SetLabel(sprintf("%.2f" , $self->{print}->total_cost));
$self->{"print_info_fil_g"}->SetLabel(sprintf("%.2f" , $self->{print}->total_weight)); $self->{"print_info_fil_g"}->SetLabel(sprintf("%.2f" , $self->{print}->total_weight));
$self->{"print_info_fil_mm3"}->SetLabel(sprintf("%.2f" , $self->{print}->total_extruded_volume)); $self->{"print_info_fil_mm3"}->SetLabel(sprintf("%.2f" , $self->{print}->total_extruded_volume));
$self->{"print_info_time"}->SetLabel($self->{print}->estimated_print_time); #==========================================================================================================================================
$self->{"print_info_normal_time"}->SetLabel($self->{print}->estimated_normal_print_time);
# $self->{"print_info_default_time"}->SetLabel($self->{print}->estimated_default_print_time);
#==========================================================================================================================================
$self->{"print_info_silent_time"}->SetLabel($self->{print}->estimated_silent_print_time);
$self->{"print_info_fil_m"}->SetLabel(sprintf("%.2f" , $self->{print}->total_used_filament / 1000)); $self->{"print_info_fil_m"}->SetLabel(sprintf("%.2f" , $self->{print}->total_used_filament / 1000));
$self->{"print_info_box_show"}->(1); $self->{"print_info_box_show"}->(1);
@ -1694,6 +1702,34 @@ sub export_object_stl {
$self->statusbar->SetStatusText(L("STL file exported to ").$output_file); $self->statusbar->SetStatusText(L("STL file exported to ").$output_file);
} }
sub fix_through_netfabb {
my ($self) = @_;
my ($obj_idx, $object) = $self->selected_object;
return if !defined $obj_idx;
my $model_object = $self->{model}->objects->[$obj_idx];
my $model_fixed = Slic3r::Model->new;
Slic3r::GUI::fix_model_by_win10_sdk_gui($model_object, $self->{print}, $model_fixed);
my @new_obj_idx = $self->load_model_objects(@{$model_fixed->objects});
return if !@new_obj_idx;
foreach my $new_obj_idx (@new_obj_idx) {
my $o = $self->{model}->objects->[$new_obj_idx];
$o->clear_instances;
$o->add_instance($_) for @{$model_object->instances};
#$o->invalidate_bounding_box;
if ($o->volumes_count == $model_object->volumes_count) {
for my $i (0..($o->volumes_count-1)) {
$o->get_volume($i)->config->apply($model_object->get_volume($i)->config);
}
}
#FIXME restore volumes and their configs, layer_height_ranges, layer_height_profile, layer_height_profile_valid,
}
$self->remove($obj_idx);
}
sub export_amf { sub export_amf {
my ($self) = @_; my ($self) = @_;
return if !@{$self->{objects}}; return if !@{$self->{objects}};
@ -2272,6 +2308,11 @@ sub object_menu {
$frame->_append_menu_item($menu, L("Export object as STL…"), L('Export this single object as STL file'), sub { $frame->_append_menu_item($menu, L("Export object as STL…"), L('Export this single object as STL file'), sub {
$self->export_object_stl; $self->export_object_stl;
}, undef, 'brick_go.png'); }, undef, 'brick_go.png');
if (Slic3r::GUI::is_windows10) {
$frame->_append_menu_item($menu, L("Fix STL through Netfabb"), L('Fix the model by sending it to a Netfabb cloud service through Windows 10 API'), sub {
$self->fix_through_netfabb;
}, undef, 'brick_go.png');
}
return $menu; return $menu;
} }

View File

@ -1,3 +1,5 @@
min_slic3r_version = 1.41.0-alpha
0.2.0-alpha
min_slic3r_version = 1.40.0 min_slic3r_version = 1.40.0
0.1.6 Split the MK2.5 profile from the MK2S 0.1.6 Split the MK2.5 profile from the MK2S
min_slic3r_version = 1.40.0-beta min_slic3r_version = 1.40.0-beta

View File

@ -5,7 +5,7 @@
name = Prusa Research name = Prusa Research
# Configuration version of this file. Config file will only be installed, if the config_version differs. # Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the Slic3r configuration to be downgraded. # This means, the server may force the Slic3r configuration to be downgraded.
config_version = 0.1.6 config_version = 0.2.0-alpha
# Where to get the updates from? # Where to get the updates from?
config_update_url = https://raw.githubusercontent.com/prusa3d/Slic3r-settings/master/live/PrusaResearch/ config_update_url = https://raw.githubusercontent.com/prusa3d/Slic3r-settings/master/live/PrusaResearch/
@ -140,7 +140,7 @@ infill_extrusion_width = 0.25
perimeter_extrusion_width = 0.25 perimeter_extrusion_width = 0.25
solid_infill_extrusion_width = 0.25 solid_infill_extrusion_width = 0.25
top_infill_extrusion_width = 0.25 top_infill_extrusion_width = 0.25
support_material_extrusion_width = 0.18 support_material_extrusion_width = 0.2
support_material_interface_layers = 0 support_material_interface_layers = 0
support_material_interface_spacing = 0.15 support_material_interface_spacing = 0.15
support_material_spacing = 1 support_material_spacing = 1
@ -155,6 +155,7 @@ infill_extrusion_width = 0.7
perimeter_extrusion_width = 0.65 perimeter_extrusion_width = 0.65
solid_infill_extrusion_width = 0.65 solid_infill_extrusion_width = 0.65
top_infill_extrusion_width = 0.6 top_infill_extrusion_width = 0.6
support_material_extrusion_width = 0.55
[print:*soluble_support*] [print:*soluble_support*]
overhangs = 1 overhangs = 1
@ -213,26 +214,18 @@ top_infill_extrusion_width = 0.4
[print:0.05mm ULTRADETAIL 0.25 nozzle] [print:0.05mm ULTRADETAIL 0.25 nozzle]
inherits = *0.05mm*; *0.25nozzle* inherits = *0.05mm*; *0.25nozzle*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.25 and num_extruders==1 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
external_perimeter_extrusion_width = 0
extrusion_width = 0.28
fill_density = 20% fill_density = 20%
first_layer_extrusion_width = 0.3
infill_extrusion_width = 0
infill_speed = 20 infill_speed = 20
max_print_speed = 100 max_print_speed = 100
perimeter_extrusion_width = 0
perimeter_speed = 20 perimeter_speed = 20
small_perimeter_speed = 15 small_perimeter_speed = 15
solid_infill_extrusion_width = 0
solid_infill_speed = 20 solid_infill_speed = 20
support_material_speed = 20 support_material_speed = 20
top_infill_extrusion_width = 0
[print:0.05mm ULTRADETAIL 0.25 nozzle MK3] [print:0.05mm ULTRADETAIL 0.25 nozzle MK3]
inherits = *0.05mm*; *0.25nozzle* inherits = *0.05mm*; *0.25nozzle*
compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
fill_pattern = grid fill_pattern = grid
top_infill_extrusion_width = 0.4
# XXXXXXXXXXXXXXXXXXXX # XXXXXXXXXXXXXXXXXXXX
# XXX--- 0.10mm ---XXX # XXX--- 0.10mm ---XXX
@ -294,7 +287,6 @@ infill_speed = 200
max_print_speed = 200 max_print_speed = 200
perimeter_speed = 45 perimeter_speed = 45
solid_infill_speed = 200 solid_infill_speed = 200
top_infill_extrusion_width = 0.4
top_solid_infill_speed = 50 top_solid_infill_speed = 50
[print:0.10mm DETAIL 0.6 nozzle MK3] [print:0.10mm DETAIL 0.6 nozzle MK3]
@ -308,7 +300,6 @@ infill_speed = 200
max_print_speed = 200 max_print_speed = 200
perimeter_speed = 45 perimeter_speed = 45
solid_infill_speed = 200 solid_infill_speed = 200
top_infill_extrusion_width = 0.4
top_solid_infill_speed = 50 top_solid_infill_speed = 50
# XXXXXXXXXXXXXXXXXXXX # XXXXXXXXXXXXXXXXXXXX
@ -358,7 +349,6 @@ perimeter_acceleration = 600
perimeter_speed = 25 perimeter_speed = 25
small_perimeter_speed = 15 small_perimeter_speed = 15
solid_infill_speed = 40 solid_infill_speed = 40
support_material_extrusion_width = 0.2
top_solid_infill_speed = 30 top_solid_infill_speed = 30
[print:0.15mm OPTIMAL 0.6 nozzle] [print:0.15mm OPTIMAL 0.6 nozzle]
@ -544,7 +534,6 @@ external_perimeter_extrusion_width = 0.6
external_perimeter_speed = 30 external_perimeter_speed = 30
notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder
perimeter_speed = 40 perimeter_speed = 40
support_material_extrusion_width = 0.55
support_material_interface_layers = 3 support_material_interface_layers = 3
support_material_xy_spacing = 120% support_material_xy_spacing = 120%
top_infill_extrusion_width = 0.57 top_infill_extrusion_width = 0.57
@ -912,6 +901,23 @@ end_gcode = G4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbe
extruder_colour = #FFFF00 extruder_colour = #FFFF00
extruder_offset = 0x0 extruder_offset = 0x0
gcode_flavor = marlin gcode_flavor = marlin
silent_mode = 0
machine_max_acceleration_e = 10000
machine_max_acceleration_extruding = 1500
machine_max_acceleration_retracting = 1500
machine_max_acceleration_x = 9000
machine_max_acceleration_y = 9000
machine_max_acceleration_z = 500
machine_max_feedrate_e = 120
machine_max_feedrate_x = 500
machine_max_feedrate_y = 500
machine_max_feedrate_z = 12
machine_max_jerk_e = 2.5
machine_max_jerk_x = 10
machine_max_jerk_y = 10
machine_max_jerk_z = 0.2
machine_min_extruding_rate = 0
machine_min_travel_rate = 0
layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z] layer_gcode = ;AFTER_LAYER_CHANGE\n;[layer_z]
max_layer_height = 0.25 max_layer_height = 0.25
min_layer_height = 0.07 min_layer_height = 0.07
@ -935,7 +941,7 @@ retract_speed = 35
serial_port = serial_port =
serial_speed = 250000 serial_speed = 250000
single_extruder_multi_material = 0 single_extruder_multi_material = 0
start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM201 X9000 Y9000 Z500 E10000 ; sets maximum accelerations, mm/sec^2\nM203 X500 Y500 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1500 T1500 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.2 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
toolchange_gcode = toolchange_gcode =
use_firmware_retraction = 0 use_firmware_retraction = 0
use_relative_e_distances = 1 use_relative_e_distances = 1
@ -971,7 +977,7 @@ printer_model = MK2SMM
inherits = *multimaterial* inherits = *multimaterial*
end_gcode = G1 E-4 F2100.00000\nG91\nG1 Z1 F7200.000\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7 \nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3 \nG1 E-15.0000 F5000\nG1 E-50.0000 F5400\nG1 E-15.0000 F3000\nG1 E-12.0000 F2000\nG1 F1600\nG1 X0 Y1 E3.0000\nG1 X50 Y1 E-5.0000\nG1 F2000\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-3.0000\nG4 S0\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM84 ; disable motors\n\n end_gcode = G1 E-4 F2100.00000\nG91\nG1 Z1 F7200.000\nG90\nG1 X245 Y1\nG1 X240 E4\nG1 F4000\nG1 X190 E2.7 \nG1 F4600\nG1 X110 E2.8\nG1 F5200\nG1 X40 E3 \nG1 E-15.0000 F5000\nG1 E-50.0000 F5400\nG1 E-15.0000 F3000\nG1 E-12.0000 F2000\nG1 F1600\nG1 X0 Y1 E3.0000\nG1 X50 Y1 E-5.0000\nG1 F2000\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-5.0000\nG1 F2400\nG1 X0 Y1 E5.0000\nG1 X50 Y1 E-3.0000\nG4 S0\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nG28 X0 ; home X axis\nM84 ; disable motors\n\n
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN
start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM201 X9000 Y9000 Z500 E10000 ; sets maximum accelerations, mm/sec^2\nM203 X500 Y500 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1500 T1500 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.2 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100\nM92 E140\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG1 E-4 F1000.0\nG92 E0.0 start_gcode = M115 U3.1.0 ; tell printer latest fw version\n; Start G-Code sequence START\nT?\nM104 S[first_layer_temperature]\nM140 S[first_layer_bed_temperature]\nM109 S[first_layer_temperature]\nM190 S[first_layer_bed_temperature]\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100\nM92 E140\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG1 E-4 F1000.0\nG92 E0.0
default_print_profile = 0.15mm OPTIMAL default_print_profile = 0.15mm OPTIMAL
default_filament_profile = Prusa PLA default_filament_profile = Prusa PLA
@ -981,7 +987,7 @@ end_gcode = {if not has_wipe_tower}\n; Pull the filament into the cooling tubes.
extruder_colour = #FFAA55;#5182DB;#4ECDD3;#FB7259 extruder_colour = #FFAA55;#5182DB;#4ECDD3;#FB7259
nozzle_diameter = 0.4,0.4,0.4,0.4 nozzle_diameter = 0.4,0.4,0.4,0.4
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2\nPRINTER_HAS_BOWDEN
start_gcode = M115 U3.1.0 ; tell printer latest fw version\nM201 X9000 Y9000 Z500 E10000 ; sets maximum accelerations, mm/sec^2\nM203 X500 Y500 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1500 T1500 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.2 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\n; Start G-Code sequence START\nT[initial_tool]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100 ; set max feedrate\nM92 E140 ; E-steps per filament milimeter\n{if not has_wipe_tower}\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG1 E-4 F1000.0\n{endif}\nG92 E0.0 start_gcode = M115 U3.1.0 ; tell printer latest fw version\n; Start G-Code sequence START\nT[initial_tool]\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG28 W\nG80\nG92 E0.0\nM203 E100 ; set max feedrate\nM92 E140 ; E-steps per filament milimeter\n{if not has_wipe_tower}\nG1 Z0.250 F7200.000\nG1 X50.0 E80.0 F1000.0\nG1 X160.0 E20.0 F1000.0\nG1 Z0.200 F7200.000\nG1 X220.0 E13 F1000.0\nG1 X240.0 E0 F1000.0\nG1 E-4 F1000.0\n{endif}\nG92 E0.0
variable_layer_height = 0 variable_layer_height = 0
default_print_profile = 0.15mm OPTIMAL default_print_profile = 0.15mm OPTIMAL
default_filament_profile = Prusa PLA default_filament_profile = Prusa PLA
@ -1005,7 +1011,7 @@ printer_variant = 0.25
default_print_profile = 0.10mm DETAIL 0.25 nozzle default_print_profile = 0.10mm DETAIL 0.25 nozzle
[printer:Original Prusa i3 MK2 0.6 nozzle] [printer:Original Prusa i3 MK2 0.6 nozzle]
inherits = *common*; *0.6nozzle* inherits = *common*
max_layer_height = 0.35 max_layer_height = 0.35
min_layer_height = 0.1 min_layer_height = 0.1
nozzle_diameter = 0.6 nozzle_diameter = 0.6
@ -1020,7 +1026,7 @@ default_print_profile = 0.20mm NORMAL 0.6 nozzle
inherits = *mm-single* inherits = *mm-single*
[printer:Original Prusa i3 MK2 MM Single Mode 0.6 nozzle] [printer:Original Prusa i3 MK2 MM Single Mode 0.6 nozzle]
inherits = *mm-single*; *0.6nozzle* inherits = *mm-single*
nozzle_diameter = 0.6 nozzle_diameter = 0.6
printer_variant = 0.6 printer_variant = 0.6
default_print_profile = 0.20mm NORMAL 0.6 nozzle default_print_profile = 0.20mm NORMAL 0.6 nozzle
@ -1030,7 +1036,7 @@ inherits = *mm-multi*
nozzle_diameter = 0.4,0.4,0.4,0.4 nozzle_diameter = 0.4,0.4,0.4,0.4
[printer:Original Prusa i3 MK2 MultiMaterial 0.6 nozzle] [printer:Original Prusa i3 MK2 MultiMaterial 0.6 nozzle]
inherits = *mm-multi*; *0.6nozzle* inherits = *mm-multi*
nozzle_diameter = 0.6,0.6,0.6,0.6 nozzle_diameter = 0.6,0.6,0.6,0.6
printer_variant = 0.6 printer_variant = 0.6
default_print_profile = 0.20mm NORMAL 0.6 nozzle default_print_profile = 0.20mm NORMAL 0.6 nozzle
@ -1042,17 +1048,17 @@ default_print_profile = 0.20mm NORMAL 0.6 nozzle
[printer:Original Prusa i3 MK2.5] [printer:Original Prusa i3 MK2.5]
inherits = Original Prusa i3 MK2 inherits = Original Prusa i3 MK2
printer_model = MK2.5 printer_model = MK2.5
start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM201 X9000 Y9000 Z500 E10000 ; sets maximum accelerations, mm/sec^2\nM203 X500 Y500 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1500 T1500 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.2 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
[printer:Original Prusa i3 MK2.5 0.25 nozzle] [printer:Original Prusa i3 MK2.5 0.25 nozzle]
inherits = Original Prusa i3 MK2 0.25 nozzle inherits = Original Prusa i3 MK2 0.25 nozzle
printer_model = MK2.5 printer_model = MK2.5
start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM201 X9000 Y9000 Z500 E10000 ; sets maximum accelerations, mm/sec^2\nM203 X500 Y500 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1500 T1500 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.2 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
[printer:Original Prusa i3 MK2.5 0.6 nozzle] [printer:Original Prusa i3 MK2.5 0.6 nozzle]
inherits = Original Prusa i3 MK2 0.6 nozzle inherits = Original Prusa i3 MK2 0.6 nozzle
printer_model = MK2.5 printer_model = MK2.5
start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM201 X9000 Y9000 Z500 E10000 ; sets maximum accelerations, mm/sec^2\nM203 X500 Y500 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1500 T1500 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.2 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0
# XXXXXXXXXXXXXXXXX # XXXXXXXXXXXXXXXXX
# XXX--- MK3 ---XXX # XXX--- MK3 ---XXX
@ -1061,38 +1067,47 @@ start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM201 X9000 Y9000 Z50
[printer:Original Prusa i3 MK3] [printer:Original Prusa i3 MK3]
inherits = *common* inherits = *common*
end_gcode = G4 ; wait\nM221 S100\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors end_gcode = G4 ; wait\nM221 S100\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors
machine_max_acceleration_e = 9000,9000
machine_max_acceleration_extruding = 1250,960
machine_max_acceleration_retracting = 1250,1250
machine_max_acceleration_x = 1000,1000
machine_max_acceleration_y = 1000,1000
machine_max_acceleration_z = 1000,1000
machine_max_feedrate_e = 120,120
machine_max_feedrate_x = 200,172
machine_max_feedrate_y = 200,172
machine_max_feedrate_z = 12,12
machine_max_jerk_e = 1.5,1.5
machine_max_jerk_x = 8,8
machine_max_jerk_y = 8,8
machine_max_jerk_z = 0.4,0.4
machine_min_extruding_rate = 0,0
machine_min_travel_rate = 0,0
silent_mode = 1
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
retract_lift_below = 209 retract_lift_below = 209
max_print_height = 210 max_print_height = 210
start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM201 X1000 Y1000 Z200 E5000 ; sets maximum accelerations, mm/sec^2\nM203 X200 Y200 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1250 T1250 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.4 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height==0.05}100{else}95{endif} start_gcode = M115 U3.3.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height==0.05}100{else}95{endif}
printer_model = MK3 printer_model = MK3
default_print_profile = 0.15mm OPTIMAL MK3 default_print_profile = 0.15mm OPTIMAL MK3
[printer:Original Prusa i3 MK3 0.25 nozzle] [printer:Original Prusa i3 MK3 0.25 nozzle]
inherits = *common* inherits = Original Prusa i3 MK3
nozzle_diameter = 0.25 nozzle_diameter = 0.25
end_gcode = G4 ; wait\nM221 S100\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors max_layer_height = 0.1
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n min_layer_height = 0.05
retract_lift_below = 209
max_print_height = 210
start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM201 X1000 Y1000 Z200 E5000 ; sets maximum accelerations, mm/sec^2\nM203 X200 Y200 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1250 T1250 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.4 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height==0.05}100{else}95{endif}
printer_model = MK3
printer_variant = 0.25 printer_variant = 0.25
default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3 default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3
[printer:Original Prusa i3 MK3 0.6 nozzle] [printer:Original Prusa i3 MK3 0.6 nozzle]
inherits = *common* inherits = Original Prusa i3 MK3
nozzle_diameter = 0.6 nozzle_diameter = 0.6
end_gcode = G4 ; wait\nM221 S100\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors max_layer_height = 0.35
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n min_layer_height = 0.1
retract_lift_below = 209
max_print_height = 210
start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM201 X1000 Y1000 Z200 E5000 ; sets maximum accelerations, mm/sec^2\nM203 X200 Y200 Z12 E120 ; sets maximum feedrates, mm/sec\nM204 S1250 T1250 ; sets acceleration (S) and retract acceleration (T)\nM205 X10 Y10 Z0.4 E2.5 ; sets the jerk limits, mm/sec\nM205 S0 T0 ; sets the minimum extruding and travel feed rate, mm/sec\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height==0.05}100{else}95{endif}
printer_model = MK3
printer_variant = 0.6 printer_variant = 0.6
default_print_profile = 0.15mm OPTIMAL 0.6 nozzle MK3 default_print_profile = 0.15mm OPTIMAL 0.6 nozzle MK3
# The obsolete presets will be removed when upgrading from the legacy configuration structure (up to Slic3r 1.39.2) to 1.40.0 and newer. # The obsolete presets will be removed when upgrading from the legacy configuration structure (up to Slic3r 1.39.2) to 1.40.0 and newer.
[obsolete_presets] [obsolete_presets]
print="0.05mm DETAIL 0.25 nozzle";"0.05mm DETAIL MK3";"0.05mm DETAIL";"0.20mm NORMAL MK3";"0.35mm FAST MK3" print="0.05mm DETAIL 0.25 nozzle";"0.05mm DETAIL MK3";"0.05mm DETAIL";"0.20mm NORMAL MK3";"0.35mm FAST MK3"
filament="ColorFabb Brass Bronze 1.75mm";"ColorFabb HT 1.75mm";"ColorFabb nGen 1.75mm";"ColorFabb Woodfil 1.75mm";"ColorFabb XT 1.75mm";"ColorFabb XT-CF20 1.75mm";"E3D PC-ABS 1.75mm";"Fillamentum ABS 1.75mm";"Fillamentum ASA 1.75mm";"Generic ABS 1.75mm";"Generic PET 1.75mm";"Generic PLA 1.75mm";"Prusa ABS 1.75mm";"Prusa HIPS 1.75mm";"Prusa PET 1.75mm";"Prusa PLA 1.75mm";"Taulman Bridge 1.75mm";"Taulman T-Glase 1.75mm" filament="ColorFabb Brass Bronze 1.75mm";"ColorFabb HT 1.75mm";"ColorFabb nGen 1.75mm";"ColorFabb Woodfil 1.75mm";"ColorFabb XT 1.75mm";"ColorFabb XT-CF20 1.75mm";"E3D PC-ABS 1.75mm";"Fillamentum ABS 1.75mm";"Fillamentum ASA 1.75mm";"Generic ABS 1.75mm";"Generic PET 1.75mm";"Generic PLA 1.75mm";"Prusa ABS 1.75mm";"Prusa HIPS 1.75mm";"Prusa PET 1.75mm";"Prusa PLA 1.75mm";"Taulman Bridge 1.75mm";"Taulman T-Glase 1.75mm"

View File

@ -175,7 +175,7 @@ use Slic3r::Test;
if ($info->{extruding} && $info->{dist_XY} > 0) { if ($info->{extruding} && $info->{dist_XY} > 0) {
$cur_loop ||= [ [$self->X, $self->Y] ]; $cur_loop ||= [ [$self->X, $self->Y] ];
push @$cur_loop, [ @$info{qw(new_X new_Y)} ]; push @$cur_loop, [ @$info{qw(new_X new_Y)} ];
} else { } elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
if ($cur_loop) { if ($cur_loop) {
$has_cw_loops = 1 if Slic3r::Polygon->new(@$cur_loop)->is_clockwise; $has_cw_loops = 1 if Slic3r::Polygon->new(@$cur_loop)->is_clockwise;
$cur_loop = undef; $cur_loop = undef;
@ -201,7 +201,7 @@ use Slic3r::Test;
if ($info->{extruding} && $info->{dist_XY} > 0) { if ($info->{extruding} && $info->{dist_XY} > 0) {
$cur_loop ||= [ [$self->X, $self->Y] ]; $cur_loop ||= [ [$self->X, $self->Y] ];
push @$cur_loop, [ @$info{qw(new_X new_Y)} ]; push @$cur_loop, [ @$info{qw(new_X new_Y)} ];
} else { } elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
if ($cur_loop) { if ($cur_loop) {
$has_cw_loops = 1 if Slic3r::Polygon->new_scale(@$cur_loop)->is_clockwise; $has_cw_loops = 1 if Slic3r::Polygon->new_scale(@$cur_loop)->is_clockwise;
if ($self->F == $config->external_perimeter_speed*60) { if ($self->F == $config->external_perimeter_speed*60) {
@ -306,7 +306,7 @@ use Slic3r::Test;
if ($info->{extruding} && $info->{dist_XY} > 0 && ($args->{F} // $self->F) == $config->perimeter_speed*60) { if ($info->{extruding} && $info->{dist_XY} > 0 && ($args->{F} // $self->F) == $config->perimeter_speed*60) {
$perimeters{$self->Z}++ if !$in_loop; $perimeters{$self->Z}++ if !$in_loop;
$in_loop = 1; $in_loop = 1;
} else { } elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
$in_loop = 0; $in_loop = 0;
} }
}); });
@ -430,7 +430,7 @@ use Slic3r::Test;
push @seam_points, Slic3r::Point->new_scale($self->X, $self->Y); push @seam_points, Slic3r::Point->new_scale($self->X, $self->Y);
} }
$was_extruding = 1; $was_extruding = 1;
} else { } elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
$was_extruding = 0; $was_extruding = 0;
} }
}); });

View File

@ -82,8 +82,8 @@ if(LIBNEST2D_OPTIMIZER_BACKEND STREQUAL "nlopt")
${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizers/genetic.hpp ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizers/genetic.hpp
${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizers/nlopt_boilerplate.hpp) ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizers/nlopt_boilerplate.hpp)
list(APPEND LIBNEST2D_LIBRARIES ${NLopt_LIBS} list(APPEND LIBNEST2D_LIBRARIES ${NLopt_LIBS}
# Threads::Threads # Threads::Threads
) )
list(APPEND LIBNEST2D_HEADERS ${NLopt_INCLUDE_DIR}) list(APPEND LIBNEST2D_HEADERS ${NLopt_INCLUDE_DIR})
endif() endif()

View File

@ -84,7 +84,8 @@ void arrangeRectangles() {
// {{0, 0}, {0, 20*SCALE}, {10*SCALE, 0}, {0, 0}} // {{0, 0}, {0, 20*SCALE}, {10*SCALE, 0}, {0, 0}}
// }; // };
std::vector<Item> crasher = { std::vector<Item> crasher =
{
{ {
{-5000000, 8954050}, {-5000000, 8954050},
{5000000, 8954050}, {5000000, 8954050},
@ -527,12 +528,12 @@ void arrangeRectangles() {
}; };
std::vector<Item> input; std::vector<Item> input;
// input.insert(input.end(), prusaParts().begin(), prusaParts().end()); input.insert(input.end(), prusaParts().begin(), prusaParts().end());
// input.insert(input.end(), prusaExParts().begin(), prusaExParts().end()); // input.insert(input.end(), prusaExParts().begin(), prusaExParts().end());
// input.insert(input.end(), stegoParts().begin(), stegoParts().end()); // input.insert(input.end(), stegoParts().begin(), stegoParts().end());
// input.insert(input.end(), rects.begin(), rects.end()); // input.insert(input.end(), rects.begin(), rects.end());
// input.insert(input.end(), proba.begin(), proba.end()); // input.insert(input.end(), proba.begin(), proba.end());
input.insert(input.end(), crasher.begin(), crasher.end()); // input.insert(input.end(), crasher.begin(), crasher.end());
Box bin(250*SCALE, 210*SCALE); Box bin(250*SCALE, 210*SCALE);
@ -545,18 +546,18 @@ void arrangeRectangles() {
Packer::PlacementConfig pconf; Packer::PlacementConfig pconf;
pconf.alignment = Placer::Config::Alignment::CENTER; pconf.alignment = Placer::Config::Alignment::CENTER;
pconf.starting_point = Placer::Config::Alignment::CENTER;
pconf.rotations = {0.0/*, Pi/2.0, Pi, 3*Pi/2*/}; pconf.rotations = {0.0/*, Pi/2.0, Pi, 3*Pi/2*/};
pconf.object_function = [&bin](Placer::Pile pile, double area, pconf.object_function = [&bin](Placer::Pile pile, double area,
double norm, double penality) { double norm, double penality) {
auto bb = ShapeLike::boundingBox(pile); auto bb = ShapeLike::boundingBox(pile);
double diameter = PointLike::distance(bb.minCorner(), auto& sh = pile.back();
bb.maxCorner()); auto rv = Nfp::referenceVertex(sh);
auto c = bin.center();
// We will optimize to the diameter of the circle around the bounding auto d = PointLike::distance(rv, c);
// box and use the norming factor to get rid of the physical dimensions double score = double(d)/norm;
double score = diameter / norm;
// If it does not fit into the print bed we will beat it // If it does not fit into the print bed we will beat it
// with a large penality // with a large penality
@ -568,7 +569,9 @@ void arrangeRectangles() {
Packer::SelectionConfig sconf; Packer::SelectionConfig sconf;
// sconf.allow_parallel = false; // sconf.allow_parallel = false;
// sconf.force_parallel = false; // sconf.force_parallel = false;
// sconf.try_triplets = true;
// sconf.try_reverse_order = true; // sconf.try_reverse_order = true;
// sconf.waste_increment = 0.1;
arrange.configure(pconf, sconf); arrange.configure(pconf, sconf);

View File

@ -26,11 +26,20 @@ struct NfpPConfig {
/// Where to align the resulting packed pile /// Where to align the resulting packed pile
Alignment alignment; Alignment alignment;
Alignment starting_point;
std::function<double(const Nfp::Shapes<RawShape>&, double, double, double)> std::function<double(const Nfp::Shapes<RawShape>&, double, double, double)>
object_function; object_function;
/**
* @brief The quality of search for an optimal placement.
* This is a compromise slider between quality and speed. Zero is the
* fast and poor solution while 1.0 is the slowest but most accurate.
*/
float accuracy = 1.0;
NfpPConfig(): rotations({0.0, Pi/2.0, Pi, 3*Pi/2}), NfpPConfig(): rotations({0.0, Pi/2.0, Pi, 3*Pi/2}),
alignment(Alignment::CENTER) {} alignment(Alignment::CENTER), starting_point(Alignment::CENTER) {}
}; };
// A class for getting a point on the circumference of the polygon (in log time) // A class for getting a point on the circumference of the polygon (in log time)
@ -39,14 +48,6 @@ template<class RawShape> class EdgeCache {
using Coord = TCoord<Vertex>; using Coord = TCoord<Vertex>;
using Edge = _Segment<Vertex>; using Edge = _Segment<Vertex>;
// enum Corners {
// BOTTOM,
// LEFT,
// RIGHT,
// TOP,
// NUM_CORNERS
// };
mutable std::vector<double> corners_; mutable std::vector<double> corners_;
std::vector<Edge> emap_; std::vector<Edge> emap_;
@ -70,49 +71,9 @@ template<class RawShape> class EdgeCache {
void fetchCorners() const { void fetchCorners() const {
if(!corners_.empty()) return; if(!corners_.empty()) return;
// TODO Accuracy
corners_ = distances_; corners_ = distances_;
for(auto& d : corners_) { for(auto& d : corners_) d /= full_distance_;
d /= full_distance_;
}
// corners_ = std::vector<double>(NUM_CORNERS, 0.0);
// std::vector<unsigned> idx_ud(emap_.size(), 0);
// std::vector<unsigned> idx_lr(emap_.size(), 0);
// std::iota(idx_ud.begin(), idx_ud.end(), 0);
// std::iota(idx_lr.begin(), idx_lr.end(), 0);
// std::sort(idx_ud.begin(), idx_ud.end(),
// [this](unsigned idx1, unsigned idx2)
// {
// const Vertex& v1 = emap_[idx1].first();
// const Vertex& v2 = emap_[idx2].first();
// auto diff = getY(v1) - getY(v2);
// if(std::abs(diff) <= std::numeric_limits<Coord>::epsilon())
// return getX(v1) < getX(v2);
// return diff < 0;
// });
// std::sort(idx_lr.begin(), idx_lr.end(),
// [this](unsigned idx1, unsigned idx2)
// {
// const Vertex& v1 = emap_[idx1].first();
// const Vertex& v2 = emap_[idx2].first();
// auto diff = getX(v1) - getX(v2);
// if(std::abs(diff) <= std::numeric_limits<Coord>::epsilon())
// return getY(v1) < getY(v2);
// return diff < 0;
// });
// corners_[BOTTOM] = distances_[idx_ud.front()]/full_distance_;
// corners_[TOP] = distances_[idx_ud.back()]/full_distance_;
// corners_[LEFT] = distances_[idx_lr.front()]/full_distance_;
// corners_[RIGHT] = distances_[idx_lr.back()]/full_distance_;
} }
public: public:
@ -167,12 +128,6 @@ public:
inline double circumference() const BP2D_NOEXCEPT { return full_distance_; } inline double circumference() const BP2D_NOEXCEPT { return full_distance_; }
// inline double corner(Corners c) const BP2D_NOEXCEPT {
// assert(c < NUM_CORNERS);
// fetchCorners();
// return corners_[c];
// }
inline const std::vector<double>& corners() const BP2D_NOEXCEPT { inline const std::vector<double>& corners() const BP2D_NOEXCEPT {
fetchCorners(); fetchCorners();
return corners_; return corners_;
@ -400,7 +355,7 @@ public:
opt::StopCriteria stopcr; opt::StopCriteria stopcr;
stopcr.max_iterations = 1000; stopcr.max_iterations = 1000;
stopcr.stoplimit = 0.01; stopcr.stoplimit = 0.001;
stopcr.type = opt::StopLimitType::RELATIVE; stopcr.type = opt::StopLimitType::RELATIVE;
opt::TOptimizer<opt::Method::L_SIMPLEX> solver(stopcr); opt::TOptimizer<opt::Method::L_SIMPLEX> solver(stopcr);
@ -518,11 +473,37 @@ private:
void setInitialPosition(Item& item) { void setInitialPosition(Item& item) {
Box&& bb = item.boundingBox(); Box&& bb = item.boundingBox();
Vertex ci, cb;
Vertex ci = bb.minCorner(); switch(config_.starting_point) {
Vertex cb = bin_.minCorner(); case Config::Alignment::CENTER: {
ci = bb.center();
cb = bin_.center();
break;
}
case Config::Alignment::BOTTOM_LEFT: {
ci = bb.minCorner();
cb = bin_.minCorner();
break;
}
case Config::Alignment::BOTTOM_RIGHT: {
ci = {getX(bb.maxCorner()), getY(bb.minCorner())};
cb = {getX(bin_.maxCorner()), getY(bin_.minCorner())};
break;
}
case Config::Alignment::TOP_LEFT: {
ci = {getX(bb.minCorner()), getY(bb.maxCorner())};
cb = {getX(bin_.minCorner()), getY(bin_.maxCorner())};
break;
}
case Config::Alignment::TOP_RIGHT: {
ci = bb.maxCorner();
cb = bin_.maxCorner();
break;
}
}
auto&& d = cb - ci; auto d = cb - ci;
item.translate(d); item.translate(d);
} }

View File

@ -41,11 +41,24 @@ public:
struct Config { struct Config {
/** /**
* If true, the algorithm will try to place pair and driplets in all * If true, the algorithm will try to place pair and triplets in all
* possible order. * possible order. It will have a hugely negative impact on performance.
*/ */
bool try_reverse_order = true; bool try_reverse_order = true;
/**
* @brief try_pairs Whether to try pairs of items to pack. It will add
* a quadratic component to the complexity.
*/
bool try_pairs = true;
/**
* @brief Whether to try groups of 3 items to pack. This could be very
* slow for large number of items (>100) as it adds a cubic component
* to the complexity.
*/
bool try_triplets = false;
/** /**
* The initial fill proportion of the bin area that will be filled before * The initial fill proportion of the bin area that will be filled before
* trying items one by one, or pairs or triplets. * trying items one by one, or pairs or triplets.
@ -151,8 +164,8 @@ public:
return std::any_of(wrong_pairs.begin(), wrong_pairs.end(), return std::any_of(wrong_pairs.begin(), wrong_pairs.end(),
[&i1, &i2](const TPair& pair) [&i1, &i2](const TPair& pair)
{ {
Item& pi1 = std::get<0>(pair), pi2 = std::get<1>(pair); Item& pi1 = std::get<0>(pair), &pi2 = std::get<1>(pair);
Item& ri1 = i1, ri2 = i2; Item& ri1 = i1, &ri2 = i2;
return (&pi1 == &ri1 && &pi2 == &ri2) || return (&pi1 == &ri1 && &pi2 == &ri2) ||
(&pi1 == &ri2 && &pi2 == &ri1); (&pi1 == &ri2 && &pi2 == &ri1);
}); });
@ -172,7 +185,7 @@ public:
Item& pi1 = std::get<0>(tripl); Item& pi1 = std::get<0>(tripl);
Item& pi2 = std::get<1>(tripl); Item& pi2 = std::get<1>(tripl);
Item& pi3 = std::get<2>(tripl); Item& pi3 = std::get<2>(tripl);
Item& ri1 = i1, ri2 = i2, ri3 = i3; Item& ri1 = i1, &ri2 = i2, &ri3 = i3;
return (&pi1 == &ri1 && &pi2 == &ri2 && &pi3 == &ri3) || return (&pi1 == &ri1 && &pi2 == &ri2 && &pi3 == &ri3) ||
(&pi1 == &ri1 && &pi2 == &ri3 && &pi3 == &ri2) || (&pi1 == &ri1 && &pi2 == &ri3 && &pi3 == &ri2) ||
(&pi1 == &ri2 && &pi2 == &ri1 && &pi3 == &ri3) || (&pi1 == &ri2 && &pi2 == &ri1 && &pi3 == &ri3) ||
@ -348,6 +361,10 @@ public:
// Will be true if a succesfull pack can be made. // Will be true if a succesfull pack can be made.
bool ret = false; bool ret = false;
auto area = [](const ItemListIt& it) {
return it->get().area();
};
while (it != endit && !ret) { // drill down 1st level while (it != endit && !ret) { // drill down 1st level
// We need to determine in each iteration the largest, second // We need to determine in each iteration the largest, second
@ -361,7 +378,7 @@ public:
// Check if there is enough free area for the item and the two // Check if there is enough free area for the item and the two
// largest item // largest item
if(free_area - it->get().area() - area_of_two_largest > waste) if(free_area - area(it) - area_of_two_largest > waste)
break; break;
// Determine the area of the two smallest item. // Determine the area of the two smallest item.
@ -373,7 +390,7 @@ public:
double area_of_two_smallest = double area_of_two_smallest =
smallest.area() + second_smallest.area(); smallest.area() + second_smallest.area();
if(it->get().area() + area_of_two_smallest > free_area) { if(area(it) + area_of_two_smallest > free_area) {
it++; continue; it++; continue;
} }
@ -384,16 +401,18 @@ public:
it2 = not_packed.begin(); it2 = not_packed.begin();
double rem2_area = free_area - largest.area(); double rem2_area = free_area - largest.area();
double a2_sum = it->get().area() + it2->get().area(); double a2_sum = 0;
while(it2 != endit && !ret && while(it2 != endit && !ret &&
rem2_area - a2_sum <= waste) { // Drill down level 2 rem2_area - (a2_sum = area(it) + area(it2)) <= waste) {
// Drill down level 2
if(a2_sum != area(it) + area(it2)) throw -1;
if(it == it2 || check_pair(wrong_pairs, *it, *it2)) { if(it == it2 || check_pair(wrong_pairs, *it, *it2)) {
it2++; continue; it2++; continue;
} }
a2_sum = it->get().area() + it2->get().area();
if(a2_sum + smallest.area() > free_area) { if(a2_sum + smallest.area() > free_area) {
it2++; continue; it2++; continue;
} }
@ -429,14 +448,13 @@ public:
// The 'smallest' variable now could be identical with // The 'smallest' variable now could be identical with
// it2 but we don't bother with that // it2 but we don't bother with that
if(!can_pack2) { it2++; continue; }
it3 = not_packed.begin(); it3 = not_packed.begin();
double a3_sum = a2_sum + it3->get().area(); double a3_sum = 0;
while(it3 != endit && !ret && while(it3 != endit && !ret &&
free_area - a3_sum <= waste) { // 3rd level free_area - (a3_sum = a2_sum + area(it3)) <= waste) {
// 3rd level
if(it3 == it || it3 == it2 || if(it3 == it || it3 == it2 ||
check_triplet(wrong_triplets, *it, *it2, *it3)) check_triplet(wrong_triplets, *it, *it2, *it3))
@ -560,8 +578,11 @@ public:
if(do_parallel) dout() << "Parallel execution..." << "\n"; if(do_parallel) dout() << "Parallel execution..." << "\n";
bool do_pairs = config_.try_pairs;
bool do_triplets = config_.try_triplets;
// The DJD heuristic algorithm itself: // The DJD heuristic algorithm itself:
auto packjob = [INITIAL_FILL_AREA, bin_area, w, auto packjob = [INITIAL_FILL_AREA, bin_area, w, do_triplets, do_pairs,
&tryOneByOne, &tryOneByOne,
&tryGroupsOfTwo, &tryGroupsOfTwo,
&tryGroupsOfThree, &tryGroupsOfThree,
@ -573,7 +594,7 @@ public:
double waste = .0; double waste = .0;
bool lasttry = false; bool lasttry = false;
while(!not_packed.empty() ) { while(!not_packed.empty()) {
{// Fill the bin up to INITIAL_FILL_PROPORTION of its capacity {// Fill the bin up to INITIAL_FILL_PROPORTION of its capacity
auto it = not_packed.begin(); auto it = not_packed.begin();
@ -594,26 +615,25 @@ public:
// try pieses one by one // try pieses one by one
while(tryOneByOne(placer, not_packed, waste, free_area, while(tryOneByOne(placer, not_packed, waste, free_area,
filled_area)) { filled_area)) {
if(lasttry) std::cout << "Lasttry monopack" << std::endl;
waste = 0; lasttry = false; waste = 0; lasttry = false;
makeProgress(placer, idx, 1); makeProgress(placer, idx, 1);
} }
// try groups of 2 pieses // try groups of 2 pieses
while(tryGroupsOfTwo(placer, not_packed, waste, free_area, while(do_pairs &&
tryGroupsOfTwo(placer, not_packed, waste, free_area,
filled_area)) { filled_area)) {
if(lasttry) std::cout << "Lasttry bipack" << std::endl;
waste = 0; lasttry = false; waste = 0; lasttry = false;
makeProgress(placer, idx, 2); makeProgress(placer, idx, 2);
} }
// // try groups of 3 pieses // try groups of 3 pieses
// while(tryGroupsOfThree(placer, not_packed, waste, free_area, while(do_triplets &&
// filled_area)) { tryGroupsOfThree(placer, not_packed, waste, free_area,
// if(lasttry) std::cout << "Lasttry tripack" << std::endl; filled_area)) {
// waste = 0; lasttry = false; waste = 0; lasttry = false;
// makeProgress(placer, idx, 3); makeProgress(placer, idx, 3);
// } }
waste += w; waste += w;
if(!lasttry && waste > free_area) lasttry = true; if(!lasttry && waste > free_area) lasttry = true;

View File

@ -55,6 +55,18 @@ public:
this->progress_(--total); this->progress_(--total);
}; };
// Safety test: try to pack each item into an empty bin. If it fails
// then it should be removed from the not_packed list
{ auto it = store_.begin();
while (it != store_.end()) {
Placer p(bin);
if(!p.pack(*it)) {
auto itmp = it++;
store_.erase(itmp);
} else it++;
}
}
for(auto& item : store_ ) { for(auto& item : store_ ) {
bool was_packed = false; bool was_packed = false;
while(!was_packed) { while(!was_packed) {

View File

@ -374,6 +374,12 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
throw std::runtime_error(std::string("G-code export to ") + path + " failed\nIs the disk full?\n"); throw std::runtime_error(std::string("G-code export to ") + path + " failed\nIs the disk full?\n");
} }
fclose(file); fclose(file);
m_normal_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
if (m_silent_time_estimator_enabled)
m_silent_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
if (! this->m_placeholder_parser_failed_templates.empty()) { if (! this->m_placeholder_parser_failed_templates.empty()) {
// G-code export proceeded, but some of the PlaceholderParser substitutions failed. // G-code export proceeded, but some of the PlaceholderParser substitutions failed.
std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n"; std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n";
@ -403,10 +409,48 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
{ {
PROFILE_FUNC(); PROFILE_FUNC();
// resets time estimator // resets time estimators
m_time_estimator.reset(); m_normal_time_estimator.reset();
m_time_estimator.set_dialect(print.config.gcode_flavor); m_normal_time_estimator.set_dialect(print.config.gcode_flavor);
m_normal_time_estimator.set_acceleration(print.config.machine_max_acceleration_extruding.values[0]);
m_normal_time_estimator.set_retract_acceleration(print.config.machine_max_acceleration_retracting.values[0]);
m_normal_time_estimator.set_minimum_feedrate(print.config.machine_min_extruding_rate.values[0]);
m_normal_time_estimator.set_minimum_travel_feedrate(print.config.machine_min_travel_rate.values[0]);
m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, print.config.machine_max_acceleration_x.values[0]);
m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, print.config.machine_max_acceleration_y.values[0]);
m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, print.config.machine_max_acceleration_z.values[0]);
m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, print.config.machine_max_acceleration_e.values[0]);
m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, print.config.machine_max_feedrate_x.values[0]);
m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, print.config.machine_max_feedrate_y.values[0]);
m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, print.config.machine_max_feedrate_z.values[0]);
m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, print.config.machine_max_feedrate_e.values[0]);
m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, print.config.machine_max_jerk_x.values[0]);
m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, print.config.machine_max_jerk_y.values[0]);
m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, print.config.machine_max_jerk_z.values[0]);
m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, print.config.machine_max_jerk_e.values[0]);
m_silent_time_estimator_enabled = (print.config.gcode_flavor == gcfMarlin) && print.config.silent_mode && boost::starts_with(print.config.printer_model.value, "MK3");
if (m_silent_time_estimator_enabled)
{
m_silent_time_estimator.reset();
m_silent_time_estimator.set_dialect(print.config.gcode_flavor);
m_silent_time_estimator.set_acceleration(print.config.machine_max_acceleration_extruding.values[1]);
m_silent_time_estimator.set_retract_acceleration(print.config.machine_max_acceleration_retracting.values[1]);
m_silent_time_estimator.set_minimum_feedrate(print.config.machine_min_extruding_rate.values[1]);
m_silent_time_estimator.set_minimum_travel_feedrate(print.config.machine_min_travel_rate.values[1]);
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, print.config.machine_max_acceleration_x.values[1]);
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, print.config.machine_max_acceleration_y.values[1]);
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, print.config.machine_max_acceleration_z.values[1]);
m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, print.config.machine_max_acceleration_e.values[1]);
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, print.config.machine_max_feedrate_x.values[1]);
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, print.config.machine_max_feedrate_y.values[1]);
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, print.config.machine_max_feedrate_z.values[1]);
m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, print.config.machine_max_feedrate_e.values[1]);
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, print.config.machine_max_jerk_x.values[1]);
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, print.config.machine_max_jerk_y.values[1]);
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, print.config.machine_max_jerk_z.values[1]);
m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, print.config.machine_max_jerk_e.values[1]);
}
// resets analyzer // resets analyzer
m_analyzer.reset(); m_analyzer.reset();
m_enable_analyzer = preview_data != nullptr; m_enable_analyzer = preview_data != nullptr;
@ -569,6 +613,9 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
m_cooling_buffer->set_current_extruder(initial_extruder_id); m_cooling_buffer->set_current_extruder(initial_extruder_id);
// Emit machine envelope limits for the Marlin firmware.
this->print_machine_envelope(file, print);
// Disable fan. // Disable fan.
if (! print.config.cooling.get_at(initial_extruder_id) || print.config.disable_fan_first_layers.get_at(initial_extruder_id)) if (! print.config.cooling.get_at(initial_extruder_id) || print.config.disable_fan_first_layers.get_at(initial_extruder_id))
_write(file, m_writer.set_fan(0, true)); _write(file, m_writer.set_fan(0, true));
@ -806,7 +853,9 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
_write(file, m_writer.postamble()); _write(file, m_writer.postamble());
// calculates estimated printing time // calculates estimated printing time
m_time_estimator.calculate_time(); m_normal_time_estimator.calculate_time();
if (m_silent_time_estimator_enabled)
m_silent_time_estimator.calculate_time();
// Get filament stats. // Get filament stats.
print.filament_stats.clear(); print.filament_stats.clear();
@ -814,13 +863,14 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
print.total_extruded_volume = 0.; print.total_extruded_volume = 0.;
print.total_weight = 0.; print.total_weight = 0.;
print.total_cost = 0.; print.total_cost = 0.;
print.estimated_print_time = m_time_estimator.get_time_hms(); print.estimated_normal_print_time = m_normal_time_estimator.get_time_dhms();
print.estimated_silent_print_time = m_silent_time_estimator_enabled ? m_silent_time_estimator.get_time_dhms() : "N/A";
for (const Extruder &extruder : m_writer.extruders()) { for (const Extruder &extruder : m_writer.extruders()) {
double used_filament = extruder.used_filament(); double used_filament = extruder.used_filament();
double extruded_volume = extruder.extruded_volume(); double extruded_volume = extruder.extruded_volume();
double filament_weight = extruded_volume * extruder.filament_density() * 0.001; double filament_weight = extruded_volume * extruder.filament_density() * 0.001;
double filament_cost = filament_weight * extruder.filament_cost() * 0.001; double filament_cost = filament_weight * extruder.filament_cost() * 0.001;
print.filament_stats.insert(std::pair<size_t,float>(extruder.id(), used_filament)); print.filament_stats.insert(std::pair<size_t, float>(extruder.id(), (float)used_filament));
_write_format(file, "; filament used = %.1lfmm (%.1lfcm3)\n", used_filament, extruded_volume * 0.001); _write_format(file, "; filament used = %.1lfmm (%.1lfcm3)\n", used_filament, extruded_volume * 0.001);
if (filament_weight > 0.) { if (filament_weight > 0.) {
print.total_weight = print.total_weight + filament_weight; print.total_weight = print.total_weight + filament_weight;
@ -834,7 +884,9 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
print.total_extruded_volume = print.total_extruded_volume + extruded_volume; print.total_extruded_volume = print.total_extruded_volume + extruded_volume;
} }
_write_format(file, "; total filament cost = %.1lf\n", print.total_cost); _write_format(file, "; total filament cost = %.1lf\n", print.total_cost);
_write_format(file, "; estimated printing time = %s\n", m_time_estimator.get_time_hms().c_str()); _write_format(file, "; estimated printing time (normal mode) = %s\n", m_normal_time_estimator.get_time_dhms().c_str());
if (m_silent_time_estimator_enabled)
_write_format(file, "; estimated printing time (silent mode) = %s\n", m_silent_time_estimator.get_time_dhms().c_str());
// Append full config. // Append full config.
_write(file, "\n"); _write(file, "\n");
@ -919,6 +971,35 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc
return temp_set_by_gcode; return temp_set_by_gcode;
} }
// Print the machine envelope G-code for the Marlin firmware based on the "machine_max_xxx" parameters.
// Do not process this piece of G-code by the time estimator, it already knows the values through another sources.
void GCode::print_machine_envelope(FILE *file, Print &print)
{
if (print.config.gcode_flavor.value == gcfMarlin) {
fprintf(file, "M201 X%d Y%d Z%d E%d ; sets maximum accelerations, mm/sec^2\n",
int(print.config.machine_max_acceleration_x.values.front() + 0.5),
int(print.config.machine_max_acceleration_y.values.front() + 0.5),
int(print.config.machine_max_acceleration_z.values.front() + 0.5),
int(print.config.machine_max_acceleration_e.values.front() + 0.5));
fprintf(file, "M203 X%d Y%d Z%d E%d ; sets maximum feedrates, mm/sec\n",
int(print.config.machine_max_feedrate_x.values.front() + 0.5),
int(print.config.machine_max_feedrate_y.values.front() + 0.5),
int(print.config.machine_max_feedrate_z.values.front() + 0.5),
int(print.config.machine_max_feedrate_e.values.front() + 0.5));
fprintf(file, "M204 S%d T%d ; sets acceleration (S) and retract acceleration (T), mm/sec^2\n",
int(print.config.machine_max_acceleration_extruding.values.front() + 0.5),
int(print.config.machine_max_acceleration_retracting.values.front() + 0.5));
fprintf(file, "M205 X%.2lf Y%.2lf Z%.2lf E%.2lf ; sets the jerk limits, mm/sec\n",
print.config.machine_max_jerk_x.values.front(),
print.config.machine_max_jerk_y.values.front(),
print.config.machine_max_jerk_z.values.front(),
print.config.machine_max_jerk_e.values.front());
fprintf(file, "M205 S%d T%d ; sets the minimum extruding and travel feed rate, mm/sec\n",
int(print.config.machine_min_extruding_rate.values.front() + 0.5),
int(print.config.machine_min_travel_rate.values.front() + 0.5));
}
}
// Write 1st layer bed temperatures into the G-code. // Write 1st layer bed temperatures into the G-code.
// Only do that if the start G-code does not already contain any M-code controlling an extruder temperature. // Only do that if the start G-code does not already contain any M-code controlling an extruder temperature.
// M140 - Set Extruder Temperature // M140 - Set Extruder Temperature
@ -1406,7 +1487,7 @@ void GCode::process_layer(
if (m_pressure_equalizer) if (m_pressure_equalizer)
gcode = m_pressure_equalizer->process(gcode.c_str(), false); gcode = m_pressure_equalizer->process(gcode.c_str(), false);
// printf("G-code after filter:\n%s\n", out.c_str()); // printf("G-code after filter:\n%s\n", out.c_str());
_write(file, gcode); _write(file, gcode);
} }
@ -2073,7 +2154,9 @@ void GCode::_write(FILE* file, const char *what)
// writes string to file // writes string to file
fwrite(gcode, 1, ::strlen(gcode), file); fwrite(gcode, 1, ::strlen(gcode), file);
// updates time estimator and gcode lines vector // updates time estimator and gcode lines vector
m_time_estimator.add_gcode_block(gcode); m_normal_time_estimator.add_gcode_block(gcode);
if (m_silent_time_estimator_enabled)
m_silent_time_estimator.add_gcode_block(gcode);
} }
} }

View File

@ -133,6 +133,9 @@ public:
m_last_height(GCodeAnalyzer::Default_Height), m_last_height(GCodeAnalyzer::Default_Height),
m_brim_done(false), m_brim_done(false),
m_second_layer_things_done(false), m_second_layer_things_done(false),
m_normal_time_estimator(GCodeTimeEstimator::Normal),
m_silent_time_estimator(GCodeTimeEstimator::Silent),
m_silent_time_estimator_enabled(false),
m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max())) m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max()))
{} {}
~GCode() {} ~GCode() {}
@ -303,8 +306,10 @@ protected:
// Index of a last object copy extruded. // Index of a last object copy extruded.
std::pair<const PrintObject*, Point> m_last_obj_copy; std::pair<const PrintObject*, Point> m_last_obj_copy;
// Time estimator // Time estimators
GCodeTimeEstimator m_time_estimator; GCodeTimeEstimator m_normal_time_estimator;
GCodeTimeEstimator m_silent_time_estimator;
bool m_silent_time_estimator_enabled;
// Analyzer // Analyzer
GCodeAnalyzer m_analyzer; GCodeAnalyzer m_analyzer;
@ -322,6 +327,7 @@ protected:
void _write_format(FILE* file, const char* format, ...); void _write_format(FILE* file, const char* format, ...);
std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1); std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1);
void print_machine_envelope(FILE *file, Print &print);
void _print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); void _print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
void _print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); void _print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
// this flag triggers first layer speeds // this flag triggers first layer speeds

View File

@ -4,15 +4,20 @@
#include <Shiny/Shiny.h> #include <Shiny/Shiny.h>
#include <boost/nowide/fstream.hpp>
#include <boost/nowide/cstdio.hpp>
#include <boost/algorithm/string/predicate.hpp>
static const float MMMIN_TO_MMSEC = 1.0f / 60.0f; static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
static const float MILLISEC_TO_SEC = 0.001f; static const float MILLISEC_TO_SEC = 0.001f;
static const float INCHES_TO_MM = 25.4f; static const float INCHES_TO_MM = 25.4f;
static const float DEFAULT_FEEDRATE = 1500.0f; // from Prusa Firmware (Marlin_main.cpp) static const float DEFAULT_FEEDRATE = 1500.0f; // from Prusa Firmware (Marlin_main.cpp)
static const float DEFAULT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2 static const float DEFAULT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
static const float DEFAULT_RETRACT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2 static const float DEFAULT_RETRACT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
static const float DEFAULT_AXIS_MAX_FEEDRATE[] = { 500.0f, 500.0f, 12.0f, 120.0f }; // Prusa Firmware 1_75mm_MK2 static const float DEFAULT_AXIS_MAX_FEEDRATE[] = { 500.0f, 500.0f, 12.0f, 120.0f }; // Prusa Firmware 1_75mm_MK2
static const float DEFAULT_AXIS_MAX_ACCELERATION[] = { 9000.0f, 9000.0f, 500.0f, 10000.0f }; // Prusa Firmware 1_75mm_MK2 static const float DEFAULT_AXIS_MAX_ACCELERATION[] = { 9000.0f, 9000.0f, 500.0f, 10000.0f }; // Prusa Firmware 1_75mm_MK2
static const float DEFAULT_AXIS_MAX_JERK[] = { 10.0f, 10.0f, 0.2f, 2.5f }; // from Prusa Firmware (Configuration.h) static const float DEFAULT_AXIS_MAX_JERK[] = { 10.0f, 10.0f, 0.4f, 2.5f }; // from Prusa Firmware (Configuration.h)
static const float DEFAULT_MINIMUM_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h) static const float DEFAULT_MINIMUM_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
static const float DEFAULT_MINIMUM_TRAVEL_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h) static const float DEFAULT_MINIMUM_TRAVEL_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
static const float DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE = 1.0f; // 100 percent static const float DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE = 1.0f; // 100 percent
@ -73,6 +78,11 @@ namespace Slic3r {
return ::sqrt(value); return ::sqrt(value);
} }
GCodeTimeEstimator::Block::Block()
: st_synchronized(false)
{
}
float GCodeTimeEstimator::Block::move_length() const float GCodeTimeEstimator::Block::move_length() const
{ {
float length = ::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z])); float length = ::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
@ -159,63 +169,13 @@ namespace Slic3r {
} }
#endif // ENABLE_MOVE_STATS #endif // ENABLE_MOVE_STATS
GCodeTimeEstimator::GCodeTimeEstimator() GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
: _mode(mode)
{ {
reset(); reset();
set_default(); set_default();
} }
void GCodeTimeEstimator::calculate_time_from_text(const std::string& gcode)
{
reset();
_parser.parse_buffer(gcode,
[this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
{ this->_process_gcode_line(reader, line); });
_calculate_time();
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
_reset_blocks();
_reset();
}
void GCodeTimeEstimator::calculate_time_from_file(const std::string& file)
{
reset();
_parser.parse_file(file, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2));
_calculate_time();
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
_reset_blocks();
_reset();
}
void GCodeTimeEstimator::calculate_time_from_lines(const std::vector<std::string>& gcode_lines)
{
reset();
auto action = [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
{ this->_process_gcode_line(reader, line); };
for (const std::string& line : gcode_lines)
_parser.parse_line(line, action);
_calculate_time();
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
_reset_blocks();
_reset();
}
void GCodeTimeEstimator::add_gcode_line(const std::string& gcode_line) void GCodeTimeEstimator::add_gcode_line(const std::string& gcode_line)
{ {
PROFILE_FUNC(); PROFILE_FUNC();
@ -239,14 +199,167 @@ namespace Slic3r {
void GCodeTimeEstimator::calculate_time() void GCodeTimeEstimator::calculate_time()
{ {
PROFILE_FUNC(); PROFILE_FUNC();
_reset_time();
_set_blocks_st_synchronize(false);
_calculate_time(); _calculate_time();
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
_log_moves_stats(); _log_moves_stats();
#endif // ENABLE_MOVE_STATS #endif // ENABLE_MOVE_STATS
}
_reset_blocks(); void GCodeTimeEstimator::calculate_time_from_text(const std::string& gcode)
_reset(); {
reset();
_parser.parse_buffer(gcode,
[this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
{ this->_process_gcode_line(reader, line); });
_calculate_time();
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
}
void GCodeTimeEstimator::calculate_time_from_file(const std::string& file)
{
reset();
_parser.parse_file(file, boost::bind(&GCodeTimeEstimator::_process_gcode_line, this, _1, _2));
_calculate_time();
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
}
void GCodeTimeEstimator::calculate_time_from_lines(const std::vector<std::string>& gcode_lines)
{
reset();
auto action = [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
{ this->_process_gcode_line(reader, line); };
for (const std::string& line : gcode_lines)
_parser.parse_line(line, action);
_calculate_time();
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
}
bool GCodeTimeEstimator::post_process_remaining_times(const std::string& filename, float interval)
{
boost::nowide::ifstream in(filename);
if (!in.good())
throw std::runtime_error(std::string("Remaining times export failed.\nCannot open file for reading.\n"));
std::string path_tmp = filename + ".times";
FILE* out = boost::nowide::fopen(path_tmp.c_str(), "wb");
if (out == nullptr)
throw std::runtime_error(std::string("Remaining times export failed.\nCannot open file for writing.\n"));
std::string time_mask;
switch (_mode)
{
default:
case Normal:
{
time_mask = "M73 P%s R%s\n";
break;
}
case Silent:
{
time_mask = "M73 Q%s S%s\n";
break;
}
}
unsigned int g1_lines_count = 0;
float last_recorded_time = 0.0f;
std::string gcode_line;
// buffer line to export only when greater than 64K to reduce writing calls
std::string export_line;
char time_line[64];
while (std::getline(in, gcode_line))
{
if (!in.good())
{
fclose(out);
throw std::runtime_error(std::string("Remaining times export failed.\nError while reading from file.\n"));
}
gcode_line += "\n";
// add remaining time lines where needed
_parser.parse_line(gcode_line,
[this, &g1_lines_count, &last_recorded_time, &time_line, &gcode_line, time_mask, interval](GCodeReader& reader, const GCodeReader::GCodeLine& line)
{
if (line.cmd_is("G1"))
{
++g1_lines_count;
if (!line.has_e())
return;
G1LineIdToBlockIdMap::const_iterator it = _g1_line_ids.find(g1_lines_count);
if ((it != _g1_line_ids.end()) && (it->second < (unsigned int)_blocks.size()))
{
const Block& block = _blocks[it->second];
if (block.elapsed_time != -1.0f)
{
float block_remaining_time = _time - block.elapsed_time;
if (std::abs(last_recorded_time - block_remaining_time) > interval)
{
sprintf(time_line, time_mask.c_str(), std::to_string((int)(100.0f * block.elapsed_time / _time)).c_str(), _get_time_minutes(block_remaining_time).c_str());
gcode_line += time_line;
last_recorded_time = block_remaining_time;
}
}
}
}
});
export_line += gcode_line;
if (export_line.length() > 65535)
{
fwrite((const void*)export_line.c_str(), 1, export_line.length(), out);
if (ferror(out))
{
in.close();
fclose(out);
boost::nowide::remove(path_tmp.c_str());
throw std::runtime_error(std::string("Remaining times export failed.\nIs the disk full?\n"));
}
export_line.clear();
}
}
if (export_line.length() > 0)
{
fwrite((const void*)export_line.c_str(), 1, export_line.length(), out);
if (ferror(out))
{
in.close();
fclose(out);
boost::nowide::remove(path_tmp.c_str());
throw std::runtime_error(std::string("Remaining times export failed.\nIs the disk full?\n"));
}
}
fclose(out);
in.close();
boost::nowide::remove(filename.c_str());
if (boost::nowide::rename(path_tmp.c_str(), filename.c_str()) != 0)
throw std::runtime_error(std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + filename + '\n' +
"Is " + path_tmp + " locked?" + '\n');
return true;
} }
void GCodeTimeEstimator::set_axis_position(EAxis axis, float position) void GCodeTimeEstimator::set_axis_position(EAxis axis, float position)
@ -389,6 +502,21 @@ namespace Slic3r {
return _state.e_local_positioning_type; return _state.e_local_positioning_type;
} }
int GCodeTimeEstimator::get_g1_line_id() const
{
return _state.g1_line_id;
}
void GCodeTimeEstimator::increment_g1_line_id()
{
++_state.g1_line_id;
}
void GCodeTimeEstimator::reset_g1_line_id()
{
_state.g1_line_id = 0;
}
void GCodeTimeEstimator::add_additional_time(float timeSec) void GCodeTimeEstimator::add_additional_time(float timeSec)
{ {
_state.additional_time += timeSec; _state.additional_time += timeSec;
@ -417,7 +545,7 @@ namespace Slic3r {
set_minimum_feedrate(DEFAULT_MINIMUM_FEEDRATE); set_minimum_feedrate(DEFAULT_MINIMUM_FEEDRATE);
set_minimum_travel_feedrate(DEFAULT_MINIMUM_TRAVEL_FEEDRATE); set_minimum_travel_feedrate(DEFAULT_MINIMUM_TRAVEL_FEEDRATE);
set_extrude_factor_override_percentage(DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE); set_extrude_factor_override_percentage(DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE);
for (unsigned char a = X; a < Num_Axis; ++a) for (unsigned char a = X; a < Num_Axis; ++a)
{ {
EAxis axis = (EAxis)a; EAxis axis = (EAxis)a;
@ -429,7 +557,7 @@ namespace Slic3r {
void GCodeTimeEstimator::reset() void GCodeTimeEstimator::reset()
{ {
_time = 0.0f; _reset_time();
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
_moves_stats.clear(); _moves_stats.clear();
#endif // ENABLE_MOVE_STATS #endif // ENABLE_MOVE_STATS
@ -442,23 +570,14 @@ namespace Slic3r {
return _time; return _time;
} }
std::string GCodeTimeEstimator::get_time_hms() const std::string GCodeTimeEstimator::get_time_dhms() const
{ {
float timeinsecs = get_time(); return _get_time_dhms(get_time());
int hours = (int)(timeinsecs / 3600.0f); }
timeinsecs -= (float)hours * 3600.0f;
int minutes = (int)(timeinsecs / 60.0f);
timeinsecs -= (float)minutes * 60.0f;
char buffer[64]; std::string GCodeTimeEstimator::get_time_minutes() const
if (hours > 0) {
::sprintf(buffer, "%dh %dm %ds", hours, minutes, (int)timeinsecs); return _get_time_minutes(get_time());
else if (minutes > 0)
::sprintf(buffer, "%dm %ds", minutes, (int)timeinsecs);
else
::sprintf(buffer, "%ds", (int)timeinsecs);
return buffer;
} }
void GCodeTimeEstimator::_reset() void GCodeTimeEstimator::_reset()
@ -471,6 +590,14 @@ namespace Slic3r {
set_axis_position(Z, 0.0f); set_axis_position(Z, 0.0f);
set_additional_time(0.0f); set_additional_time(0.0f);
reset_g1_line_id();
_g1_line_ids.clear();
}
void GCodeTimeEstimator::_reset_time()
{
_time = 0.0f;
} }
void GCodeTimeEstimator::_reset_blocks() void GCodeTimeEstimator::_reset_blocks()
@ -478,6 +605,14 @@ namespace Slic3r {
_blocks.clear(); _blocks.clear();
} }
void GCodeTimeEstimator::_set_blocks_st_synchronize(bool state)
{
for (Block& block : _blocks)
{
block.st_synchronized = state;
}
}
void GCodeTimeEstimator::_calculate_time() void GCodeTimeEstimator::_calculate_time()
{ {
_forward_pass(); _forward_pass();
@ -486,14 +621,18 @@ namespace Slic3r {
_time += get_additional_time(); _time += get_additional_time();
for (const Block& block : _blocks) for (Block& block : _blocks)
{ {
if (block.st_synchronized)
continue;
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
float block_time = 0.0f; float block_time = 0.0f;
block_time += block.acceleration_time(); block_time += block.acceleration_time();
block_time += block.cruise_time(); block_time += block.cruise_time();
block_time += block.deceleration_time(); block_time += block.deceleration_time();
_time += block_time; _time += block_time;
block.elapsed_time = _time;
MovesStatsMap::iterator it = _moves_stats.find(block.move_type); MovesStatsMap::iterator it = _moves_stats.find(block.move_type);
if (it == _moves_stats.end()) if (it == _moves_stats.end())
@ -505,6 +644,7 @@ namespace Slic3r {
_time += block.acceleration_time(); _time += block.acceleration_time();
_time += block.cruise_time(); _time += block.cruise_time();
_time += block.deceleration_time(); _time += block.deceleration_time();
block.elapsed_time = _time;
#endif // ENABLE_MOVE_STATS #endif // ENABLE_MOVE_STATS
} }
} }
@ -642,6 +782,8 @@ namespace Slic3r {
void GCodeTimeEstimator::_processG1(const GCodeReader::GCodeLine& line) void GCodeTimeEstimator::_processG1(const GCodeReader::GCodeLine& line)
{ {
increment_g1_line_id();
// updates axes positions from line // updates axes positions from line
EUnits units = get_units(); EUnits units = get_units();
float new_pos[Num_Axis]; float new_pos[Num_Axis];
@ -690,13 +832,16 @@ namespace Slic3r {
if (_curr.abs_axis_feedrate[a] > 0.0f) if (_curr.abs_axis_feedrate[a] > 0.0f)
min_feedrate_factor = std::min(min_feedrate_factor, get_axis_max_feedrate((EAxis)a) / _curr.abs_axis_feedrate[a]); min_feedrate_factor = std::min(min_feedrate_factor, get_axis_max_feedrate((EAxis)a) / _curr.abs_axis_feedrate[a]);
} }
block.feedrate.cruise = min_feedrate_factor * _curr.feedrate; block.feedrate.cruise = min_feedrate_factor * _curr.feedrate;
for (unsigned char a = X; a < Num_Axis; ++a) if (min_feedrate_factor < 1.0f)
{ {
_curr.axis_feedrate[a] *= min_feedrate_factor; for (unsigned char a = X; a < Num_Axis; ++a)
_curr.abs_axis_feedrate[a] *= min_feedrate_factor; {
_curr.axis_feedrate[a] *= min_feedrate_factor;
_curr.abs_axis_feedrate[a] *= min_feedrate_factor;
}
} }
// calculates block acceleration // calculates block acceleration
@ -829,6 +974,7 @@ namespace Slic3r {
// adds block to blocks list // adds block to blocks list
_blocks.emplace_back(block); _blocks.emplace_back(block);
_g1_line_ids.insert(G1LineIdToBlockIdMap::value_type(get_g1_line_id(), (unsigned int)_blocks.size() - 1));
} }
void GCodeTimeEstimator::_processG4(const GCodeReader::GCodeLine& line) void GCodeTimeEstimator::_processG4(const GCodeReader::GCodeLine& line)
@ -1043,7 +1189,7 @@ namespace Slic3r {
void GCodeTimeEstimator::_simulate_st_synchronize() void GCodeTimeEstimator::_simulate_st_synchronize()
{ {
_calculate_time(); _calculate_time();
_reset_blocks(); _set_blocks_st_synchronize(true);
} }
void GCodeTimeEstimator::_forward_pass() void GCodeTimeEstimator::_forward_pass()
@ -1051,7 +1197,10 @@ namespace Slic3r {
if (_blocks.size() > 1) if (_blocks.size() > 1)
{ {
for (unsigned int i = 0; i < (unsigned int)_blocks.size() - 1; ++i) for (unsigned int i = 0; i < (unsigned int)_blocks.size() - 1; ++i)
{ {
if (_blocks[i].st_synchronized || _blocks[i + 1].st_synchronized)
continue;
_planner_forward_pass_kernel(_blocks[i], _blocks[i + 1]); _planner_forward_pass_kernel(_blocks[i], _blocks[i + 1]);
} }
} }
@ -1063,6 +1212,9 @@ namespace Slic3r {
{ {
for (int i = (int)_blocks.size() - 1; i >= 1; --i) for (int i = (int)_blocks.size() - 1; i >= 1; --i)
{ {
if (_blocks[i - 1].st_synchronized || _blocks[i].st_synchronized)
continue;
_planner_reverse_pass_kernel(_blocks[i - 1], _blocks[i]); _planner_reverse_pass_kernel(_blocks[i - 1], _blocks[i]);
} }
} }
@ -1115,6 +1267,9 @@ namespace Slic3r {
for (Block& b : _blocks) for (Block& b : _blocks)
{ {
if (b.st_synchronized)
continue;
curr = next; curr = next;
next = &b; next = &b;
@ -1144,6 +1299,33 @@ namespace Slic3r {
} }
} }
std::string GCodeTimeEstimator::_get_time_dhms(float time_in_secs)
{
int days = (int)(time_in_secs / 86400.0f);
time_in_secs -= (float)days * 86400.0f;
int hours = (int)(time_in_secs / 3600.0f);
time_in_secs -= (float)hours * 3600.0f;
int minutes = (int)(time_in_secs / 60.0f);
time_in_secs -= (float)minutes * 60.0f;
char buffer[64];
if (days > 0)
::sprintf(buffer, "%dd %dh %dm %ds", days, hours, minutes, (int)time_in_secs);
else if (hours > 0)
::sprintf(buffer, "%dh %dm %ds", hours, minutes, (int)time_in_secs);
else if (minutes > 0)
::sprintf(buffer, "%dm %ds", minutes, (int)time_in_secs);
else
::sprintf(buffer, "%ds", (int)time_in_secs);
return buffer;
}
std::string GCodeTimeEstimator::_get_time_minutes(float time_in_secs)
{
return std::to_string((int)(::roundf(time_in_secs / 60.0f)));
}
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
void GCodeTimeEstimator::_log_moves_stats() const void GCodeTimeEstimator::_log_moves_stats() const
{ {

View File

@ -17,6 +17,12 @@ namespace Slic3r {
class GCodeTimeEstimator class GCodeTimeEstimator
{ {
public: public:
enum EMode : unsigned char
{
Normal,
Silent
};
enum EUnits : unsigned char enum EUnits : unsigned char
{ {
Millimeters, Millimeters,
@ -70,7 +76,8 @@ namespace Slic3r {
float additional_time; // s float additional_time; // s
float minimum_feedrate; // mm/s float minimum_feedrate; // mm/s
float minimum_travel_feedrate; // mm/s float minimum_travel_feedrate; // mm/s
float extrude_factor_override_percentage; float extrude_factor_override_percentage;
unsigned int g1_line_id;
}; };
public: public:
@ -121,7 +128,6 @@ namespace Slic3r {
bool nominal_length; bool nominal_length;
}; };
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
EMoveType move_type; EMoveType move_type;
#endif // ENABLE_MOVE_STATS #endif // ENABLE_MOVE_STATS
@ -134,6 +140,11 @@ namespace Slic3r {
FeedrateProfile feedrate; FeedrateProfile feedrate;
Trapezoid trapezoid; Trapezoid trapezoid;
float elapsed_time;
bool st_synchronized;
Block();
// Returns the length of the move covered by this block, in mm // Returns the length of the move covered by this block, in mm
float move_length() const; float move_length() const;
@ -187,19 +198,34 @@ namespace Slic3r {
typedef std::map<Block::EMoveType, MoveStats> MovesStatsMap; typedef std::map<Block::EMoveType, MoveStats> MovesStatsMap;
#endif // ENABLE_MOVE_STATS #endif // ENABLE_MOVE_STATS
typedef std::map<unsigned int, unsigned int> G1LineIdToBlockIdMap;
private: private:
EMode _mode;
GCodeReader _parser; GCodeReader _parser;
State _state; State _state;
Feedrates _curr; Feedrates _curr;
Feedrates _prev; Feedrates _prev;
BlocksList _blocks; BlocksList _blocks;
// Map between g1 line id and blocks id, used to speed up export of remaining times
G1LineIdToBlockIdMap _g1_line_ids;
float _time; // s float _time; // s
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
MovesStatsMap _moves_stats; MovesStatsMap _moves_stats;
#endif // ENABLE_MOVE_STATS #endif // ENABLE_MOVE_STATS
public: public:
GCodeTimeEstimator(); explicit GCodeTimeEstimator(EMode mode);
// Adds the given gcode line
void add_gcode_line(const std::string& gcode_line);
void add_gcode_block(const char *ptr);
void add_gcode_block(const std::string &str) { this->add_gcode_block(str.c_str()); }
// Calculates the time estimate from the gcode lines added using add_gcode_line() or add_gcode_block()
void calculate_time();
// Calculates the time estimate from the given gcode in string format // Calculates the time estimate from the given gcode in string format
void calculate_time_from_text(const std::string& gcode); void calculate_time_from_text(const std::string& gcode);
@ -210,14 +236,12 @@ namespace Slic3r {
// Calculates the time estimate from the gcode contained in given list of gcode lines // Calculates the time estimate from the gcode contained in given list of gcode lines
void calculate_time_from_lines(const std::vector<std::string>& gcode_lines); void calculate_time_from_lines(const std::vector<std::string>& gcode_lines);
// Adds the given gcode line // Process the gcode contained in the file with the given filename,
void add_gcode_line(const std::string& gcode_line); // placing in it new lines (M73) containing the remaining time, at the given interval in seconds
// and saving the result back in the same file
void add_gcode_block(const char *ptr); // This time estimator should have been already used to calculate the time estimate for the gcode
void add_gcode_block(const std::string &str) { this->add_gcode_block(str.c_str()); } // contained in the given file before to call this method
bool post_process_remaining_times(const std::string& filename, float interval_sec);
// Calculates the time estimate from the gcode lines added using add_gcode_line()
void calculate_time();
// Set current position on the given axis with the given value // Set current position on the given axis with the given value
void set_axis_position(EAxis axis, float position); void set_axis_position(EAxis axis, float position);
@ -263,6 +287,10 @@ namespace Slic3r {
void set_e_local_positioning_type(EPositioningType type); void set_e_local_positioning_type(EPositioningType type);
EPositioningType get_e_local_positioning_type() const; EPositioningType get_e_local_positioning_type() const;
int get_g1_line_id() const;
void increment_g1_line_id();
void reset_g1_line_id();
void add_additional_time(float timeSec); void add_additional_time(float timeSec);
void set_additional_time(float timeSec); void set_additional_time(float timeSec);
float get_additional_time() const; float get_additional_time() const;
@ -275,13 +303,19 @@ namespace Slic3r {
// Returns the estimated time, in seconds // Returns the estimated time, in seconds
float get_time() const; float get_time() const;
// Returns the estimated time, in format HHh MMm SSs // Returns the estimated time, in format DDd HHh MMm SSs
std::string get_time_hms() const; std::string get_time_dhms() const;
// Returns the estimated time, in minutes (integer)
std::string get_time_minutes() const;
private: private:
void _reset(); void _reset();
void _reset_time();
void _reset_blocks(); void _reset_blocks();
void _set_blocks_st_synchronize(bool state);
// Calculates the time estimate // Calculates the time estimate
void _calculate_time(); void _calculate_time();
@ -353,6 +387,12 @@ namespace Slic3r {
void _recalculate_trapezoids(); void _recalculate_trapezoids();
// Returns the given time is seconds in format DDd HHh MMm SSs
static std::string _get_time_dhms(float time_in_secs);
// Returns the given, in minutes (integer)
static std::string _get_time_minutes(float time_in_secs);
#if ENABLE_MOVE_STATS #if ENABLE_MOVE_STATS
void _log_moves_stats() const; void _log_moves_stats() const;
#endif // ENABLE_MOVE_STATS #endif // ENABLE_MOVE_STATS

View File

@ -19,7 +19,6 @@
#include <boost/nowide/iostream.hpp> #include <boost/nowide/iostream.hpp>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
// #include <benchmark.h>
#include "SVG.hpp" #include "SVG.hpp"
#include <Eigen/Dense> #include <Eigen/Dense>
@ -309,7 +308,7 @@ namespace arr {
using namespace libnest2d; using namespace libnest2d;
std::string toString(const Model& model) { std::string toString(const Model& model, bool holes = true) {
std::stringstream ss; std::stringstream ss;
ss << "{\n"; ss << "{\n";
@ -348,17 +347,17 @@ std::string toString(const Model& model) {
// Holes: // Holes:
ss << "\t\t{\n"; ss << "\t\t{\n";
// for(auto h : expoly.holes) { if(holes) for(auto h : expoly.holes) {
// ss << "\t\t\t{\n"; ss << "\t\t\t{\n";
// for(auto v : h.points) ss << "\t\t\t\t{" for(auto v : h.points) ss << "\t\t\t\t{"
// << v.x << ", " << v.x << ", "
// << v.y << "},\n"; << v.y << "},\n";
// { {
// auto v = h.points.front(); auto v = h.points.front();
// ss << "\t\t\t\t{" << v.x << ", " << v.y << "},\n"; ss << "\t\t\t\t{" << v.x << ", " << v.y << "},\n";
// } }
// ss << "\t\t\t},\n"; ss << "\t\t\t},\n";
// } }
ss << "\t\t},\n"; ss << "\t\t},\n";
ss << "\t},\n"; ss << "\t},\n";
@ -477,58 +476,21 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
// Create the arranger config // Create the arranger config
auto min_obj_distance = static_cast<Coord>(dist/SCALING_FACTOR); auto min_obj_distance = static_cast<Coord>(dist/SCALING_FACTOR);
// Benchmark bench;
// std::cout << "Creating model siluett..." << std::endl;
// bench.start();
// Get the 2D projected shapes with their 3D model instance pointers // Get the 2D projected shapes with their 3D model instance pointers
auto shapemap = arr::projectModelFromTop(model); auto shapemap = arr::projectModelFromTop(model);
// bench.stop();
// std::cout << "Model siluett created in " << bench.getElapsedSec()
// << " seconds. " << "Min object distance = " << min_obj_distance << std::endl;
// std::cout << "{" << std::endl;
// std::for_each(shapemap.begin(), shapemap.end(),
// [] (ShapeData2D::value_type& it)
// {
// std::cout << "\t{" << std::endl;
// Item& item = it.second;
// for(auto& v : item) {
// std::cout << "\t\t" << "{" << getX(v)
// << ", " << getY(v) << "},\n";
// }
// std::cout << "\t}," << std::endl;
// });
// std::cout << "}" << std::endl;
// return true;
bool hasbin = bb != nullptr && bb->defined; bool hasbin = bb != nullptr && bb->defined;
double area_max = 0; double area_max = 0;
Item *biggest = nullptr;
// Copy the references for the shapes only as the arranger expects a // Copy the references for the shapes only as the arranger expects a
// sequence of objects convertible to Item or ClipperPolygon // sequence of objects convertible to Item or ClipperPolygon
std::vector<std::reference_wrapper<Item>> shapes; std::vector<std::reference_wrapper<Item>> shapes;
shapes.reserve(shapemap.size()); shapes.reserve(shapemap.size());
std::for_each(shapemap.begin(), shapemap.end(), std::for_each(shapemap.begin(), shapemap.end(),
[&shapes, min_obj_distance, &area_max, &biggest,hasbin] [&shapes, min_obj_distance, &area_max, hasbin]
(ShapeData2D::value_type& it) (ShapeData2D::value_type& it)
{ {
if(!hasbin) {
Item& item = it.second;
item.addOffset(min_obj_distance);
auto b = ShapeLike::boundingBox(item.transformedShape());
auto a = b.width()*b.height();
if(area_max < a) {
area_max = static_cast<double>(a);
biggest = &item;
}
}
shapes.push_back(std::ref(it.second)); shapes.push_back(std::ref(it.second));
}); });
Box bin; Box bin;
@ -546,9 +508,6 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
static_cast<libnest2d::Coord>(bbb.max.x), static_cast<libnest2d::Coord>(bbb.max.x),
static_cast<libnest2d::Coord>(bbb.max.y) static_cast<libnest2d::Coord>(bbb.max.y)
}); });
} else {
// Just take the biggest item as bin... ?
bin = ShapeLike::boundingBox(biggest->transformedShape());
} }
// Will use the DJD selection heuristic with the BottomLeft placement // Will use the DJD selection heuristic with the BottomLeft placement
@ -563,20 +522,22 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
// Align the arranged pile into the center of the bin // Align the arranged pile into the center of the bin
pcfg.alignment = PConf::Alignment::CENTER; pcfg.alignment = PConf::Alignment::CENTER;
// Start placing the items from the center of the print bed
pcfg.starting_point = PConf::Alignment::CENTER;
// TODO cannot use rotations until multiple objects of same geometry can // TODO cannot use rotations until multiple objects of same geometry can
// handle different rotations // handle different rotations
// arranger.useMinimumBoundigBoxRotation(); // arranger.useMinimumBoundigBoxRotation();
pcfg.rotations = { 0.0 }; pcfg.rotations = { 0.0 };
// Magic: we will specify what is the goal of arrangement... // Magic: we will specify what is the goal of arrangement...
// In this case we override the default object function because we // In this case we override the default object to make the larger items go
// (apparently) don't care about pack efficiency and all we care is that the // into the center of the pile and smaller items orbit it so the resulting
// larger items go into the center of the pile and smaller items orbit it // pile has a circle-like shape. This is good for the print bed's heat
// so the resulting pile has a circle-like shape. // profile. We alse sacrafice a bit of pack efficiency for this to work. As
// This is good for the print bed's heat profile. // a side effect, the arrange procedure is a lot faster (we do not need to
// As a side effect, the arrange procedure is a lot faster (we do not need // calculate the convex hulls)
// to calculate the convex hulls) pcfg.object_function = [bin, hasbin](
pcfg.object_function = [&bin](
NfpPlacer::Pile pile, // The currently arranged pile NfpPlacer::Pile pile, // The currently arranged pile
double /*area*/, // Sum area of items (not needed) double /*area*/, // Sum area of items (not needed)
double norm, // A norming factor for physical dimensions double norm, // A norming factor for physical dimensions
@ -584,14 +545,25 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
{ {
auto bb = ShapeLike::boundingBox(pile); auto bb = ShapeLike::boundingBox(pile);
// We will optimize to the diameter of the circle around the bounding // We get the current item that's being evaluated.
// box and use the norming factor to get rid of the physical dimensions auto& sh = pile.back();
double score = PointLike::distance(bb.minCorner(),
bb.maxCorner()) / norm; // We retrieve the reference point of this item
auto rv = Nfp::referenceVertex(sh);
// We get the distance of the reference point from the center of the
// heat bed
auto c = bin.center();
auto d = PointLike::distance(rv, c);
// The score will be the normalized distance which will be minimized,
// effectively creating a circle shaped pile of items
double score = double(d)/norm;
// If it does not fit into the print bed we will beat it // If it does not fit into the print bed we will beat it
// with a large penality // with a large penality. If we would not do this, there would be only
if(!NfpPlacer::wouldFit(bb, bin)) score = 2*penality - score; // one big pile that doesn't care whether it fits onto the print bed.
if(hasbin && !NfpPlacer::wouldFit(bb, bin)) score = 2*penality - score;
return score; return score;
}; };
@ -602,18 +574,10 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
// Set the progress indicator for the arranger. // Set the progress indicator for the arranger.
arranger.progressIndicator(progressind); arranger.progressIndicator(progressind);
// std::cout << "Arranging model..." << std::endl;
// bench.start();
// Arrange and return the items with their respective indices within the // Arrange and return the items with their respective indices within the
// input sequence. // input sequence.
auto result = arranger.arrangeIndexed(shapes.begin(), shapes.end()); auto result = arranger.arrangeIndexed(shapes.begin(), shapes.end());
// bench.stop();
// std::cout << "Model arranged in " << bench.getElapsedSec()
// << " seconds." << std::endl;
auto applyResult = [&shapemap](ArrangeResult::value_type& group, auto applyResult = [&shapemap](ArrangeResult::value_type& group,
Coord batch_offset) Coord batch_offset)
{ {
@ -637,8 +601,6 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
} }
}; };
// std::cout << "Applying result..." << std::endl;
// bench.start();
if(first_bin_only) { if(first_bin_only) {
applyResult(result.front(), 0); applyResult(result.front(), 0);
} else { } else {
@ -658,9 +620,6 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
batch_offset += stride; batch_offset += stride;
} }
} }
// bench.stop();
// std::cout << "Result applied in " << bench.getElapsedSec()
// << " seconds." << std::endl;
for(auto objptr : model.objects) objptr->invalidate_bounding_box(); for(auto objptr : model.objects) objptr->invalidate_bounding_box();
@ -675,16 +634,11 @@ bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb,
{ {
bool ret = false; bool ret = false;
if(bb != nullptr && bb->defined) { if(bb != nullptr && bb->defined) {
// Despite the new arrange is able to run without a specified bin,
// the perl testsuit still fails for this case. For now the safest
// thing to do is to use the new arrange only when a proper bin is
// specified.
ret = arr::arrange(*this, dist, bb, false, progressind); ret = arr::arrange(*this, dist, bb, false, progressind);
// std::fstream out("out.cpp", std::fstream::out);
// if(out.good()) {
// out << "const TestData OBJECTS = \n";
// out << arr::toString(*this);
// }
// out.close();
// SVG svg("out.svg");
// arr::toSVG(svg, *this);
// svg.Close();
} else { } else {
// get the (transformed) size of each instance so that we take // get the (transformed) size of each instance so that we take
// into account their different transformations when packing // into account their different transformations when packing

View File

@ -236,7 +236,8 @@ public:
PrintRegionPtrs regions; PrintRegionPtrs regions;
PlaceholderParser placeholder_parser; PlaceholderParser placeholder_parser;
// TODO: status_cb // TODO: status_cb
std::string estimated_print_time; std::string estimated_normal_print_time;
std::string estimated_silent_print_time;
double total_used_filament, total_extruded_volume, total_cost, total_weight; double total_used_filament, total_extruded_volume, total_cost, total_weight;
std::map<size_t, float> filament_stats; std::map<size_t, float> filament_stats;
PrintState<PrintStep, psCount> state; PrintState<PrintStep, psCount> state;

View File

@ -291,11 +291,11 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("hilbertcurve"); def->enum_values.push_back("hilbertcurve");
def->enum_values.push_back("archimedeanchords"); def->enum_values.push_back("archimedeanchords");
def->enum_values.push_back("octagramspiral"); def->enum_values.push_back("octagramspiral");
def->enum_labels.push_back("Rectilinear"); def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back("Concentric"); def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back("Hilbert Curve"); def->enum_labels.push_back(L("Hilbert Curve"));
def->enum_labels.push_back("Archimedean Chords"); def->enum_labels.push_back(L("Archimedean Chords"));
def->enum_labels.push_back("Octagram Spiral"); def->enum_labels.push_back(L("Octagram Spiral"));
// solid_fill_pattern is an obsolete equivalent to external_fill_pattern. // solid_fill_pattern is an obsolete equivalent to external_fill_pattern.
def->aliases.push_back("solid_fill_pattern"); def->aliases.push_back("solid_fill_pattern");
def->default_value = new ConfigOptionEnum<InfillPattern>(ipRectilinear); def->default_value = new ConfigOptionEnum<InfillPattern>(ipRectilinear);
@ -651,19 +651,19 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("hilbertcurve"); def->enum_values.push_back("hilbertcurve");
def->enum_values.push_back("archimedeanchords"); def->enum_values.push_back("archimedeanchords");
def->enum_values.push_back("octagramspiral"); def->enum_values.push_back("octagramspiral");
def->enum_labels.push_back("Rectilinear"); def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back("Grid"); def->enum_labels.push_back(L("Grid"));
def->enum_labels.push_back("Triangles"); def->enum_labels.push_back(L("Triangles"));
def->enum_labels.push_back("Stars"); def->enum_labels.push_back(L("Stars"));
def->enum_labels.push_back("Cubic"); def->enum_labels.push_back(L("Cubic"));
def->enum_labels.push_back("Line"); def->enum_labels.push_back(L("Line"));
def->enum_labels.push_back("Concentric"); def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back("Honeycomb"); def->enum_labels.push_back(L("Honeycomb"));
def->enum_labels.push_back("3D Honeycomb"); def->enum_labels.push_back(L("3D Honeycomb"));
def->enum_labels.push_back("Gyroid"); def->enum_labels.push_back(L("Gyroid"));
def->enum_labels.push_back("Hilbert Curve"); def->enum_labels.push_back(L("Hilbert Curve"));
def->enum_labels.push_back("Archimedean Chords"); def->enum_labels.push_back(L("Archimedean Chords"));
def->enum_labels.push_back("Octagram Spiral"); def->enum_labels.push_back(L("Octagram Spiral"));
def->default_value = new ConfigOptionEnum<InfillPattern>(ipStars); def->default_value = new ConfigOptionEnum<InfillPattern>(ipStars);
def = this->add("first_layer_acceleration", coFloat); def = this->add("first_layer_acceleration", coFloat);
@ -771,8 +771,8 @@ PrintConfigDef::PrintConfigDef()
def->enum_labels.push_back("Mach3/LinuxCNC"); def->enum_labels.push_back("Mach3/LinuxCNC");
def->enum_labels.push_back("Machinekit"); def->enum_labels.push_back("Machinekit");
def->enum_labels.push_back("Smoothie"); def->enum_labels.push_back("Smoothie");
def->enum_labels.push_back("No extrusion"); def->enum_labels.push_back(L("No extrusion"));
def->default_value = new ConfigOptionEnum<GCodeFlavor>(gcfMarlin); def->default_value = new ConfigOptionEnum<GCodeFlavor>(gcfRepRap);
def = this->add("infill_acceleration", coFloat); def = this->add("infill_acceleration", coFloat);
def->label = L("Infill"); def->label = L("Infill");
@ -892,6 +892,12 @@ PrintConfigDef::PrintConfigDef()
def->min = 0; def->min = 0;
def->default_value = new ConfigOptionFloat(0.3); def->default_value = new ConfigOptionFloat(0.3);
def = this->add("silent_mode", coBool);
def->label = L("Support silent mode");
def->tooltip = L("Set silent mode for the G-code flavor");
def->default_value = new ConfigOptionBool(true);
const int machine_limits_opt_width = 70;
{ {
struct AxisDefault { struct AxisDefault {
std::string name; std::string name;
@ -901,75 +907,82 @@ PrintConfigDef::PrintConfigDef()
}; };
std::vector<AxisDefault> axes { std::vector<AxisDefault> axes {
// name, max_feedrate, max_acceleration, max_jerk // name, max_feedrate, max_acceleration, max_jerk
{ "x", { 200., 200. }, { 1000., 1000. }, { 10., 10. } }, { "x", { 500., 200. }, { 9000., 1000. }, { 10. , 10. } },
{ "y", { 200., 200. }, { 1000., 1000. }, { 10., 10. } }, { "y", { 500., 200. }, { 9000., 1000. }, { 10. , 10. } },
{ "z", { 12., 12. }, { 200., 200. }, { 0.4, 0.4 } }, { "z", { 12., 12. }, { 500., 200. }, { 0.2, 0.4 } },
{ "e", { 120., 120. }, { 5000., 5000. }, { 2.5, 2.5 } } { "e", { 120., 120. }, { 10000., 5000. }, { 2.5, 2.5 } }
}; };
for (const AxisDefault &axis : axes) { for (const AxisDefault &axis : axes) {
std::string axis_upper = boost::to_upper_copy<std::string>(axis.name); std::string axis_upper = boost::to_upper_copy<std::string>(axis.name);
// Add the machine feedrate limits for XYZE axes. (M203) // Add the machine feedrate limits for XYZE axes. (M203)
def = this->add("machine_max_feedrate_" + axis.name, coFloats); def = this->add("machine_max_feedrate_" + axis.name, coFloats);
def->label = (boost::format(L("Maximum feedrate %1%")) % axis_upper).str(); def->full_label = (boost::format(L("Maximum feedrate %1%")) % axis_upper).str();
def->category = L("Machine limits"); def->category = L("Machine limits");
def->tooltip = (boost::format(L("Maximum feedrate of the %1% axis")) % axis_upper).str(); def->tooltip = (boost::format(L("Maximum feedrate of the %1% axis")) % axis_upper).str();
def->sidetext = L("mm/s"); def->sidetext = L("mm/s");
def->min = 0; def->min = 0;
def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats(axis.max_feedrate); def->default_value = new ConfigOptionFloats(axis.max_feedrate);
// Add the machine acceleration limits for XYZE axes (M201) // Add the machine acceleration limits for XYZE axes (M201)
def = this->add("machine_max_acceleration_" + axis.name, coFloats); def = this->add("machine_max_acceleration_" + axis.name, coFloats);
def->label = (boost::format(L("Maximum acceleration %1%")) % axis_upper).str(); def->full_label = (boost::format(L("Maximum acceleration %1%")) % axis_upper).str();
def->category = L("Machine limits"); def->category = L("Machine limits");
def->tooltip = (boost::format(L("Maximum acceleration of the %1% axis")) % axis_upper).str(); def->tooltip = (boost::format(L("Maximum acceleration of the %1% axis")) % axis_upper).str();
def->sidetext = L("mm/s²"); def->sidetext = L("mm/s²");
def->min = 0; def->min = 0;
def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats(axis.max_acceleration); def->default_value = new ConfigOptionFloats(axis.max_acceleration);
// Add the machine jerk limits for XYZE axes (M205) // Add the machine jerk limits for XYZE axes (M205)
def = this->add("machine_max_jerk_" + axis.name, coFloats); def = this->add("machine_max_jerk_" + axis.name, coFloats);
def->label = (boost::format(L("Maximum jerk %1%")) % axis_upper).str(); def->full_label = (boost::format(L("Maximum jerk %1%")) % axis_upper).str();
def->category = L("Machine limits"); def->category = L("Machine limits");
def->tooltip = (boost::format(L("Maximum jerk of the %1% axis")) % axis_upper).str(); def->tooltip = (boost::format(L("Maximum jerk of the %1% axis")) % axis_upper).str();
def->sidetext = L("mm/s"); def->sidetext = L("mm/s");
def->min = 0; def->min = 0;
def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats(axis.max_jerk); def->default_value = new ConfigOptionFloats(axis.max_jerk);
} }
} }
// M205 S... [mm/sec] // M205 S... [mm/sec]
def = this->add("machine_min_extruding_rate", coFloats); def = this->add("machine_min_extruding_rate", coFloats);
def->label = L("Minimum feedrate when extruding"); def->full_label = L("Minimum feedrate when extruding");
def->category = L("Machine limits"); def->category = L("Machine limits");
def->tooltip = L("Minimum feedrate when extruding") + " (M205 S)"; def->tooltip = L("Minimum feedrate when extruding") + " (M205 S)";
def->sidetext = L("mm/s"); def->sidetext = L("mm/s");
def->min = 0; def->min = 0;
def->default_value = new ConfigOptionFloats(0., 0.); def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats{ 0., 0. };
// M205 T... [mm/sec] // M205 T... [mm/sec]
def = this->add("machine_min_travel_rate", coFloats); def = this->add("machine_min_travel_rate", coFloats);
def->label = L("Minimum travel feedrate"); def->full_label = L("Minimum travel feedrate");
def->category = L("Machine limits"); def->category = L("Machine limits");
def->tooltip = L("Minimum travel feedrate") + " (M205 T)"; def->tooltip = L("Minimum travel feedrate") + " (M205 T)";
def->sidetext = L("mm/s"); def->sidetext = L("mm/s");
def->min = 0; def->min = 0;
def->default_value = new ConfigOptionFloats(0., 0.); def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats{ 0., 0. };
// M204 S... [mm/sec^2] // M204 S... [mm/sec^2]
def = this->add("machine_max_acceleration_extruding", coFloats); def = this->add("machine_max_acceleration_extruding", coFloats);
def->label = L("Maximum acceleration when extruding"); def->full_label = L("Maximum acceleration when extruding");
def->category = L("Machine limits"); def->category = L("Machine limits");
def->tooltip = L("Maximum acceleration when extruding") + " (M204 S)"; def->tooltip = L("Maximum acceleration when extruding") + " (M204 S)";
def->sidetext = L("mm/s²"); def->sidetext = L("mm/s²");
def->min = 0; def->min = 0;
def->default_value = new ConfigOptionFloats(1250., 1250.); def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats{ 1500., 1250. };
// M204 T... [mm/sec^2] // M204 T... [mm/sec^2]
def = this->add("machine_max_acceleration_retracting", coFloats); def = this->add("machine_max_acceleration_retracting", coFloats);
def->label = L("Maximum acceleration when retracting"); def->full_label = L("Maximum acceleration when retracting");
def->category = L("Machine limits"); def->category = L("Machine limits");
def->tooltip = L("Maximum acceleration when retracting") + " (M204 T)"; def->tooltip = L("Maximum acceleration when retracting") + " (M204 T)";
def->sidetext = L("mm/s²"); def->sidetext = L("mm/s²");
def->min = 0; def->min = 0;
def->default_value = new ConfigOptionFloats(1250., 1250.); def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats{ 1500., 1250. };
def = this->add("max_fan_speed", coInts); def = this->add("max_fan_speed", coInts);
def->label = L("Max"); def->label = L("Max");
@ -1392,10 +1405,10 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("nearest"); def->enum_values.push_back("nearest");
def->enum_values.push_back("aligned"); def->enum_values.push_back("aligned");
def->enum_values.push_back("rear"); def->enum_values.push_back("rear");
def->enum_labels.push_back("Random"); def->enum_labels.push_back(L("Random"));
def->enum_labels.push_back("Nearest"); def->enum_labels.push_back(L("Nearest"));
def->enum_labels.push_back("Aligned"); def->enum_labels.push_back(L("Aligned"));
def->enum_labels.push_back("Rear"); def->enum_labels.push_back(L("Rear"));
def->default_value = new ConfigOptionEnum<SeamPosition>(spAligned); def->default_value = new ConfigOptionEnum<SeamPosition>(spAligned);
#if 0 #if 0
@ -1608,7 +1621,7 @@ PrintConfigDef::PrintConfigDef()
def->label = L("Single Extruder Multi Material"); def->label = L("Single Extruder Multi Material");
def->tooltip = L("The printer multiplexes filaments into a single hot end."); def->tooltip = L("The printer multiplexes filaments into a single hot end.");
def->cli = "single-extruder-multi-material!"; def->cli = "single-extruder-multi-material!";
def->default_value = new ConfigOptionBool(false); def->default_value = new ConfigOptionBool(false);
def = this->add("support_material", coBool); def = this->add("support_material", coBool);
def->label = L("Generate support material"); def->label = L("Generate support material");
@ -1658,8 +1671,8 @@ PrintConfigDef::PrintConfigDef()
def->min = 0; def->min = 0;
def->enum_values.push_back("0"); def->enum_values.push_back("0");
def->enum_values.push_back("0.2"); def->enum_values.push_back("0.2");
def->enum_labels.push_back("0 (soluble)"); def->enum_labels.push_back((boost::format("0 (%1%)") % L("soluble")).str());
def->enum_labels.push_back("0.2 (detachable)"); def->enum_labels.push_back((boost::format("0.2 (%1%)") % L("detachable")).str());
def->default_value = new ConfigOptionFloat(0.2); def->default_value = new ConfigOptionFloat(0.2);
def = this->add("support_material_enforce_layers", coInt); def = this->add("support_material_enforce_layers", coInt);
@ -1748,9 +1761,9 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("rectilinear"); def->enum_values.push_back("rectilinear");
def->enum_values.push_back("rectilinear-grid"); def->enum_values.push_back("rectilinear-grid");
def->enum_values.push_back("honeycomb"); def->enum_values.push_back("honeycomb");
def->enum_labels.push_back("rectilinear"); def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back("rectilinear grid"); def->enum_labels.push_back(L("Rectilinear grid"));
def->enum_labels.push_back("honeycomb"); def->enum_labels.push_back(L("Honeycomb"));
def->default_value = new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear); def->default_value = new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear);
def = this->add("support_material_spacing", coFloat); def = this->add("support_material_spacing", coFloat);

View File

@ -562,9 +562,9 @@ public:
ConfigOptionFloat cooling_tube_retraction; ConfigOptionFloat cooling_tube_retraction;
ConfigOptionFloat cooling_tube_length; ConfigOptionFloat cooling_tube_length;
ConfigOptionFloat parking_pos_retraction; ConfigOptionFloat parking_pos_retraction;
ConfigOptionBool silent_mode;
ConfigOptionFloat extra_loading_move; ConfigOptionFloat extra_loading_move;
std::string get_extrusion_axis() const std::string get_extrusion_axis() const
{ {
return return
@ -623,6 +623,7 @@ protected:
OPT_PTR(cooling_tube_retraction); OPT_PTR(cooling_tube_retraction);
OPT_PTR(cooling_tube_length); OPT_PTR(cooling_tube_length);
OPT_PTR(parking_pos_retraction); OPT_PTR(parking_pos_retraction);
OPT_PTR(silent_mode);
OPT_PTR(extra_loading_move); OPT_PTR(extra_loading_move);
} }
}; };
@ -676,6 +677,7 @@ public:
ConfigOptionString output_filename_format; ConfigOptionString output_filename_format;
ConfigOptionFloat perimeter_acceleration; ConfigOptionFloat perimeter_acceleration;
ConfigOptionStrings post_process; ConfigOptionStrings post_process;
ConfigOptionString printer_model;
ConfigOptionString printer_notes; ConfigOptionString printer_notes;
ConfigOptionFloat resolution; ConfigOptionFloat resolution;
ConfigOptionFloats retract_before_travel; ConfigOptionFloats retract_before_travel;
@ -746,6 +748,7 @@ protected:
OPT_PTR(output_filename_format); OPT_PTR(output_filename_format);
OPT_PTR(perimeter_acceleration); OPT_PTR(perimeter_acceleration);
OPT_PTR(post_process); OPT_PTR(post_process);
OPT_PTR(printer_model);
OPT_PTR(printer_notes); OPT_PTR(printer_notes);
OPT_PTR(resolution); OPT_PTR(resolution);
OPT_PTR(retract_before_travel); OPT_PTR(retract_before_travel);

View File

@ -14,7 +14,7 @@
#include <boost/thread.hpp> #include <boost/thread.hpp>
#define SLIC3R_FORK_NAME "Slic3r Prusa Edition" #define SLIC3R_FORK_NAME "Slic3r Prusa Edition"
#define SLIC3R_VERSION "1.40.1" #define SLIC3R_VERSION "1.41.0-alpha"
#define SLIC3R_BUILD "UNKNOWN" #define SLIC3R_BUILD "UNKNOWN"
typedef int32_t coord_t; typedef int32_t coord_t;

View File

@ -1686,7 +1686,7 @@ bool _3DScene::LegendTexture::generate(const GCodePreviewData& preview_data, con
m_data.clear(); m_data.clear();
// collects items to render // collects items to render
auto title = GUI::L_str(preview_data.get_legend_title()); auto title = _(preview_data.get_legend_title());
const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors); const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors);
unsigned int items_count = (unsigned int)items.size(); unsigned int items_count = (unsigned int)items.size();

View File

@ -45,6 +45,22 @@ namespace Slic3r { namespace GUI {
set_undo_bitmap(&bmp); set_undo_bitmap(&bmp);
set_undo_to_sys_bitmap(&bmp); set_undo_to_sys_bitmap(&bmp);
switch (m_opt.type)
{
case coPercents:
case coFloats:
case coStrings:
case coBools:
case coInts: {
auto tag_pos = m_opt_id.find("#");
if (tag_pos != std::string::npos)
m_opt_idx = stoi(m_opt_id.substr(tag_pos + 1, m_opt_id.size()));
break;
}
default:
break;
}
BUILD(); BUILD();
} }
@ -77,7 +93,7 @@ namespace Slic3r { namespace GUI {
wxString Field::get_tooltip_text(const wxString& default_string) wxString Field::get_tooltip_text(const wxString& default_string)
{ {
wxString tooltip_text(""); wxString tooltip_text("");
wxString tooltip = L_str(m_opt.tooltip); wxString tooltip = _(m_opt.tooltip);
if (tooltip.length() > 0) if (tooltip.length() > 0)
tooltip_text = tooltip + "(" + _(L("default")) + ": " + tooltip_text = tooltip + "(" + _(L("default")) + ": " +
(boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") + (boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") +
@ -161,10 +177,10 @@ namespace Slic3r { namespace GUI {
case coFloat: case coFloat:
{ {
double val = m_opt.type == coFloats ? double val = m_opt.type == coFloats ?
static_cast<const ConfigOptionFloats*>(m_opt.default_value)->get_at(0) : static_cast<const ConfigOptionFloats*>(m_opt.default_value)->get_at(m_opt_idx) :
m_opt.type == coFloat ? m_opt.type == coFloat ?
m_opt.default_value->getFloat() : m_opt.default_value->getFloat() :
static_cast<const ConfigOptionPercents*>(m_opt.default_value)->get_at(0); static_cast<const ConfigOptionPercents*>(m_opt.default_value)->get_at(m_opt_idx);
text_value = double_to_string(val); text_value = double_to_string(val);
break; break;
} }
@ -174,10 +190,8 @@ namespace Slic3r { namespace GUI {
case coStrings: case coStrings:
{ {
const ConfigOptionStrings *vec = static_cast<const ConfigOptionStrings*>(m_opt.default_value); const ConfigOptionStrings *vec = static_cast<const ConfigOptionStrings*>(m_opt.default_value);
if (vec == nullptr || vec->empty()) break; if (vec == nullptr || vec->empty()) break; //for the case of empty default value
if (vec->size() > 1) text_value = vec->get_at(m_opt_idx);
break;
text_value = vec->values.at(0);
break; break;
} }
default: default:
@ -259,7 +273,7 @@ void CheckBox::BUILD() {
bool check_value = m_opt.type == coBool ? bool check_value = m_opt.type == coBool ?
m_opt.default_value->getBool() : m_opt.type == coBools ? m_opt.default_value->getBool() : m_opt.type == coBools ?
static_cast<ConfigOptionBools*>(m_opt.default_value)->values.at(0) : static_cast<ConfigOptionBools*>(m_opt.default_value)->get_at(m_opt_idx) :
false; false;
auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size); auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size);
@ -365,7 +379,7 @@ void Choice::BUILD() {
} }
else{ else{
for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels){ for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels){
const wxString& str = m_opt_id == "support" ? L_str(el) : el; const wxString& str = _(el);//m_opt_id == "support" ? _(el) : el;
temp->Append(str); temp->Append(str);
} }
set_selection(); set_selection();
@ -418,7 +432,7 @@ void Choice::set_selection()
break; break;
} }
case coStrings:{ case coStrings:{
text_value = static_cast<const ConfigOptionStrings*>(m_opt.default_value)->values.at(0); text_value = static_cast<const ConfigOptionStrings*>(m_opt.default_value)->get_at(m_opt_idx);
size_t idx = 0; size_t idx = 0;
for (auto el : m_opt.enum_values) for (auto el : m_opt.enum_values)
@ -582,7 +596,7 @@ void ColourPicker::BUILD()
if (m_opt.height >= 0) size.SetHeight(m_opt.height); if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width); if (m_opt.width >= 0) size.SetWidth(m_opt.width);
wxString clr(static_cast<ConfigOptionStrings*>(m_opt.default_value)->values.at(0)); wxString clr(static_cast<ConfigOptionStrings*>(m_opt.default_value)->get_at(m_opt_idx));
auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size); auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size);
// // recast as a wxWindow to fit the calling convention // // recast as a wxWindow to fit the calling convention
@ -675,6 +689,22 @@ boost::any& PointCtrl::get_value()
return m_value = ret_point; return m_value = ret_point;
} }
void StaticText::BUILD()
{
auto size = wxSize(wxDefaultSize);
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
wxString legend(static_cast<ConfigOptionString*>(m_opt.default_value)->value);
auto temp = new wxStaticText(m_parent, wxID_ANY, legend, wxDefaultPosition, size);
temp->SetFont(bold_font());
// // recast as a wxWindow to fit the calling convention
window = dynamic_cast<wxWindow*>(temp);
temp->SetToolTip(get_tooltip_text(legend));
}
} // GUI } // GUI
} // Slic3r } // Slic3r

View File

@ -95,6 +95,7 @@ public:
/// Copy of ConfigOption for deduction purposes /// Copy of ConfigOption for deduction purposes
const ConfigOptionDef m_opt {ConfigOptionDef()}; const ConfigOptionDef m_opt {ConfigOptionDef()};
const t_config_option_key m_opt_id;//! {""}; const t_config_option_key m_opt_id;//! {""};
int m_opt_idx = 0;
/// Sets a value for this control. /// Sets a value for this control.
/// subclasses should overload with a specific version /// subclasses should overload with a specific version
@ -384,6 +385,34 @@ public:
wxSizer* getSizer() override { return sizer; } wxSizer* getSizer() override { return sizer; }
}; };
class StaticText : public Field {
using Field::Field;
public:
StaticText(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
StaticText(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
~StaticText() {}
wxWindow* window{ nullptr };
void BUILD() override;
void set_value(const std::string& value, bool change_event = false) {
m_disable_change_event = !change_event;
dynamic_cast<wxStaticText*>(window)->SetLabel(value);
m_disable_change_event = false;
}
void set_value(const boost::any& value, bool change_event = false) {
m_disable_change_event = !change_event;
dynamic_cast<wxStaticText*>(window)->SetLabel(boost::any_cast<wxString>(value));
m_disable_change_event = false;
}
boost::any& get_value()override { return m_value; }
void enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); };
void disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); };
wxWindow* getWindow() override { return window; }
};
} // GUI } // GUI
} // Slic3r } // Slic3r

View File

@ -56,8 +56,9 @@
#include "../Utils/PresetUpdater.hpp" #include "../Utils/PresetUpdater.hpp"
#include "../Config/Snapshot.hpp" #include "../Config/Snapshot.hpp"
#include "libslic3r/I18N.hpp"
#include "3DScene.hpp" #include "3DScene.hpp"
#include "libslic3r/I18N.hpp"
namespace Slic3r { namespace GUI { namespace Slic3r { namespace GUI {
@ -110,6 +111,7 @@ wxNotebook *g_wxTabPanel = nullptr;
AppConfig *g_AppConfig = nullptr; AppConfig *g_AppConfig = nullptr;
PresetBundle *g_PresetBundle= nullptr; PresetBundle *g_PresetBundle= nullptr;
PresetUpdater *g_PresetUpdater = nullptr; PresetUpdater *g_PresetUpdater = nullptr;
_3DScene *g_3DScene = nullptr;
wxColour g_color_label_modified; wxColour g_color_label_modified;
wxColour g_color_label_sys; wxColour g_color_label_sys;
wxColour g_color_label_default; wxColour g_color_label_default;
@ -118,6 +120,9 @@ std::vector<Tab *> g_tabs_list;
wxLocale* g_wxLocale; wxLocale* g_wxLocale;
wxFont g_small_font;
wxFont g_bold_font;
std::shared_ptr<ConfigOptionsGroup> m_optgroup; std::shared_ptr<ConfigOptionsGroup> m_optgroup;
double m_brim_width = 0.0; double m_brim_width = 0.0;
wxButton* g_wiping_dialog_button = nullptr; wxButton* g_wiping_dialog_button = nullptr;
@ -150,6 +155,16 @@ void update_label_colours_from_appconfig()
} }
} }
static void init_fonts()
{
g_small_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
g_bold_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold();
#ifdef __WXMAC__
g_small_font.SetPointSize(11);
g_bold_font.SetPointSize(13);
#endif /*__WXMAC__*/
}
static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); } static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); }
void set_wxapp(wxApp *app) void set_wxapp(wxApp *app)
@ -158,6 +173,7 @@ void set_wxapp(wxApp *app)
// Let the libslic3r know the callback, which will translate messages on demand. // Let the libslic3r know the callback, which will translate messages on demand.
Slic3r::I18N::set_translate_callback(libslic3r_translate_callback); Slic3r::I18N::set_translate_callback(libslic3r_translate_callback);
init_label_colours(); init_label_colours();
init_fonts();
} }
void set_main_frame(wxFrame *main_frame) void set_main_frame(wxFrame *main_frame)
@ -185,6 +201,11 @@ void set_preset_updater(PresetUpdater *updater)
g_PresetUpdater = updater; g_PresetUpdater = updater;
} }
void set_3DScene(_3DScene *scene)
{
g_3DScene = scene;
}
std::vector<Tab *>& get_tabs_list() std::vector<Tab *>& get_tabs_list()
{ {
return g_tabs_list; return g_tabs_list;
@ -675,6 +696,14 @@ void set_label_clr_sys(const wxColour& clr) {
g_AppConfig->save(); g_AppConfig->save();
} }
const wxFont& small_font(){
return g_small_font;
}
const wxFont& bold_font(){
return g_bold_font;
}
const wxColour& get_label_clr_default() { const wxColour& get_label_clr_default() {
return g_color_label_default; return g_color_label_default;
} }

View File

@ -11,7 +11,7 @@
class wxApp; class wxApp;
class wxWindow; class wxWindow;
class wxFrame; class wxFrame;
class wxWindow; class wxFont;
class wxMenuBar; class wxMenuBar;
class wxNotebook; class wxNotebook;
class wxComboCtrl; class wxComboCtrl;
@ -32,6 +32,7 @@ class AppConfig;
class PresetUpdater; class PresetUpdater;
class DynamicPrintConfig; class DynamicPrintConfig;
class TabIface; class TabIface;
class _3DScene;
#define _(s) Slic3r::GUI::I18N::translate((s)) #define _(s) Slic3r::GUI::I18N::translate((s))
@ -90,6 +91,7 @@ void set_tab_panel(wxNotebook *tab_panel);
void set_app_config(AppConfig *app_config); void set_app_config(AppConfig *app_config);
void set_preset_bundle(PresetBundle *preset_bundle); void set_preset_bundle(PresetBundle *preset_bundle);
void set_preset_updater(PresetUpdater *updater); void set_preset_updater(PresetUpdater *updater);
void set_3DScene(_3DScene *scene);
AppConfig* get_app_config(); AppConfig* get_app_config();
wxApp* get_app(); wxApp* get_app();
@ -102,6 +104,9 @@ unsigned get_colour_approx_luma(const wxColour &colour);
void set_label_clr_modified(const wxColour& clr); void set_label_clr_modified(const wxColour& clr);
void set_label_clr_sys(const wxColour& clr); void set_label_clr_sys(const wxColour& clr);
const wxFont& small_font();
const wxFont& bold_font();
extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change); extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change);
// This is called when closing the application, when loading a config file or when starting the config wizard // This is called when closing the application, when loading a config file or when starting the config wizard

View File

@ -31,6 +31,8 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(parent(), opt, id))); m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(parent(), opt, id)));
} else if (opt.gui_type.compare("slider") == 0) { } else if (opt.gui_type.compare("slider") == 0) {
} else if (opt.gui_type.compare("i_spin") == 0) { // Spinctrl } else if (opt.gui_type.compare("i_spin") == 0) { // Spinctrl
} else if (opt.gui_type.compare("legend") == 0) { // StaticText
m_fields.emplace(id, STDMOVE(StaticText::Create<StaticText>(parent(), opt, id)));
} else { } else {
switch (opt.type) { switch (opt.type) {
case coFloatOrPercent: case coFloatOrPercent:
@ -86,7 +88,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
if (!this->m_disabled) if (!this->m_disabled)
this->back_to_sys_value(opt_id); this->back_to_sys_value(opt_id);
}; };
if (!m_is_tab_opt) { if (!m_show_modified_btns) {
field->m_Undo_btn->Hide(); field->m_Undo_btn->Hide();
field->m_Undo_to_sys_btn->Hide(); field->m_Undo_to_sys_btn->Hide();
} }
@ -199,7 +201,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
ConfigOptionDef option = opt.opt; ConfigOptionDef option = opt.opt;
// add label if any // add label if any
if (option.label != "") { if (option.label != "") {
wxString str_label = L_str(option.label); wxString str_label = _(option.label);
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1 //! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
// wxString str_label = (option.label == "Top" || option.label == "Bottom") ? // wxString str_label = (option.label == "Top" || option.label == "Bottom") ?
// wxGETTEXT_IN_CONTEXT("Layers", wxString(option.label.c_str()): // wxGETTEXT_IN_CONTEXT("Layers", wxString(option.label.c_str()):
@ -220,7 +222,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
// add sidetext if any // add sidetext if any
if (option.sidetext != "") { if (option.sidetext != "") {
auto sidetext = new wxStaticText(parent(), wxID_ANY, L_str(option.sidetext), wxDefaultPosition, wxDefaultSize); auto sidetext = new wxStaticText(parent(), wxID_ANY, _(option.sidetext), wxDefaultPosition, wxDefaultSize);
sidetext->SetFont(sidetext_font); sidetext->SetFont(sidetext_font);
sizer->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4); sizer->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4);
} }
@ -242,7 +244,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
} }
Line OptionsGroup::create_single_option_line(const Option& option) const { Line OptionsGroup::create_single_option_line(const Option& option) const {
Line retval{ L_str(option.opt.label), L_str(option.opt.tooltip) }; Line retval{ _(option.opt.label), _(option.opt.tooltip) };
Option tmp(option); Option tmp(option);
tmp.opt.label = std::string(""); tmp.opt.label = std::string("");
retval.append_option(tmp); retval.append_option(tmp);

View File

@ -127,9 +127,15 @@ public:
inline void enable() { for (auto& field : m_fields) field.second->enable(); } inline void enable() { for (auto& field : m_fields) field.second->enable(); }
inline void disable() { for (auto& field : m_fields) field.second->disable(); } inline void disable() { for (auto& field : m_fields) field.second->disable(); }
void set_show_modified_btns_val(bool show) {
m_show_modified_btns = show;
}
OptionsGroup(wxWindow* _parent, const wxString& title, bool is_tab_opt=false) : OptionsGroup(wxWindow* _parent, const wxString& title, bool is_tab_opt=false) :
m_parent(_parent), title(title), m_is_tab_opt(is_tab_opt), staticbox(title!="") { m_parent(_parent), title(title), m_show_modified_btns(is_tab_opt), staticbox(title!="") {
sizer = (staticbox ? new wxStaticBoxSizer(new wxStaticBox(_parent, wxID_ANY, title), wxVERTICAL) : new wxBoxSizer(wxVERTICAL)); auto stb = new wxStaticBox(_parent, wxID_ANY, title);
stb->SetFont(bold_font());
sizer = (staticbox ? new wxStaticBoxSizer(stb/*new wxStaticBox(_parent, wxID_ANY, title)*/, wxVERTICAL) : new wxBoxSizer(wxVERTICAL));
auto num_columns = 1U; auto num_columns = 1U;
if (label_width != 0) num_columns++; if (label_width != 0) num_columns++;
if (extra_column != nullptr) num_columns++; if (extra_column != nullptr) num_columns++;
@ -156,7 +162,7 @@ protected:
bool m_disabled {false}; bool m_disabled {false};
wxGridSizer* m_grid_sizer {nullptr}; wxGridSizer* m_grid_sizer {nullptr};
// "true" if option is created in preset tabs // "true" if option is created in preset tabs
bool m_is_tab_opt{ false }; bool m_show_modified_btns{ false };
// This panel is needed for correct showing of the ToolTips for Button, StaticText and CheckBox // This panel is needed for correct showing of the ToolTips for Button, StaticText and CheckBox
// Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel // Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel

View File

@ -327,6 +327,11 @@ const std::vector<std::string>& Preset::printer_options()
"single_extruder_multi_material", "start_gcode", "end_gcode", "before_layer_gcode", "layer_gcode", "toolchange_gcode", "single_extruder_multi_material", "start_gcode", "end_gcode", "before_layer_gcode", "layer_gcode", "toolchange_gcode",
"between_objects_gcode", "printer_vendor", "printer_model", "printer_variant", "printer_notes", "cooling_tube_retraction", "between_objects_gcode", "printer_vendor", "printer_model", "printer_variant", "printer_notes", "cooling_tube_retraction",
"cooling_tube_length", "parking_pos_retraction", "extra_loading_move", "max_print_height", "default_print_profile", "inherits", "cooling_tube_length", "parking_pos_retraction", "extra_loading_move", "max_print_height", "default_print_profile", "inherits",
"silent_mode", "machine_max_acceleration_extruding", "machine_max_acceleration_retracting",
"machine_max_acceleration_x", "machine_max_acceleration_y", "machine_max_acceleration_z", "machine_max_acceleration_e",
"machine_max_feedrate_x", "machine_max_feedrate_y", "machine_max_feedrate_z", "machine_max_feedrate_e",
"machine_min_extruding_rate", "machine_min_travel_rate",
"machine_max_jerk_x", "machine_max_jerk_y", "machine_max_jerk_z", "machine_max_jerk_e"
}; };
s_opts.insert(s_opts.end(), Preset::nozzle_options().begin(), Preset::nozzle_options().end()); s_opts.insert(s_opts.end(), Preset::nozzle_options().begin(), Preset::nozzle_options().end());
} }
@ -505,6 +510,9 @@ Preset& PresetCollection::load_external_preset(
// Insert a new profile. // Insert a new profile.
Preset &preset = this->load_preset(path, new_name, std::move(cfg), select); Preset &preset = this->load_preset(path, new_name, std::move(cfg), select);
preset.is_external = true; preset.is_external = true;
if (&this->get_selected_preset() == &preset)
this->get_edited_preset().is_external = true;
return preset; return preset;
} }

View File

@ -353,10 +353,6 @@ public:
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing. // Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
std::string path_from_name(const std::string &new_name) const; std::string path_from_name(const std::string &new_name) const;
// update m_edited_preset.is_external value after loading preset for .ini, .gcode, .amf, .3mf
void update_edited_preset_is_external(bool is_external) {
m_edited_preset.is_external = is_external; }
protected: protected:
// Select a preset, if it exists. If it does not exist, select an invalid (-1) index. // Select a preset, if it exists. If it does not exist, select an invalid (-1) index.
// This is a temporary state, which shall be fixed immediately by the following step. // This is a temporary state, which shall be fixed immediately by the following step.

View File

@ -565,12 +565,11 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
size_t idx = (i_group == 0) ? 0 : num_extruders + 1; size_t idx = (i_group == 0) ? 0 : num_extruders + 1;
inherits = inherits_values[idx]; inherits = inherits_values[idx];
compatible_printers_condition = compatible_printers_condition_values[idx]; compatible_printers_condition = compatible_printers_condition_values[idx];
if (is_external) { if (is_external)
presets.load_external_preset(name_or_path, name, presets.load_external_preset(name_or_path, name,
config.opt_string((i_group == 0) ? "print_settings_id" : "printer_settings_id", true), config.opt_string((i_group == 0) ? "print_settings_id" : "printer_settings_id", true),
config); config);
presets.update_edited_preset_is_external(true); else
} else
presets.load_preset(presets.path_from_name(name), name, config).save(); presets.load_preset(presets.path_from_name(name), name, config).save();
} }
@ -583,10 +582,9 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
// Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets. // Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets.
inherits = inherits_values[1]; inherits = inherits_values[1];
compatible_printers_condition = compatible_printers_condition_values[1]; compatible_printers_condition = compatible_printers_condition_values[1];
if (is_external) { if (is_external)
this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config); this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config);
this->filaments.update_edited_preset_is_external(true); else
} else
this->filaments.load_preset(this->filaments.path_from_name(name), name, config).save(); this->filaments.load_preset(this->filaments.path_from_name(name), name, config).save();
this->filament_presets.clear(); this->filament_presets.clear();
this->filament_presets.emplace_back(name); this->filament_presets.emplace_back(name);
@ -615,12 +613,11 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
cfg.opt_string("inherits", true) = inherits_values[i + 1]; cfg.opt_string("inherits", true) = inherits_values[i + 1];
// Load all filament presets, but only select the first one in the preset dialog. // Load all filament presets, but only select the first one in the preset dialog.
Preset *loaded = nullptr; Preset *loaded = nullptr;
if (is_external) { if (is_external)
loaded = &this->filaments.load_external_preset(name_or_path, name, loaded = &this->filaments.load_external_preset(name_or_path, name,
(i < old_filament_profile_names->values.size()) ? old_filament_profile_names->values[i] : "", (i < old_filament_profile_names->values.size()) ? old_filament_profile_names->values[i] : "",
std::move(cfg), i == 0); std::move(cfg), i == 0);
this->filaments.update_edited_preset_is_external(true); else {
} else {
// Used by the config wizard when creating a custom setup. // Used by the config wizard when creating a custom setup.
// Therefore this block should only be called for a single extruder. // Therefore this block should only be called for a single extruder.
char suffix[64]; char suffix[64];

View File

@ -1605,6 +1605,22 @@ void TabPrinter::build()
optgroup = page->new_optgroup(_(L("Firmware"))); optgroup = page->new_optgroup(_(L("Firmware")));
optgroup->append_single_option_line("gcode_flavor"); optgroup->append_single_option_line("gcode_flavor");
optgroup->append_single_option_line("silent_mode");
optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value){
wxTheApp->CallAfter([this, opt_key, value](){
if (opt_key.compare("silent_mode") == 0) {
bool val = boost::any_cast<bool>(value);
if (m_use_silent_mode != val) {
m_rebuild_kinematics_page = true;
m_use_silent_mode = val;
}
}
build_extruder_pages();
update_dirty();
on_value_change(opt_key, value);
});
};
optgroup = page->new_optgroup(_(L("Advanced"))); optgroup = page->new_optgroup(_(L("Advanced")));
optgroup->append_single_option_line("use_relative_e_distances"); optgroup->append_single_option_line("use_relative_e_distances");
@ -1686,8 +1702,94 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){
on_value_change("extruders_count", extruders_count); on_value_change("extruders_count", extruders_count);
} }
void TabPrinter::build_extruder_pages(){ void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key)
{
auto option = optgroup->get_option(opt_key, 0);
auto line = Line{ option.opt.full_label, "" };
line.append_option(option);
if (m_use_silent_mode)
line.append_option(optgroup->get_option(opt_key, 1));
optgroup->append_line(line);
}
PageShp TabPrinter::build_kinematics_page()
{
auto page = add_options_page(_(L("Machine limits")), "cog.png", true);
if (m_use_silent_mode) {
// Legend for OptionsGroups
auto optgroup = page->new_optgroup(_(L("")));
optgroup->set_show_modified_btns_val(false);
optgroup->label_width = 230;
auto line = Line{ "", "" };
ConfigOptionDef def;
def.type = coString;
def.width = 150;
def.gui_type = "legend";
def.tooltip = L("Values in this column are for Full Power mode");
def.default_value = new ConfigOptionString{ L("Full Power") };
auto option = Option(def, "full_power_legend");
line.append_option(option);
def.tooltip = L("Values in this column are for Silent mode");
def.default_value = new ConfigOptionString{ L("Silent") };
option = Option(def, "silent_legend");
line.append_option(option);
optgroup->append_line(line);
}
std::vector<std::string> axes{ "x", "y", "z", "e" };
auto optgroup = page->new_optgroup(_(L("Maximum accelerations")));
for (const std::string &axis : axes) {
append_option_line(optgroup, "machine_max_acceleration_" + axis);
}
optgroup = page->new_optgroup(_(L("Maximum feedrates")));
for (const std::string &axis : axes) {
append_option_line(optgroup, "machine_max_feedrate_" + axis);
}
optgroup = page->new_optgroup(_(L("Starting Acceleration")));
append_option_line(optgroup, "machine_max_acceleration_extruding");
append_option_line(optgroup, "machine_max_acceleration_retracting");
optgroup = page->new_optgroup(_(L("Advanced")));
append_option_line(optgroup, "machine_min_extruding_rate");
append_option_line(optgroup, "machine_min_travel_rate");
for (const std::string &axis : axes) {
append_option_line(optgroup, "machine_max_jerk_" + axis);
}
return page;
}
void TabPrinter::build_extruder_pages()
{
size_t n_before_extruders = 2; // Count of pages before Extruder pages size_t n_before_extruders = 2; // Count of pages before Extruder pages
bool is_marlin_flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin;
// Add/delete Kinematics page according to is_marlin_flavor
size_t existed_page = 0;
for (int i = n_before_extruders; i < m_pages.size(); ++i) // first make sure it's not there already
if (m_pages[i]->title().find(_(L("Machine limits"))) != std::string::npos) {
if (!is_marlin_flavor || m_rebuild_kinematics_page)
m_pages.erase(m_pages.begin() + i);
else
existed_page = i;
break;
}
if (existed_page < n_before_extruders && is_marlin_flavor){
auto page = build_kinematics_page();
m_pages.insert(m_pages.begin() + n_before_extruders, page);
}
if (is_marlin_flavor)
n_before_extruders++;
size_t n_after_single_extruder_MM = 2; // Count of pages after single_extruder_multi_material page size_t n_after_single_extruder_MM = 2; // Count of pages after single_extruder_multi_material page
if (m_extruders_count_old == m_extruders_count || if (m_extruders_count_old == m_extruders_count ||
@ -1796,6 +1898,24 @@ void TabPrinter::update(){
get_field("toolchange_gcode")->toggle(have_multiple_extruders); get_field("toolchange_gcode")->toggle(have_multiple_extruders);
get_field("single_extruder_multi_material")->toggle(have_multiple_extruders); get_field("single_extruder_multi_material")->toggle(have_multiple_extruders);
bool is_marlin_flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin;
{
Field *sm = get_field("silent_mode");
if (! is_marlin_flavor)
// Disable silent mode for non-marlin firmwares.
get_field("silent_mode")->toggle(false);
if (is_marlin_flavor)
sm->enable();
else
sm->disable();
}
if (m_use_silent_mode != m_config->opt_bool("silent_mode")) {
m_rebuild_kinematics_page = true;
m_use_silent_mode = m_config->opt_bool("silent_mode");
}
for (size_t i = 0; i < m_extruders_count; ++i) { for (size_t i = 0; i < m_extruders_count; ++i) {
bool have_retract_length = m_config->opt_float("retract_length", i) > 0; bool have_retract_length = m_config->opt_float("retract_length", i) > 0;
@ -1914,7 +2034,8 @@ void Tab::rebuild_page_tree()
auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID()); auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
m_treectrl->SetItemTextColour(itemId, p->get_item_colour()); m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
if (p->title() == selected) { if (p->title() == selected) {
m_disable_tree_sel_changed_event = 1; if (!(p->title() == _(L("Machine limits")) || p->title() == _(L("Single extruder MM setup")))) // These Pages have to be updated inside OnTreeSelChange
m_disable_tree_sel_changed_event = 1;
m_treectrl->SelectItem(itemId); m_treectrl->SelectItem(itemId);
m_disable_tree_sel_changed_event = 0; m_disable_tree_sel_changed_event = 0;
have_selection = 1; have_selection = 1;

View File

@ -316,6 +316,9 @@ public:
class TabPrinter : public Tab class TabPrinter : public Tab
{ {
bool m_has_single_extruder_MM_page = false; bool m_has_single_extruder_MM_page = false;
bool m_use_silent_mode = false;
void append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key);
bool m_rebuild_kinematics_page = false;
public: public:
wxButton* m_serial_test_btn; wxButton* m_serial_test_btn;
wxButton* m_octoprint_host_test_btn; wxButton* m_octoprint_host_test_btn;
@ -333,6 +336,7 @@ public:
void update() override; void update() override;
void update_serial_ports(); void update_serial_ports();
void extruders_count_changed(size_t extruders_count); void extruders_count_changed(size_t extruders_count);
PageShp build_kinematics_page();
void build_extruder_pages(); void build_extruder_pages();
void on_preset_loaded() override; void on_preset_loaded() override;
void init_options_list() override; void init_options_list() override;

View File

@ -101,3 +101,6 @@ void desktop_open_datadir_folder()
void fix_model_by_win10_sdk_gui(ModelObject *model_object_src, Print *print, Model *model_dst) void fix_model_by_win10_sdk_gui(ModelObject *model_object_src, Print *print, Model *model_dst)
%code%{ Slic3r::fix_model_by_win10_sdk_gui(*model_object_src, *print, *model_dst); %}; %code%{ Slic3r::fix_model_by_win10_sdk_gui(*model_object_src, *print, *model_dst); %};
void set_3DScene(SV *scene)
%code%{ Slic3r::GUI::set_3DScene((_3DScene *)wxPli_sv_2_object(aTHX_ scene, "Slic3r::Model::3DScene") ); %};

View File

@ -145,8 +145,10 @@ _constant()
%code%{ RETVAL = &THIS->skirt; %}; %code%{ RETVAL = &THIS->skirt; %};
Ref<ExtrusionEntityCollection> brim() Ref<ExtrusionEntityCollection> brim()
%code%{ RETVAL = &THIS->brim; %}; %code%{ RETVAL = &THIS->brim; %};
std::string estimated_print_time() std::string estimated_normal_print_time()
%code%{ RETVAL = THIS->estimated_print_time; %}; %code%{ RETVAL = THIS->estimated_normal_print_time; %};
std::string estimated_silent_print_time()
%code%{ RETVAL = THIS->estimated_silent_print_time; %};
PrintObjectPtrs* objects() PrintObjectPtrs* objects()
%code%{ RETVAL = &THIS->objects; %}; %code%{ RETVAL = &THIS->objects; %};