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_g => L("Used Filament (g)"),
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) {
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_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_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_box_show"}->(1);
@ -1694,6 +1702,34 @@ sub export_object_stl {
$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 {
my ($self) = @_;
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 {
$self->export_object_stl;
}, 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;
}

View File

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

View File

@ -5,7 +5,7 @@
name = Prusa Research
# Configuration version of this file. Config file will only be installed, if the config_version differs.
# This means, the server may force the Slic3r configuration to be downgraded.
config_version = 0.1.6
config_version = 0.2.0-alpha
# Where to get the updates from?
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
solid_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_spacing = 0.15
support_material_spacing = 1
@ -155,6 +155,7 @@ infill_extrusion_width = 0.7
perimeter_extrusion_width = 0.65
solid_infill_extrusion_width = 0.65
top_infill_extrusion_width = 0.6
support_material_extrusion_width = 0.55
[print:*soluble_support*]
overhangs = 1
@ -213,26 +214,18 @@ top_infill_extrusion_width = 0.4
[print:0.05mm ULTRADETAIL 0.25 nozzle]
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
external_perimeter_extrusion_width = 0
extrusion_width = 0.28
fill_density = 20%
first_layer_extrusion_width = 0.3
infill_extrusion_width = 0
infill_speed = 20
max_print_speed = 100
perimeter_extrusion_width = 0
perimeter_speed = 20
small_perimeter_speed = 15
solid_infill_extrusion_width = 0
solid_infill_speed = 20
support_material_speed = 20
top_infill_extrusion_width = 0
[print:0.05mm ULTRADETAIL 0.25 nozzle MK3]
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
fill_pattern = grid
top_infill_extrusion_width = 0.4
# XXXXXXXXXXXXXXXXXXXX
# XXX--- 0.10mm ---XXX
@ -294,7 +287,6 @@ infill_speed = 200
max_print_speed = 200
perimeter_speed = 45
solid_infill_speed = 200
top_infill_extrusion_width = 0.4
top_solid_infill_speed = 50
[print:0.10mm DETAIL 0.6 nozzle MK3]
@ -308,7 +300,6 @@ infill_speed = 200
max_print_speed = 200
perimeter_speed = 45
solid_infill_speed = 200
top_infill_extrusion_width = 0.4
top_solid_infill_speed = 50
# XXXXXXXXXXXXXXXXXXXX
@ -358,7 +349,6 @@ perimeter_acceleration = 600
perimeter_speed = 25
small_perimeter_speed = 15
solid_infill_speed = 40
support_material_extrusion_width = 0.2
top_solid_infill_speed = 30
[print:0.15mm OPTIMAL 0.6 nozzle]
@ -544,7 +534,6 @@ external_perimeter_extrusion_width = 0.6
external_perimeter_speed = 30
notes = Set your solluble extruder in Multiple Extruders > Support material/raft interface extruder
perimeter_speed = 40
support_material_extrusion_width = 0.55
support_material_interface_layers = 3
support_material_xy_spacing = 120%
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_offset = 0x0
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]
max_layer_height = 0.25
min_layer_height = 0.07
@ -935,7 +941,7 @@ retract_speed = 35
serial_port =
serial_speed = 250000
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 =
use_firmware_retraction = 0
use_relative_e_distances = 1
@ -971,7 +977,7 @@ printer_model = MK2SMM
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
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_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
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
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
default_print_profile = 0.15mm OPTIMAL
default_filament_profile = Prusa PLA
@ -1005,7 +1011,7 @@ printer_variant = 0.25
default_print_profile = 0.10mm DETAIL 0.25 nozzle
[printer:Original Prusa i3 MK2 0.6 nozzle]
inherits = *common*; *0.6nozzle*
inherits = *common*
max_layer_height = 0.35
min_layer_height = 0.1
nozzle_diameter = 0.6
@ -1020,7 +1026,7 @@ default_print_profile = 0.20mm NORMAL 0.6 nozzle
inherits = *mm-single*
[printer:Original Prusa i3 MK2 MM Single Mode 0.6 nozzle]
inherits = *mm-single*; *0.6nozzle*
inherits = *mm-single*
nozzle_diameter = 0.6
printer_variant = 0.6
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
[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
printer_variant = 0.6
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]
inherits = Original Prusa i3 MK2
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]
inherits = Original Prusa i3 MK2 0.25 nozzle
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]
inherits = Original Prusa i3 MK2 0.6 nozzle
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
# 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]
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
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
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}
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
default_print_profile = 0.15mm OPTIMAL MK3
[printer:Original Prusa i3 MK3 0.25 nozzle]
inherits = *common*
inherits = Original Prusa i3 MK3
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
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
retract_lift_below = 209
max_print_height = 210
start_gcode = M115 U3.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
max_layer_height = 0.1
min_layer_height = 0.05
printer_variant = 0.25
default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3
[printer:Original Prusa i3 MK3 0.6 nozzle]
inherits = *common*
inherits = Original Prusa i3 MK3
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
printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
retract_lift_below = 209
max_print_height = 210
start_gcode = M115 U3.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
max_layer_height = 0.35
min_layer_height = 0.1
printer_variant = 0.6
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.
[obsolete_presets]
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) {
$cur_loop ||= [ [$self->X, $self->Y] ];
push @$cur_loop, [ @$info{qw(new_X new_Y)} ];
} else {
} elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
if ($cur_loop) {
$has_cw_loops = 1 if Slic3r::Polygon->new(@$cur_loop)->is_clockwise;
$cur_loop = undef;
@ -201,7 +201,7 @@ use Slic3r::Test;
if ($info->{extruding} && $info->{dist_XY} > 0) {
$cur_loop ||= [ [$self->X, $self->Y] ];
push @$cur_loop, [ @$info{qw(new_X new_Y)} ];
} else {
} elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
if ($cur_loop) {
$has_cw_loops = 1 if Slic3r::Polygon->new_scale(@$cur_loop)->is_clockwise;
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) {
$perimeters{$self->Z}++ if !$in_loop;
$in_loop = 1;
} else {
} elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
$in_loop = 0;
}
});
@ -430,7 +430,7 @@ use Slic3r::Test;
push @seam_points, Slic3r::Point->new_scale($self->X, $self->Y);
}
$was_extruding = 1;
} else {
} elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
$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/nlopt_boilerplate.hpp)
list(APPEND LIBNEST2D_LIBRARIES ${NLopt_LIBS}
# Threads::Threads
)
# Threads::Threads
)
list(APPEND LIBNEST2D_HEADERS ${NLopt_INCLUDE_DIR})
endif()

View File

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

View File

@ -26,11 +26,20 @@ struct NfpPConfig {
/// Where to align the resulting packed pile
Alignment alignment;
Alignment starting_point;
std::function<double(const Nfp::Shapes<RawShape>&, double, double, double)>
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}),
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)
@ -39,14 +48,6 @@ template<class RawShape> class EdgeCache {
using Coord = TCoord<Vertex>;
using Edge = _Segment<Vertex>;
// enum Corners {
// BOTTOM,
// LEFT,
// RIGHT,
// TOP,
// NUM_CORNERS
// };
mutable std::vector<double> corners_;
std::vector<Edge> emap_;
@ -70,49 +71,9 @@ template<class RawShape> class EdgeCache {
void fetchCorners() const {
if(!corners_.empty()) return;
// TODO Accuracy
corners_ = distances_;
for(auto& d : corners_) {
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_;
for(auto& d : corners_) d /= full_distance_;
}
public:
@ -167,12 +128,6 @@ public:
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 {
fetchCorners();
return corners_;
@ -400,7 +355,7 @@ public:
opt::StopCriteria stopcr;
stopcr.max_iterations = 1000;
stopcr.stoplimit = 0.01;
stopcr.stoplimit = 0.001;
stopcr.type = opt::StopLimitType::RELATIVE;
opt::TOptimizer<opt::Method::L_SIMPLEX> solver(stopcr);
@ -518,11 +473,37 @@ private:
void setInitialPosition(Item& item) {
Box&& bb = item.boundingBox();
Vertex ci, cb;
Vertex ci = bb.minCorner();
Vertex cb = bin_.minCorner();
switch(config_.starting_point) {
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);
}

View File

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

View File

@ -55,6 +55,18 @@ public:
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_ ) {
bool was_packed = false;
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");
}
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()) {
// 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";
@ -403,10 +409,48 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
{
PROFILE_FUNC();
// resets time estimator
m_time_estimator.reset();
m_time_estimator.set_dialect(print.config.gcode_flavor);
// resets time estimators
m_normal_time_estimator.reset();
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
m_analyzer.reset();
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);
// Emit machine envelope limits for the Marlin firmware.
this->print_machine_envelope(file, print);
// Disable fan.
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));
@ -806,7 +853,9 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
_write(file, m_writer.postamble());
// 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.
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_weight = 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()) {
double used_filament = extruder.used_filament();
double extruded_volume = extruder.extruded_volume();
double filament_weight = extruded_volume * extruder.filament_density() * 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);
if (filament_weight > 0.) {
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;
}
_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.
_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;
}
// 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.
// Only do that if the start G-code does not already contain any M-code controlling an extruder temperature.
// M140 - Set Extruder Temperature
@ -1406,7 +1487,7 @@ void GCode::process_layer(
if (m_pressure_equalizer)
gcode = m_pressure_equalizer->process(gcode.c_str(), false);
// printf("G-code after filter:\n%s\n", out.c_str());
_write(file, gcode);
}
@ -2073,7 +2154,9 @@ void GCode::_write(FILE* file, const char *what)
// writes string to file
fwrite(gcode, 1, ::strlen(gcode), file);
// 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_brim_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()))
{}
~GCode() {}
@ -303,8 +306,10 @@ protected:
// Index of a last object copy extruded.
std::pair<const PrintObject*, Point> m_last_obj_copy;
// Time estimator
GCodeTimeEstimator m_time_estimator;
// Time estimators
GCodeTimeEstimator m_normal_time_estimator;
GCodeTimeEstimator m_silent_time_estimator;
bool m_silent_time_estimator_enabled;
// Analyzer
GCodeAnalyzer m_analyzer;
@ -322,6 +327,7 @@ protected:
void _write_format(FILE* file, const char* format, ...);
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_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
// this flag triggers first layer speeds

View File

@ -4,15 +4,20 @@
#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 MILLISEC_TO_SEC = 0.001f;
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_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_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_TRAVEL_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
static const float DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE = 1.0f; // 100 percent
@ -73,6 +78,11 @@ namespace Slic3r {
return ::sqrt(value);
}
GCodeTimeEstimator::Block::Block()
: st_synchronized(false)
{
}
float GCodeTimeEstimator::Block::move_length() const
{
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
GCodeTimeEstimator::GCodeTimeEstimator()
GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
: _mode(mode)
{
reset();
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)
{
PROFILE_FUNC();
@ -239,14 +199,167 @@ namespace Slic3r {
void GCodeTimeEstimator::calculate_time()
{
PROFILE_FUNC();
_reset_time();
_set_blocks_st_synchronize(false);
_calculate_time();
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
}
_reset_blocks();
_reset();
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
}
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)
@ -389,6 +502,21 @@ namespace Slic3r {
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)
{
_state.additional_time += timeSec;
@ -417,7 +545,7 @@ namespace Slic3r {
set_minimum_feedrate(DEFAULT_MINIMUM_FEEDRATE);
set_minimum_travel_feedrate(DEFAULT_MINIMUM_TRAVEL_FEEDRATE);
set_extrude_factor_override_percentage(DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE);
for (unsigned char a = X; a < Num_Axis; ++a)
{
EAxis axis = (EAxis)a;
@ -429,7 +557,7 @@ namespace Slic3r {
void GCodeTimeEstimator::reset()
{
_time = 0.0f;
_reset_time();
#if ENABLE_MOVE_STATS
_moves_stats.clear();
#endif // ENABLE_MOVE_STATS
@ -442,23 +570,14 @@ namespace Slic3r {
return _time;
}
std::string GCodeTimeEstimator::get_time_hms() const
std::string GCodeTimeEstimator::get_time_dhms() const
{
float timeinsecs = get_time();
int hours = (int)(timeinsecs / 3600.0f);
timeinsecs -= (float)hours * 3600.0f;
int minutes = (int)(timeinsecs / 60.0f);
timeinsecs -= (float)minutes * 60.0f;
return _get_time_dhms(get_time());
}
char buffer[64];
if (hours > 0)
::sprintf(buffer, "%dh %dm %ds", hours, minutes, (int)timeinsecs);
else if (minutes > 0)
::sprintf(buffer, "%dm %ds", minutes, (int)timeinsecs);
else
::sprintf(buffer, "%ds", (int)timeinsecs);
return buffer;
std::string GCodeTimeEstimator::get_time_minutes() const
{
return _get_time_minutes(get_time());
}
void GCodeTimeEstimator::_reset()
@ -471,6 +590,14 @@ namespace Slic3r {
set_axis_position(Z, 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()
@ -478,6 +605,14 @@ namespace Slic3r {
_blocks.clear();
}
void GCodeTimeEstimator::_set_blocks_st_synchronize(bool state)
{
for (Block& block : _blocks)
{
block.st_synchronized = state;
}
}
void GCodeTimeEstimator::_calculate_time()
{
_forward_pass();
@ -486,14 +621,18 @@ namespace Slic3r {
_time += get_additional_time();
for (const Block& block : _blocks)
for (Block& block : _blocks)
{
if (block.st_synchronized)
continue;
#if ENABLE_MOVE_STATS
float block_time = 0.0f;
block_time += block.acceleration_time();
block_time += block.cruise_time();
block_time += block.deceleration_time();
_time += block_time;
block.elapsed_time = _time;
MovesStatsMap::iterator it = _moves_stats.find(block.move_type);
if (it == _moves_stats.end())
@ -505,6 +644,7 @@ namespace Slic3r {
_time += block.acceleration_time();
_time += block.cruise_time();
_time += block.deceleration_time();
block.elapsed_time = _time;
#endif // ENABLE_MOVE_STATS
}
}
@ -642,6 +782,8 @@ namespace Slic3r {
void GCodeTimeEstimator::_processG1(const GCodeReader::GCodeLine& line)
{
increment_g1_line_id();
// updates axes positions from line
EUnits units = get_units();
float new_pos[Num_Axis];
@ -690,13 +832,16 @@ namespace Slic3r {
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]);
}
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;
_curr.abs_axis_feedrate[a] *= min_feedrate_factor;
for (unsigned char a = X; a < Num_Axis; ++a)
{
_curr.axis_feedrate[a] *= min_feedrate_factor;
_curr.abs_axis_feedrate[a] *= min_feedrate_factor;
}
}
// calculates block acceleration
@ -829,6 +974,7 @@ namespace Slic3r {
// adds block to blocks list
_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)
@ -1043,7 +1189,7 @@ namespace Slic3r {
void GCodeTimeEstimator::_simulate_st_synchronize()
{
_calculate_time();
_reset_blocks();
_set_blocks_st_synchronize(true);
}
void GCodeTimeEstimator::_forward_pass()
@ -1051,7 +1197,10 @@ namespace Slic3r {
if (_blocks.size() > 1)
{
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]);
}
}
@ -1063,6 +1212,9 @@ namespace Slic3r {
{
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]);
}
}
@ -1115,6 +1267,9 @@ namespace Slic3r {
for (Block& b : _blocks)
{
if (b.st_synchronized)
continue;
curr = next;
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
void GCodeTimeEstimator::_log_moves_stats() const
{

View File

@ -17,6 +17,12 @@ namespace Slic3r {
class GCodeTimeEstimator
{
public:
enum EMode : unsigned char
{
Normal,
Silent
};
enum EUnits : unsigned char
{
Millimeters,
@ -70,7 +76,8 @@ namespace Slic3r {
float additional_time; // s
float minimum_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:
@ -121,7 +128,6 @@ namespace Slic3r {
bool nominal_length;
};
#if ENABLE_MOVE_STATS
EMoveType move_type;
#endif // ENABLE_MOVE_STATS
@ -134,6 +140,11 @@ namespace Slic3r {
FeedrateProfile feedrate;
Trapezoid trapezoid;
float elapsed_time;
bool st_synchronized;
Block();
// Returns the length of the move covered by this block, in mm
float move_length() const;
@ -187,19 +198,34 @@ namespace Slic3r {
typedef std::map<Block::EMoveType, MoveStats> MovesStatsMap;
#endif // ENABLE_MOVE_STATS
typedef std::map<unsigned int, unsigned int> G1LineIdToBlockIdMap;
private:
EMode _mode;
GCodeReader _parser;
State _state;
Feedrates _curr;
Feedrates _prev;
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
#if ENABLE_MOVE_STATS
MovesStatsMap _moves_stats;
#endif // ENABLE_MOVE_STATS
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
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
void calculate_time_from_lines(const std::vector<std::string>& gcode_lines);
// 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()
void calculate_time();
// Process the gcode contained in the file with the given filename,
// 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
// This time estimator should have been already used to calculate the time estimate for the gcode
// contained in the given file before to call this method
bool post_process_remaining_times(const std::string& filename, float interval_sec);
// Set current position on the given axis with the given value
void set_axis_position(EAxis axis, float position);
@ -263,6 +287,10 @@ namespace Slic3r {
void set_e_local_positioning_type(EPositioningType type);
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 set_additional_time(float timeSec);
float get_additional_time() const;
@ -275,13 +303,19 @@ namespace Slic3r {
// Returns the estimated time, in seconds
float get_time() const;
// Returns the estimated time, in format HHh MMm SSs
std::string get_time_hms() const;
// Returns the estimated time, in format DDd HHh MMm SSs
std::string get_time_dhms() const;
// Returns the estimated time, in minutes (integer)
std::string get_time_minutes() const;
private:
void _reset();
void _reset_time();
void _reset_blocks();
void _set_blocks_st_synchronize(bool state);
// Calculates the time estimate
void _calculate_time();
@ -353,6 +387,12 @@ namespace Slic3r {
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
void _log_moves_stats() const;
#endif // ENABLE_MOVE_STATS

View File

@ -19,7 +19,6 @@
#include <boost/nowide/iostream.hpp>
#include <boost/algorithm/string/replace.hpp>
// #include <benchmark.h>
#include "SVG.hpp"
#include <Eigen/Dense>
@ -309,7 +308,7 @@ namespace arr {
using namespace libnest2d;
std::string toString(const Model& model) {
std::string toString(const Model& model, bool holes = true) {
std::stringstream ss;
ss << "{\n";
@ -348,17 +347,17 @@ std::string toString(const Model& model) {
// Holes:
ss << "\t\t{\n";
// for(auto h : expoly.holes) {
// ss << "\t\t\t{\n";
// for(auto v : h.points) ss << "\t\t\t\t{"
// << v.x << ", "
// << v.y << "},\n";
// {
// auto v = h.points.front();
// ss << "\t\t\t\t{" << v.x << ", " << v.y << "},\n";
// }
// ss << "\t\t\t},\n";
// }
if(holes) for(auto h : expoly.holes) {
ss << "\t\t\t{\n";
for(auto v : h.points) ss << "\t\t\t\t{"
<< v.x << ", "
<< v.y << "},\n";
{
auto v = h.points.front();
ss << "\t\t\t\t{" << v.x << ", " << v.y << "},\n";
}
ss << "\t\t\t},\n";
}
ss << "\t\t},\n";
ss << "\t},\n";
@ -477,58 +476,21 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
// Create the arranger config
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
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;
double area_max = 0;
Item *biggest = nullptr;
// Copy the references for the shapes only as the arranger expects a
// sequence of objects convertible to Item or ClipperPolygon
std::vector<std::reference_wrapper<Item>> shapes;
shapes.reserve(shapemap.size());
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)
{
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));
});
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.y)
});
} else {
// Just take the biggest item as bin... ?
bin = ShapeLike::boundingBox(biggest->transformedShape());
}
// 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
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
// handle different rotations
// arranger.useMinimumBoundigBoxRotation();
pcfg.rotations = { 0.0 };
// Magic: we will specify what is the goal of arrangement...
// In this case we override the default object function because we
// (apparently) don't care about pack efficiency and all we care is that the
// larger items go into the center of the pile and smaller items orbit it
// so the resulting pile has a circle-like shape.
// This is good for the print bed's heat profile.
// As a side effect, the arrange procedure is a lot faster (we do not need
// to calculate the convex hulls)
pcfg.object_function = [&bin](
// In this case we override the default object to make the larger items go
// into the center of the pile and smaller items orbit it so the resulting
// pile has a circle-like shape. This is good for the print bed's heat
// profile. We alse sacrafice a bit of pack efficiency for this to work. As
// a side effect, the arrange procedure is a lot faster (we do not need to
// calculate the convex hulls)
pcfg.object_function = [bin, hasbin](
NfpPlacer::Pile pile, // The currently arranged pile
double /*area*/, // Sum area of items (not needed)
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);
// We will optimize to the diameter of the circle around the bounding
// box and use the norming factor to get rid of the physical dimensions
double score = PointLike::distance(bb.minCorner(),
bb.maxCorner()) / norm;
// We get the current item that's being evaluated.
auto& sh = pile.back();
// 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
// with a large penality
if(!NfpPlacer::wouldFit(bb, bin)) score = 2*penality - score;
// with a large penality. If we would not do this, there would be only
// 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;
};
@ -602,18 +574,10 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
// Set the progress indicator for the arranger.
arranger.progressIndicator(progressind);
// std::cout << "Arranging model..." << std::endl;
// bench.start();
// Arrange and return the items with their respective indices within the
// input sequence.
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,
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) {
applyResult(result.front(), 0);
} else {
@ -658,9 +620,6 @@ bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
batch_offset += stride;
}
}
// bench.stop();
// std::cout << "Result applied in " << bench.getElapsedSec()
// << " seconds." << std::endl;
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;
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);
// 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 {
// get the (transformed) size of each instance so that we take
// into account their different transformations when packing

View File

@ -236,7 +236,8 @@ public:
PrintRegionPtrs regions;
PlaceholderParser placeholder_parser;
// 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;
std::map<size_t, float> filament_stats;
PrintState<PrintStep, psCount> state;

View File

@ -291,11 +291,11 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("hilbertcurve");
def->enum_values.push_back("archimedeanchords");
def->enum_values.push_back("octagramspiral");
def->enum_labels.push_back("Rectilinear");
def->enum_labels.push_back("Concentric");
def->enum_labels.push_back("Hilbert Curve");
def->enum_labels.push_back("Archimedean Chords");
def->enum_labels.push_back("Octagram Spiral");
def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back(L("Hilbert Curve"));
def->enum_labels.push_back(L("Archimedean Chords"));
def->enum_labels.push_back(L("Octagram Spiral"));
// solid_fill_pattern is an obsolete equivalent to external_fill_pattern.
def->aliases.push_back("solid_fill_pattern");
def->default_value = new ConfigOptionEnum<InfillPattern>(ipRectilinear);
@ -651,19 +651,19 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("hilbertcurve");
def->enum_values.push_back("archimedeanchords");
def->enum_values.push_back("octagramspiral");
def->enum_labels.push_back("Rectilinear");
def->enum_labels.push_back("Grid");
def->enum_labels.push_back("Triangles");
def->enum_labels.push_back("Stars");
def->enum_labels.push_back("Cubic");
def->enum_labels.push_back("Line");
def->enum_labels.push_back("Concentric");
def->enum_labels.push_back("Honeycomb");
def->enum_labels.push_back("3D Honeycomb");
def->enum_labels.push_back("Gyroid");
def->enum_labels.push_back("Hilbert Curve");
def->enum_labels.push_back("Archimedean Chords");
def->enum_labels.push_back("Octagram Spiral");
def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Grid"));
def->enum_labels.push_back(L("Triangles"));
def->enum_labels.push_back(L("Stars"));
def->enum_labels.push_back(L("Cubic"));
def->enum_labels.push_back(L("Line"));
def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back(L("Honeycomb"));
def->enum_labels.push_back(L("3D Honeycomb"));
def->enum_labels.push_back(L("Gyroid"));
def->enum_labels.push_back(L("Hilbert Curve"));
def->enum_labels.push_back(L("Archimedean Chords"));
def->enum_labels.push_back(L("Octagram Spiral"));
def->default_value = new ConfigOptionEnum<InfillPattern>(ipStars);
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("Machinekit");
def->enum_labels.push_back("Smoothie");
def->enum_labels.push_back("No extrusion");
def->default_value = new ConfigOptionEnum<GCodeFlavor>(gcfMarlin);
def->enum_labels.push_back(L("No extrusion"));
def->default_value = new ConfigOptionEnum<GCodeFlavor>(gcfRepRap);
def = this->add("infill_acceleration", coFloat);
def->label = L("Infill");
@ -892,6 +892,12 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
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 {
std::string name;
@ -901,75 +907,82 @@ PrintConfigDef::PrintConfigDef()
};
std::vector<AxisDefault> axes {
// name, max_feedrate, max_acceleration, max_jerk
{ "x", { 200., 200. }, { 1000., 1000. }, { 10., 10. } },
{ "y", { 200., 200. }, { 1000., 1000. }, { 10., 10. } },
{ "z", { 12., 12. }, { 200., 200. }, { 0.4, 0.4 } },
{ "e", { 120., 120. }, { 5000., 5000. }, { 2.5, 2.5 } }
{ "x", { 500., 200. }, { 9000., 1000. }, { 10. , 10. } },
{ "y", { 500., 200. }, { 9000., 1000. }, { 10. , 10. } },
{ "z", { 12., 12. }, { 500., 200. }, { 0.2, 0.4 } },
{ "e", { 120., 120. }, { 10000., 5000. }, { 2.5, 2.5 } }
};
for (const AxisDefault &axis : axes) {
std::string axis_upper = boost::to_upper_copy<std::string>(axis.name);
// Add the machine feedrate limits for XYZE axes. (M203)
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->tooltip = (boost::format(L("Maximum feedrate of the %1% axis")) % axis_upper).str();
def->sidetext = L("mm/s");
def->min = 0;
def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats(axis.max_feedrate);
// Add the machine acceleration limits for XYZE axes (M201)
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->tooltip = (boost::format(L("Maximum acceleration of the %1% axis")) % axis_upper).str();
def->sidetext = L("mm/s²");
def->min = 0;
def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats(axis.max_acceleration);
// Add the machine jerk limits for XYZE axes (M205)
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->tooltip = (boost::format(L("Maximum jerk of the %1% axis")) % axis_upper).str();
def->sidetext = L("mm/s");
def->min = 0;
def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats(axis.max_jerk);
}
}
// M205 S... [mm/sec]
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->tooltip = L("Minimum feedrate when extruding") + " (M205 S)";
def->sidetext = L("mm/s");
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]
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->tooltip = L("Minimum travel feedrate") + " (M205 T)";
def->sidetext = L("mm/s");
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]
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->tooltip = L("Maximum acceleration when extruding") + " (M204 S)";
def->sidetext = L("mm/s²");
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]
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->tooltip = L("Maximum acceleration when retracting") + " (M204 T)";
def->sidetext = L("mm/s²");
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->label = L("Max");
@ -1392,10 +1405,10 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("nearest");
def->enum_values.push_back("aligned");
def->enum_values.push_back("rear");
def->enum_labels.push_back("Random");
def->enum_labels.push_back("Nearest");
def->enum_labels.push_back("Aligned");
def->enum_labels.push_back("Rear");
def->enum_labels.push_back(L("Random"));
def->enum_labels.push_back(L("Nearest"));
def->enum_labels.push_back(L("Aligned"));
def->enum_labels.push_back(L("Rear"));
def->default_value = new ConfigOptionEnum<SeamPosition>(spAligned);
#if 0
@ -1608,7 +1621,7 @@ PrintConfigDef::PrintConfigDef()
def->label = L("Single Extruder Multi Material");
def->tooltip = L("The printer multiplexes filaments into a single hot end.");
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->label = L("Generate support material");
@ -1658,8 +1671,8 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
def->enum_values.push_back("0");
def->enum_values.push_back("0.2");
def->enum_labels.push_back("0 (soluble)");
def->enum_labels.push_back("0.2 (detachable)");
def->enum_labels.push_back((boost::format("0 (%1%)") % L("soluble")).str());
def->enum_labels.push_back((boost::format("0.2 (%1%)") % L("detachable")).str());
def->default_value = new ConfigOptionFloat(0.2);
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-grid");
def->enum_values.push_back("honeycomb");
def->enum_labels.push_back("rectilinear");
def->enum_labels.push_back("rectilinear grid");
def->enum_labels.push_back("honeycomb");
def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Rectilinear grid"));
def->enum_labels.push_back(L("Honeycomb"));
def->default_value = new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear);
def = this->add("support_material_spacing", coFloat);

View File

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

View File

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

View File

@ -1686,7 +1686,7 @@ bool _3DScene::LegendTexture::generate(const GCodePreviewData& preview_data, con
m_data.clear();
// 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);
unsigned int items_count = (unsigned int)items.size();

View File

@ -45,6 +45,22 @@ namespace Slic3r { namespace GUI {
set_undo_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();
}
@ -77,7 +93,7 @@ namespace Slic3r { namespace GUI {
wxString Field::get_tooltip_text(const wxString& default_string)
{
wxString tooltip_text("");
wxString tooltip = L_str(m_opt.tooltip);
wxString tooltip = _(m_opt.tooltip);
if (tooltip.length() > 0)
tooltip_text = tooltip + "(" + _(L("default")) + ": " +
(boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") +
@ -161,10 +177,10 @@ namespace Slic3r { namespace GUI {
case coFloat:
{
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.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);
break;
}
@ -174,10 +190,8 @@ namespace Slic3r { namespace GUI {
case coStrings:
{
const ConfigOptionStrings *vec = static_cast<const ConfigOptionStrings*>(m_opt.default_value);
if (vec == nullptr || vec->empty()) break;
if (vec->size() > 1)
break;
text_value = vec->values.at(0);
if (vec == nullptr || vec->empty()) break; //for the case of empty default value
text_value = vec->get_at(m_opt_idx);
break;
}
default:
@ -259,7 +273,7 @@ void CheckBox::BUILD() {
bool check_value = m_opt.type == coBool ?
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;
auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size);
@ -365,7 +379,7 @@ void Choice::BUILD() {
}
else{
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);
}
set_selection();
@ -418,7 +432,7 @@ void Choice::set_selection()
break;
}
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;
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.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);
// // recast as a wxWindow to fit the calling convention
@ -675,6 +689,22 @@ boost::any& PointCtrl::get_value()
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
} // Slic3r

View File

@ -95,6 +95,7 @@ public:
/// Copy of ConfigOption for deduction purposes
const ConfigOptionDef m_opt {ConfigOptionDef()};
const t_config_option_key m_opt_id;//! {""};
int m_opt_idx = 0;
/// Sets a value for this control.
/// subclasses should overload with a specific version
@ -384,6 +385,34 @@ public:
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
} // Slic3r

View File

@ -56,8 +56,9 @@
#include "../Utils/PresetUpdater.hpp"
#include "../Config/Snapshot.hpp"
#include "libslic3r/I18N.hpp"
#include "3DScene.hpp"
#include "libslic3r/I18N.hpp"
namespace Slic3r { namespace GUI {
@ -110,6 +111,7 @@ wxNotebook *g_wxTabPanel = nullptr;
AppConfig *g_AppConfig = nullptr;
PresetBundle *g_PresetBundle= nullptr;
PresetUpdater *g_PresetUpdater = nullptr;
_3DScene *g_3DScene = nullptr;
wxColour g_color_label_modified;
wxColour g_color_label_sys;
wxColour g_color_label_default;
@ -118,6 +120,9 @@ std::vector<Tab *> g_tabs_list;
wxLocale* g_wxLocale;
wxFont g_small_font;
wxFont g_bold_font;
std::shared_ptr<ConfigOptionsGroup> m_optgroup;
double m_brim_width = 0.0;
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(); }
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.
Slic3r::I18N::set_translate_callback(libslic3r_translate_callback);
init_label_colours();
init_fonts();
}
void set_main_frame(wxFrame *main_frame)
@ -185,6 +201,11 @@ void set_preset_updater(PresetUpdater *updater)
g_PresetUpdater = updater;
}
void set_3DScene(_3DScene *scene)
{
g_3DScene = scene;
}
std::vector<Tab *>& get_tabs_list()
{
return g_tabs_list;
@ -675,6 +696,14 @@ void set_label_clr_sys(const wxColour& clr) {
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() {
return g_color_label_default;
}

View File

@ -11,7 +11,7 @@
class wxApp;
class wxWindow;
class wxFrame;
class wxWindow;
class wxFont;
class wxMenuBar;
class wxNotebook;
class wxComboCtrl;
@ -32,6 +32,7 @@ class AppConfig;
class PresetUpdater;
class DynamicPrintConfig;
class TabIface;
class _3DScene;
#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_preset_bundle(PresetBundle *preset_bundle);
void set_preset_updater(PresetUpdater *updater);
void set_3DScene(_3DScene *scene);
AppConfig* get_app_config();
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_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);
// 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)));
} else if (opt.gui_type.compare("slider") == 0) {
} 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 {
switch (opt.type) {
case coFloatOrPercent:
@ -86,7 +88,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
if (!this->m_disabled)
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_to_sys_btn->Hide();
}
@ -199,7 +201,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
ConfigOptionDef option = opt.opt;
// add label if any
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
// wxString str_label = (option.label == "Top" || option.label == "Bottom") ?
// 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
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);
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 retval{ L_str(option.opt.label), L_str(option.opt.tooltip) };
Line retval{ _(option.opt.label), _(option.opt.tooltip) };
Option tmp(option);
tmp.opt.label = std::string("");
retval.append_option(tmp);

View File

@ -127,9 +127,15 @@ public:
inline void enable() { for (auto& field : m_fields) field.second->enable(); }
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) :
m_parent(_parent), title(title), m_is_tab_opt(is_tab_opt), staticbox(title!="") {
sizer = (staticbox ? new wxStaticBoxSizer(new wxStaticBox(_parent, wxID_ANY, title), wxVERTICAL) : new wxBoxSizer(wxVERTICAL));
m_parent(_parent), title(title), m_show_modified_btns(is_tab_opt), staticbox(title!="") {
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;
if (label_width != 0) num_columns++;
if (extra_column != nullptr) num_columns++;
@ -156,7 +162,7 @@ protected:
bool m_disabled {false};
wxGridSizer* m_grid_sizer {nullptr};
// "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
// 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",
"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",
"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());
}
@ -505,6 +510,9 @@ Preset& PresetCollection::load_external_preset(
// Insert a new profile.
Preset &preset = this->load_preset(path, new_name, std::move(cfg), select);
preset.is_external = true;
if (&this->get_selected_preset() == &preset)
this->get_edited_preset().is_external = true;
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.
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:
// 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.

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;
inherits = inherits_values[idx];
compatible_printers_condition = compatible_printers_condition_values[idx];
if (is_external) {
if (is_external)
presets.load_external_preset(name_or_path, name,
config.opt_string((i_group == 0) ? "print_settings_id" : "printer_settings_id", true),
config);
presets.update_edited_preset_is_external(true);
} else
else
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.
inherits = inherits_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.update_edited_preset_is_external(true);
} else
else
this->filaments.load_preset(this->filaments.path_from_name(name), name, config).save();
this->filament_presets.clear();
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];
// Load all filament presets, but only select the first one in the preset dialog.
Preset *loaded = nullptr;
if (is_external) {
if (is_external)
loaded = &this->filaments.load_external_preset(name_or_path, name,
(i < old_filament_profile_names->values.size()) ? old_filament_profile_names->values[i] : "",
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.
// Therefore this block should only be called for a single extruder.
char suffix[64];

View File

@ -1605,6 +1605,22 @@ void TabPrinter::build()
optgroup = page->new_optgroup(_(L("Firmware")));
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->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);
}
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
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
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("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) {
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());
m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
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_disable_tree_sel_changed_event = 0;
have_selection = 1;

View File

@ -316,6 +316,9 @@ public:
class TabPrinter : public Tab
{
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:
wxButton* m_serial_test_btn;
wxButton* m_octoprint_host_test_btn;
@ -333,6 +336,7 @@ public:
void update() override;
void update_serial_ports();
void extruders_count_changed(size_t extruders_count);
PageShp build_kinematics_page();
void build_extruder_pages();
void on_preset_loaded() 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)
%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; %};
Ref<ExtrusionEntityCollection> brim()
%code%{ RETVAL = &THIS->brim; %};
std::string estimated_print_time()
%code%{ RETVAL = THIS->estimated_print_time; %};
std::string estimated_normal_print_time()
%code%{ RETVAL = THIS->estimated_normal_print_time; %};
std::string estimated_silent_print_time()
%code%{ RETVAL = THIS->estimated_silent_print_time; %};
PrintObjectPtrs* objects()
%code%{ RETVAL = &THIS->objects; %};