diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm
index 4d18a81ae..ac62d6337 100644
--- a/lib/Slic3r/GUI/MainFrame.pm
+++ b/lib/Slic3r/GUI/MainFrame.pm
@@ -116,6 +116,7 @@ sub new {
         wxTheApp->{app_config}->save;
         $self->{plater}->{print} = undef if($self->{plater});
         Slic3r::GUI::_3DScene::remove_all_canvases();
+        Slic3r::GUI::deregister_on_request_update_callback();
         # propagate event
         $event->Skip;
     });
diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index c0718c77b..a0eef72fe 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -128,8 +128,8 @@ sub new {
         }
         $_->set_scaling_factor($scale) for @{ $model_object->instances };
         
-        $self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%");        
-        $object->transform_thumbnail($self->{model}, $obj_idx);
+        $self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%");
+#        $object->transform_thumbnail($self->{model}, $obj_idx);
     
         #update print and start background processing
         $self->{print}->add_model_object($model_object, $obj_idx);
@@ -144,7 +144,7 @@ sub new {
         my ($angle_z) = @_;
         $self->rotate(rad2deg($angle_z), Z, 'absolute');
     };
-    
+
     # callback to update object's geometry info while using gizmos
     my $on_update_geometry_info = sub {
         my ($size_x, $size_y, $size_z, $scale_factor) = @_;
@@ -202,19 +202,22 @@ sub new {
 
         Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{canvas3D}, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{preview3D}->canvas, $self->{canvas3D}); });
     }
+
+    Slic3r::GUI::register_on_request_update_callback(sub { $self->schedule_background_process; });
     
-    # Initialize 2D preview canvas
-    $self->{canvas} = Slic3r::GUI::Plater::2D->new($self->{preview_notebook}, wxDefaultSize, $self->{objects}, $self->{model}, $self->{config});
-    $self->{preview_notebook}->AddPage($self->{canvas}, L('2D'));
-    $self->{canvas}->on_select_object($on_select_object);
-    $self->{canvas}->on_double_click($on_double_click);
-    $self->{canvas}->on_right_click(sub { $on_right_click->($self->{canvas}, @_); });
-    $self->{canvas}->on_instances_moved($on_instances_moved);
+#    # Initialize 2D preview canvas
+#    $self->{canvas} = Slic3r::GUI::Plater::2D->new($self->{preview_notebook}, wxDefaultSize, $self->{objects}, $self->{model}, $self->{config});
+#    $self->{preview_notebook}->AddPage($self->{canvas}, L('2D'));
+#    $self->{canvas}->on_select_object($on_select_object);
+#    $self->{canvas}->on_double_click($on_double_click);
+#    $self->{canvas}->on_right_click(sub { $on_right_click->($self->{canvas}, @_); });
+#    $self->{canvas}->on_instances_moved($on_instances_moved);
     
     # Initialize 3D toolpaths preview
     if ($Slic3r::GUI::have_OpenGL) {
         $self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{gcode_preview_data}, $self->{config});
         Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 1);
+        Slic3r::GUI::_3DScene::enable_dynamic_background($self->{preview3D}->canvas, 1);
         Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{preview3D}->canvas, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{canvas3D}, $self->{preview3D}->canvas); });
         $self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview'));
         $self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1;
@@ -312,6 +315,9 @@ sub new {
         my ($list, $event) = @_;
         if ($event->GetKeyCode == WXK_TAB) {
             $list->Navigate($event->ShiftDown ? &Wx::wxNavigateBackward : &Wx::wxNavigateForward);
+        } elsif ($event->GetKeyCode == WXK_DELETE ||
+                ($event->GetKeyCode == WXK_BACK && &Wx::wxMAC) ) {
+            $self->remove;
         } else {
             $event->Skip;
         }
@@ -401,7 +407,8 @@ sub new {
     
     $_->SetDropTarget(Slic3r::GUI::Plater::DropTarget->new($self))
         for grep defined($_),
-            $self, $self->{canvas}, $self->{canvas3D}, $self->{preview3D}, $self->{list};
+            $self, $self->{canvas3D}, $self->{preview3D}, $self->{list};
+#            $self, $self->{canvas}, $self->{canvas3D}, $self->{preview3D}, $self->{list};
     
     EVT_COMMAND($self, -1, $PROGRESS_BAR_EVENT, sub {
         my ($self, $event) = @_;
@@ -432,7 +439,7 @@ sub new {
         });
     }
     
-    $self->{canvas}->update_bed_size;
+#    $self->{canvas}->update_bed_size;
     if ($self->{canvas3D}) {
         Slic3r::GUI::_3DScene::set_bed_shape($self->{canvas3D}, $self->{config}->bed_shape);
         Slic3r::GUI::_3DScene::zoom_to_bed($self->{canvas3D});
@@ -847,8 +854,8 @@ sub load_model_objects {
     
         $self->{list}->SetItem($obj_idx, 1, $model_object->instances_count);
         $self->{list}->SetItem($obj_idx, 2, ($model_object->instances->[0]->scaling_factor * 100) . "%");
-    
-        $self->reset_thumbnail($obj_idx);
+
+#        $self->reset_thumbnail($obj_idx);
     }
     $self->arrange if $need_arrange;
     $self->update;
@@ -1057,7 +1064,7 @@ sub rotate {
             $inst->set_rotation($rotation);
             Slic3r::GUI::_3DScene::update_gizmos_data($self->{canvas3D}) if ($self->{canvas3D});            
         }
-        $object->transform_thumbnail($self->{model}, $obj_idx);
+#        $object->transform_thumbnail($self->{model}, $obj_idx);
     } else {
         # rotation around X and Y needs to be performed on mesh
         # so we first apply any Z rotation
@@ -1067,9 +1074,9 @@ sub rotate {
         }
         $model_object->rotate(deg2rad($angle), $axis);
         
-        # realign object to Z = 0
-        $model_object->center_around_origin;
-        $self->reset_thumbnail($obj_idx);
+#        # realign object to Z = 0
+#        $model_object->center_around_origin;
+#        $self->reset_thumbnail($obj_idx);
     }
     
     # update print and start background processing
@@ -1097,9 +1104,9 @@ sub mirror {
     
     $model_object->mirror($axis);
     
-    # realign object to Z = 0
-    $model_object->center_around_origin;
-    $self->reset_thumbnail($obj_idx);
+#    # realign object to Z = 0
+#    $model_object->center_around_origin;
+#    $self->reset_thumbnail($obj_idx);
         
     # update print and start background processing
     $self->stop_background_process;
@@ -1149,7 +1156,7 @@ sub changescale {
         #FIXME Scale the layer height profile when $axis == Z?
         #FIXME Scale the layer height ranges $axis == Z?
         # object was already aligned to Z = 0, so no need to realign it
-        $self->reset_thumbnail($obj_idx);
+#        $self->reset_thumbnail($obj_idx);
     } else {
         my $scale;
         if ($tosize) {
@@ -1173,7 +1180,7 @@ sub changescale {
             $range->[1] *= $variation;
         }
         $_->set_scaling_factor($scale) for @{ $model_object->instances };
-        $object->transform_thumbnail($self->{model}, $obj_idx);
+#        $object->transform_thumbnail($self->{model}, $obj_idx);
     }
     
     # update print and start background processing
@@ -1281,6 +1288,11 @@ sub async_apply_config {
         $self->{gcode_preview_data}->reset;
         $self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
         $self->{preview3D}->reload_print if $self->{preview3D};
+
+        # We also need to reload 3D scene because of the wipe tower preview box
+        if ($self->{config}->wipe_tower) {
+	       Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1) if $self->{canvas3D}
+        }
     }
 }
 
@@ -1493,6 +1505,9 @@ sub on_process_completed {
     return if $error;
     $self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
     $self->{preview3D}->reload_print if $self->{preview3D};
+
+    # in case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth:
+    Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 1);
     
     # if we have an export filename, start a new thread for exporting G-code
     if ($self->{export_gcode_output_file}) {
@@ -1595,7 +1610,7 @@ sub print_info_box_show {
     my ($self, $show) = @_;
     my $scrolled_window_panel = $self->{scrolled_window_panel}; 
     my $scrolled_window_sizer = $self->{scrolled_window_sizer};
-    return if $scrolled_window_sizer->IsShown(2) == $show;
+    return if (!$show && ($scrolled_window_sizer->IsShown(2) == $show));
 
     if ($show) {
         my $print_info_sizer = $self->{print_info_sizer};
@@ -1804,10 +1819,10 @@ sub _get_export_file {
     return $output_file;
 }
 
-sub reset_thumbnail {
-    my ($self, $obj_idx) = @_;
-    $self->{objects}[$obj_idx]->thumbnail(undef);
-}
+#sub reset_thumbnail {
+#    my ($self, $obj_idx) = @_;
+#    $self->{objects}[$obj_idx]->thumbnail(undef);
+#}
 
 # this method gets called whenever print center is changed or the objects' bounding box changes
 # (i.e. when an object is added/removed/moved/rotated/scaled)
@@ -1831,7 +1846,9 @@ sub update {
         $self->resume_background_process;
     }
 
-    $self->{canvas}->reload_scene if $self->{canvas};
+    $self->print_info_box_show(0);
+    
+#    $self->{canvas}->reload_scene if $self->{canvas};
     my $selections = $self->collect_selections;
     Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
     Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 0);
@@ -1888,7 +1905,7 @@ sub on_config_change {
     foreach my $opt_key (@{$self->{config}->diff($config)}) {
         $self->{config}->set($opt_key, $config->get($opt_key));
         if ($opt_key eq 'bed_shape') {
-            $self->{canvas}->update_bed_size;
+#            $self->{canvas}->update_bed_size;
             Slic3r::GUI::_3DScene::set_bed_shape($self->{canvas3D}, $self->{config}->bed_shape) if $self->{canvas3D};
             Slic3r::GUI::_3DScene::set_bed_shape($self->{preview3D}->canvas, $self->{config}->bed_shape) if $self->{preview3D};
             $update_scheduled = 1;
@@ -1948,7 +1965,7 @@ sub list_item_deselected {
     $self->{_lecursor} = Wx::BusyCursor->new();
     if ($self->{list}->GetFirstSelected == -1) {
         $self->select_object(undef);
-        $self->{canvas}->Refresh;
+#        $self->{canvas}->Refresh;
         Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas3D}) if $self->{canvas3D};
         Slic3r::GUI::_3DScene::render($self->{canvas3D}) if $self->{canvas3D};
     }
@@ -1961,7 +1978,7 @@ sub list_item_selected {
     $self->{_lecursor} = Wx::BusyCursor->new();
     my $obj_idx = $event->GetIndex;
     $self->select_object($obj_idx);
-    $self->{canvas}->Refresh;
+#    $self->{canvas}->Refresh;
     if ($self->{canvas3D}) {
         my $selections = $self->collect_selections;
         Slic3r::GUI::_3DScene::update_volumes_selection($self->{canvas3D}, \@$selections);
@@ -2058,19 +2075,19 @@ sub object_settings_dialog {
 	$self->pause_background_process;
 	$dlg->ShowModal;
 	
-    # update thumbnail since parts may have changed
-    if ($dlg->PartsChanged) {
-	    # recenter and re-align to Z = 0
-	    $model_object->center_around_origin;
-        $self->reset_thumbnail($obj_idx);
-    }
+#    # update thumbnail since parts may have changed
+#    if ($dlg->PartsChanged) {
+#	    # recenter and re-align to Z = 0
+#	    $model_object->center_around_origin;
+#        $self->reset_thumbnail($obj_idx);
+#    }
 	
 	# update print
 	if ($dlg->PartsChanged || $dlg->PartSettingsChanged) {
 	    $self->stop_background_process;
         $self->{print}->reload_object($obj_idx);
         $self->schedule_background_process;
-        $self->{canvas}->reload_scene if $self->{canvas};
+#        $self->{canvas}->reload_scene if $self->{canvas};
         my $selections = $self->collect_selections;
         Slic3r::GUI::_3DScene::set_objects_selections($self->{canvas3D}, \@$selections);
         Slic3r::GUI::_3DScene::reload_scene($self->{canvas3D}, 0);
@@ -2356,48 +2373,48 @@ package Slic3r::GUI::Plater::Object;
 use Moo;
 
 has 'name'                  => (is => 'rw', required => 1);
-has 'thumbnail'             => (is => 'rw'); # ExPolygon::Collection in scaled model units with no transforms
-has 'transformed_thumbnail' => (is => 'rw');
-has 'instance_thumbnails'   => (is => 'ro', default => sub { [] });  # array of ExPolygon::Collection objects, each one representing the actual placed thumbnail of each instance in pixel units
+#has 'thumbnail'             => (is => 'rw'); # ExPolygon::Collection in scaled model units with no transforms
+#has 'transformed_thumbnail' => (is => 'rw');
+#has 'instance_thumbnails'   => (is => 'ro', default => sub { [] });  # array of ExPolygon::Collection objects, each one representing the actual placed thumbnail of each instance in pixel units
 has 'selected'              => (is => 'rw', default => sub { 0 });
 
-sub make_thumbnail {
-    my ($self, $model, $obj_idx) = @_;
-    # make method idempotent
-    $self->thumbnail->clear;
-    # raw_mesh is the non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes.
-    my $mesh = $model->objects->[$obj_idx]->raw_mesh;
-#FIXME The "correct" variant could be extremely slow.
-#    if ($mesh->facets_count <= 5000) {
-#        # remove polygons with area <= 1mm
-#        my $area_threshold = Slic3r::Geometry::scale 1;
-#        $self->thumbnail->append(
-#            grep $_->area >= $area_threshold,
-#            @{ $mesh->horizontal_projection },   # horizontal_projection returns scaled expolygons
-#        );
-#        $self->thumbnail->simplify(0.5);
-#    } else {
-        my $convex_hull = Slic3r::ExPolygon->new($mesh->convex_hull);
-        $self->thumbnail->append($convex_hull);
-#    }
-    return $self->thumbnail;
-}
-
-sub transform_thumbnail {
-    my ($self, $model, $obj_idx) = @_;
-    
-    return unless defined $self->thumbnail;
-    
-    my $model_object = $model->objects->[$obj_idx];
-    my $model_instance = $model_object->instances->[0];
-    
-    # the order of these transformations MUST be the same everywhere, including
-    # in Slic3r::Print->add_model_object()
-    my $t = $self->thumbnail->clone;
-    $t->rotate($model_instance->rotation, Slic3r::Point->new(0,0));
-    $t->scale($model_instance->scaling_factor);
-    
-    $self->transformed_thumbnail($t);
-}
+#sub make_thumbnail {
+#    my ($self, $model, $obj_idx) = @_;
+#    # make method idempotent
+#    $self->thumbnail->clear;
+#    # raw_mesh is the non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes.
+#    my $mesh = $model->objects->[$obj_idx]->raw_mesh;
+##FIXME The "correct" variant could be extremely slow.
+##    if ($mesh->facets_count <= 5000) {
+##        # remove polygons with area <= 1mm
+##        my $area_threshold = Slic3r::Geometry::scale 1;
+##        $self->thumbnail->append(
+##            grep $_->area >= $area_threshold,
+##            @{ $mesh->horizontal_projection },   # horizontal_projection returns scaled expolygons
+##        );
+##        $self->thumbnail->simplify(0.5);
+##    } else {
+#        my $convex_hull = Slic3r::ExPolygon->new($mesh->convex_hull);
+#        $self->thumbnail->append($convex_hull);
+##    }
+#    return $self->thumbnail;
+#}
+#
+#sub transform_thumbnail {
+#    my ($self, $model, $obj_idx) = @_;
+#    
+#    return unless defined $self->thumbnail;
+#    
+#    my $model_object = $model->objects->[$obj_idx];
+#    my $model_instance = $model_object->instances->[0];
+#    
+#    # the order of these transformations MUST be the same everywhere, including
+#    # in Slic3r::Print->add_model_object()
+#    my $t = $self->thumbnail->clone;
+#    $t->rotate($model_instance->rotation, Slic3r::Point->new(0,0));
+#    $t->scale($model_instance->scaling_factor);
+#    
+#    $self->transformed_thumbnail($t);
+#}
 
 1;
diff --git a/lib/Slic3r/GUI/Plater/3DPreview.pm b/lib/Slic3r/GUI/Plater/3DPreview.pm
index 9ed2374ec..09c2f0b8c 100644
--- a/lib/Slic3r/GUI/Plater/3DPreview.pm
+++ b/lib/Slic3r/GUI/Plater/3DPreview.pm
@@ -25,6 +25,7 @@ sub new {
     # init GUI elements
     my $canvas = Slic3r::GUI::3DScene->new($self);
     Slic3r::GUI::_3DScene::enable_shader($canvas, 1);
+    Slic3r::GUI::_3DScene::set_config($canvas, $config);
     $self->canvas($canvas);
     my $slider_low = Wx::Slider->new(
         $self, -1,
@@ -365,16 +366,8 @@ sub load_print {
         if ($self->gcode_preview_data->empty) {
             # load skirt and brim
             Slic3r::GUI::_3DScene::set_print($self->canvas, $self->print);
-            Slic3r::GUI::_3DScene::load_print_toolpaths($self->canvas);
-            Slic3r::GUI::_3DScene::load_wipe_tower_toolpaths($self->canvas, \@colors);
-            foreach my $object (@{$self->print->objects}) {
-                Slic3r::GUI::_3DScene::load_print_object_toolpaths($self->canvas, $object, \@colors);
-                # Show the objects in very transparent color.
-                #my @volume_ids = $self->canvas->load_object($object->model_object);
-                #$self->canvas->volumes->[$_]->color->[3] = 0.2 for @volume_ids;
-            }
+            Slic3r::GUI::_3DScene::load_preview($self->canvas, \@colors);
             $self->show_hide_ui_elements('simple');
-            Slic3r::GUI::_3DScene::reset_legend_texture();
         } else {
             $self->{force_sliders_full_range} = (Slic3r::GUI::_3DScene::get_volumes_count($self->canvas) == 0);
             Slic3r::GUI::_3DScene::set_print($self->canvas, $self->print);
diff --git a/resources/icons/printers/PrusaResearch_MK3MM2.png b/resources/icons/printers/PrusaResearch_MK3MM2.png
deleted file mode 100644
index 1068bfc10..000000000
Binary files a/resources/icons/printers/PrusaResearch_MK3MM2.png and /dev/null differ
diff --git a/resources/icons/printers/PrusaResearch_MK3MMU2.png b/resources/icons/printers/PrusaResearch_MK3MMU2.png
new file mode 100644
index 000000000..eb5dccf08
Binary files /dev/null and b/resources/icons/printers/PrusaResearch_MK3MMU2.png differ
diff --git a/resources/localization/Slic3rPE.pot b/resources/localization/Slic3rPE.pot
index 029e7c4b2..7fa65fc5e 100644
--- a/resources/localization/Slic3rPE.pot
+++ b/resources/localization/Slic3rPE.pot
@@ -3,12 +3,13 @@
 # This file is distributed under the same license as the PACKAGE package.
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 #
+#: xs/src/slic3r/GUI/Tab.cpp:1721
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-06-26 11:11+0200\n"
+"POT-Creation-Date: 2018-07-23 12:06+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -32,8 +33,8 @@ msgstr ""
 msgid "Rectangular"
 msgstr ""
 
-#: xs/src/slic3r/GUI/BedShapeDialog.cpp:50 xs/src/slic3r/GUI/Tab.cpp:1745
-#: lib/Slic3r/GUI/Plater.pm:477
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:50 xs/src/slic3r/GUI/Tab.cpp:1826
+#: lib/Slic3r/GUI/Plater.pm:498
 msgid "Size"
 msgstr ""
 
@@ -56,33 +57,33 @@ msgid "Circular"
 msgstr ""
 
 #: xs/src/slic3r/GUI/BedShapeDialog.cpp:65
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:87
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:439
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:453
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:88
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:446
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:460
 #: xs/src/slic3r/GUI/RammingChart.cpp:81
 #: xs/src/slic3r/GUI/WipeTowerDialog.cpp:79
-#: xs/src/libslic3r/PrintConfig.cpp:130 xs/src/libslic3r/PrintConfig.cpp:173
-#: xs/src/libslic3r/PrintConfig.cpp:181 xs/src/libslic3r/PrintConfig.cpp:229
-#: xs/src/libslic3r/PrintConfig.cpp:240 xs/src/libslic3r/PrintConfig.cpp:354
-#: xs/src/libslic3r/PrintConfig.cpp:365 xs/src/libslic3r/PrintConfig.cpp:384
-#: xs/src/libslic3r/PrintConfig.cpp:497 xs/src/libslic3r/PrintConfig.cpp:851
-#: xs/src/libslic3r/PrintConfig.cpp:871 xs/src/libslic3r/PrintConfig.cpp:879
-#: xs/src/libslic3r/PrintConfig.cpp:937 xs/src/libslic3r/PrintConfig.cpp:955
-#: xs/src/libslic3r/PrintConfig.cpp:973 xs/src/libslic3r/PrintConfig.cpp:1035
-#: xs/src/libslic3r/PrintConfig.cpp:1152 xs/src/libslic3r/PrintConfig.cpp:1160
-#: xs/src/libslic3r/PrintConfig.cpp:1202 xs/src/libslic3r/PrintConfig.cpp:1211
-#: xs/src/libslic3r/PrintConfig.cpp:1221 xs/src/libslic3r/PrintConfig.cpp:1229
-#: xs/src/libslic3r/PrintConfig.cpp:1237 xs/src/libslic3r/PrintConfig.cpp:1323
-#: xs/src/libslic3r/PrintConfig.cpp:1529 xs/src/libslic3r/PrintConfig.cpp:1599
-#: xs/src/libslic3r/PrintConfig.cpp:1633 xs/src/libslic3r/PrintConfig.cpp:1829
-#: xs/src/libslic3r/PrintConfig.cpp:1836 xs/src/libslic3r/PrintConfig.cpp:1843
-#: xs/src/libslic3r/PrintConfig.cpp:1857 xs/src/libslic3r/PrintConfig.cpp:1867
-#: xs/src/libslic3r/PrintConfig.cpp:1877
+#: xs/src/libslic3r/PrintConfig.cpp:133 xs/src/libslic3r/PrintConfig.cpp:181
+#: xs/src/libslic3r/PrintConfig.cpp:189 xs/src/libslic3r/PrintConfig.cpp:237
+#: xs/src/libslic3r/PrintConfig.cpp:248 xs/src/libslic3r/PrintConfig.cpp:363
+#: xs/src/libslic3r/PrintConfig.cpp:374 xs/src/libslic3r/PrintConfig.cpp:393
+#: xs/src/libslic3r/PrintConfig.cpp:531 xs/src/libslic3r/PrintConfig.cpp:890
+#: xs/src/libslic3r/PrintConfig.cpp:1002 xs/src/libslic3r/PrintConfig.cpp:1010
+#: xs/src/libslic3r/PrintConfig.cpp:1068 xs/src/libslic3r/PrintConfig.cpp:1086
+#: xs/src/libslic3r/PrintConfig.cpp:1104 xs/src/libslic3r/PrintConfig.cpp:1166
+#: xs/src/libslic3r/PrintConfig.cpp:1176 xs/src/libslic3r/PrintConfig.cpp:1292
+#: xs/src/libslic3r/PrintConfig.cpp:1300 xs/src/libslic3r/PrintConfig.cpp:1342
+#: xs/src/libslic3r/PrintConfig.cpp:1351 xs/src/libslic3r/PrintConfig.cpp:1361
+#: xs/src/libslic3r/PrintConfig.cpp:1369 xs/src/libslic3r/PrintConfig.cpp:1377
+#: xs/src/libslic3r/PrintConfig.cpp:1463 xs/src/libslic3r/PrintConfig.cpp:1669
+#: xs/src/libslic3r/PrintConfig.cpp:1739 xs/src/libslic3r/PrintConfig.cpp:1773
+#: xs/src/libslic3r/PrintConfig.cpp:1969 xs/src/libslic3r/PrintConfig.cpp:1976
+#: xs/src/libslic3r/PrintConfig.cpp:1983 xs/src/libslic3r/PrintConfig.cpp:2015
+#: xs/src/libslic3r/PrintConfig.cpp:2025 xs/src/libslic3r/PrintConfig.cpp:2035
 msgid "mm"
 msgstr ""
 
 #: xs/src/slic3r/GUI/BedShapeDialog.cpp:66
-#: xs/src/libslic3r/PrintConfig.cpp:494
+#: xs/src/libslic3r/PrintConfig.cpp:528
 msgid "Diameter"
 msgstr ""
 
@@ -93,7 +94,7 @@ msgid ""
 msgstr ""
 
 #: xs/src/slic3r/GUI/BedShapeDialog.cpp:71
-#: xs/src/libslic3r/GCode/PreviewData.cpp:170
+#: xs/src/libslic3r/GCode/PreviewData.cpp:175
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:102
 msgid "Custom"
 msgstr ""
@@ -124,7 +125,7 @@ msgid ""
 msgstr ""
 
 #: xs/src/slic3r/GUI/BedShapeDialog.hpp:44
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:402
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:409
 msgid "Bed Shape"
 msgstr ""
 
@@ -210,7 +211,7 @@ msgstr ""
 msgid "printer"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:49 xs/src/slic3r/GUI/Tab.cpp:758
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:49 xs/src/slic3r/GUI/Tab.cpp:730
 msgid "vendor"
 msgstr ""
 
@@ -242,70 +243,74 @@ msgstr ""
 msgid "Activate"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:96 xs/src/slic3r/GUI/GUI.cpp:323
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:96 xs/src/slic3r/GUI/GUI.cpp:349
 msgid "Configuration Snapshots"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:87
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:88
 msgid "nozzle"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:105
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:89
+msgid "(default)"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:108
 msgid "Select all"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:106
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:109
 msgid "Select none"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:212
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:218
 #, possible-c-format
 msgid "Welcome to the Slic3r %s"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:212
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:218
 msgid "Welcome"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:218 xs/src/slic3r/GUI/GUI.cpp:320
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:224 xs/src/slic3r/GUI/GUI.cpp:346
 #, possible-c-format
 msgid "Run %s"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:220
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:226
 #, possible-c-format
 msgid ""
 "Hello, welcome to Slic3r Prusa Edition! This %s helps you with the initial "
 "configuration; just a few settings and you will be ready to print."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:224
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:230
 msgid ""
 "Remove user profiles - install from scratch (a snapshot will be taken "
 "beforehand)"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:245
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:252
 msgid "Other vendors"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:247
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:254
 msgid "Custom setup"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:271
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:278
 msgid "Automatic updates"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:271
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:278
 msgid "Updates"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:279 xs/src/slic3r/GUI/Preferences.cpp:59
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:286 xs/src/slic3r/GUI/Preferences.cpp:59
 msgid "Check for application updates"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:282 xs/src/slic3r/GUI/Preferences.cpp:61
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:289 xs/src/slic3r/GUI/Preferences.cpp:61
 msgid ""
 "If enabled, Slic3r checks for new versions of Slic3r PE online. When a new "
 "version becomes available a notification is displayed at the next "
@@ -313,11 +318,11 @@ msgid ""
 "notification mechanisms, no automatic installation is done."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:286 xs/src/slic3r/GUI/Preferences.cpp:67
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:293 xs/src/slic3r/GUI/Preferences.cpp:67
 msgid "Update built-in Presets automatically"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:289 xs/src/slic3r/GUI/Preferences.cpp:69
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:296 xs/src/slic3r/GUI/Preferences.cpp:69
 msgid ""
 "If enabled, Slic3r downloads updates of built-in system presets in the "
 "background. These updates are downloaded into a separate temporary location. "
@@ -325,134 +330,134 @@ msgid ""
 "startup."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:290
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:297
 msgid ""
 "Updates are never applied without user's consent and never overwrite user's "
 "customized settings."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:295
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:302
 msgid ""
 "Additionally a backup snapshot of the whole configuration is created before "
 "an update is applied."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:302
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:309
 msgid "Other Vendors"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:304
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:311
 msgid "Pick another vendor supported by Slic3r PE:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:363
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:370
 msgid "Firmware Type"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:363 xs/src/slic3r/GUI/Tab.cpp:1628
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:370 xs/src/slic3r/GUI/Tab.cpp:1606
 msgid "Firmware"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:367
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:374
 msgid "Choose the type of firmware used by your printer."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:402
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:409
 msgid "Bed Shape and Size"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:405
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:412
 msgid "Set the shape of your printer's bed."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:419
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:426
 msgid "Filament and Nozzle Diameters"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:419
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:426
 msgid "Print Diameters"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:435
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:442
 msgid "Enter the diameter of your printer's hot end nozzle."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:438
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:445
 msgid "Nozzle Diameter:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:448
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:455
 msgid "Enter the diameter of your filament."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:449
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:456
 msgid ""
 "Good precision is required, so use a caliper and do multiple measurements "
 "along the filament, then compute the average."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:452
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:459
 msgid "Filament Diameter:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:470
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:477
 msgid "Extruder and Bed Temperatures"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:470
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:477
 msgid "Temperatures"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:486
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:493
 msgid "Enter the temperature needed for extruding your filament."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:487
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:494
 msgid "A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:490
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:497
 msgid "Extrusion Temperature:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:491
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:505
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:498
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:512
 msgid "°C"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:500
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:507
 msgid ""
 "Enter the bed temperature needed for getting your filament to stick to your "
 "heated bed."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:501
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:508
 msgid ""
 "A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have "
 "no heated bed."
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:504
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:511
 msgid "Bed Temperature:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:817
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:824
 msgid "< &Back"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:818
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:825
 msgid "&Next >"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:819
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:826
 msgid "&Finish"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:889
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:896
 msgid "Configuration Wizard"
 msgstr ""
 
-#: xs/src/slic3r/GUI/ConfigWizard.cpp:891
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:898
 msgid "Configuration Assistant"
 msgstr ""
 
@@ -526,138 +531,138 @@ msgstr ""
 msgid "Confirmation"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GLCanvas3D.cpp:1990
+#: xs/src/slic3r/GUI/GLCanvas3D.cpp:2308
 msgid "Detected object outside print volume"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:208
+#: xs/src/slic3r/GUI/GUI.cpp:233
 msgid "Array of language names and identifiers should have the same size."
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:219
+#: xs/src/slic3r/GUI/GUI.cpp:244
 msgid "Select the language"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:219
+#: xs/src/slic3r/GUI/GUI.cpp:244
 msgid "Language"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:281 xs/src/libslic3r/PrintConfig.cpp:187
+#: xs/src/slic3r/GUI/GUI.cpp:306 xs/src/libslic3r/PrintConfig.cpp:195
 msgid "Default"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:323
+#: xs/src/slic3r/GUI/GUI.cpp:349
 msgid "Inspect / activate configuration snapshots"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:324
+#: xs/src/slic3r/GUI/GUI.cpp:350
 msgid "Take Configuration Snapshot"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:324
+#: xs/src/slic3r/GUI/GUI.cpp:350
 msgid "Capture a configuration snapshot"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:327 xs/src/slic3r/GUI/Preferences.cpp:9
+#: xs/src/slic3r/GUI/GUI.cpp:353 xs/src/slic3r/GUI/Preferences.cpp:9
 msgid "Preferences"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:327
+#: xs/src/slic3r/GUI/GUI.cpp:353
 msgid "Application preferences"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:328
+#: xs/src/slic3r/GUI/GUI.cpp:354
 msgid "Change Application Language"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:330
+#: xs/src/slic3r/GUI/GUI.cpp:356
 msgid "Flash printer firmware"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:330
+#: xs/src/slic3r/GUI/GUI.cpp:356
 msgid "Upload a firmware image into an Arduino based printer"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:342
+#: xs/src/slic3r/GUI/GUI.cpp:368
 msgid "Taking configuration snapshot"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:342
+#: xs/src/slic3r/GUI/GUI.cpp:368
 msgid "Snapshot name"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:380
+#: xs/src/slic3r/GUI/GUI.cpp:406
 msgid "Application will be restarted"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:380
+#: xs/src/slic3r/GUI/GUI.cpp:406
 msgid "Attention!"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:396
+#: xs/src/slic3r/GUI/GUI.cpp:422
 msgid "&Configuration"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:420
+#: xs/src/slic3r/GUI/GUI.cpp:446
 msgid "You have unsaved changes "
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:420
+#: xs/src/slic3r/GUI/GUI.cpp:446
 msgid ". Discard changes and continue anyway?"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:421
+#: xs/src/slic3r/GUI/GUI.cpp:447
 msgid "Unsaved Presets"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:629
+#: xs/src/slic3r/GUI/GUI.cpp:655
 msgid "Notice"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:634
+#: xs/src/slic3r/GUI/GUI.cpp:660
 msgid "Attempt to free unreferenced scalar"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:636 xs/src/slic3r/GUI/WipeTowerDialog.cpp:39
+#: xs/src/slic3r/GUI/GUI.cpp:662 xs/src/slic3r/GUI/WipeTowerDialog.cpp:39
 #: xs/src/slic3r/GUI/WipeTowerDialog.cpp:321
 msgid "Warning"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:825
+#: xs/src/slic3r/GUI/GUI.cpp:859
 msgid "Support"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:828
+#: xs/src/slic3r/GUI/GUI.cpp:862
 msgid "Select what kind of support do you need"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:829 xs/src/libslic3r/GCode/PreviewData.cpp:157
+#: xs/src/slic3r/GUI/GUI.cpp:863 xs/src/libslic3r/GCode/PreviewData.cpp:162
 msgid "None"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:830 xs/src/libslic3r/PrintConfig.cpp:1516
+#: xs/src/slic3r/GUI/GUI.cpp:864 xs/src/libslic3r/PrintConfig.cpp:1656
 msgid "Support on build plate only"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:831
+#: xs/src/slic3r/GUI/GUI.cpp:865
 msgid "Everywhere"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:843 xs/src/slic3r/GUI/Tab.cpp:872
+#: xs/src/slic3r/GUI/GUI.cpp:877 xs/src/slic3r/GUI/Tab.cpp:844
 msgid "Brim"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:845
+#: xs/src/slic3r/GUI/GUI.cpp:879
 msgid ""
 "This flag enables the brim that will be printed around each object on the "
 "first layer."
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:854
+#: xs/src/slic3r/GUI/GUI.cpp:888
 msgid "Purging volumes"
 msgstr ""
 
-#: xs/src/slic3r/GUI/GUI.cpp:896
+#: xs/src/slic3r/GUI/GUI.cpp:930
 msgid "Export print config"
 msgstr ""
 
@@ -669,248 +674,249 @@ msgstr ""
 msgid "Slic3r has encountered an error"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:103
+#: xs/src/slic3r/GUI/Tab.cpp:84
 msgid "Save current "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:104
+#: xs/src/slic3r/GUI/Tab.cpp:85
 msgid "Delete this preset"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:116
+#: xs/src/slic3r/GUI/Tab.cpp:97
 msgid ""
 "Hover the cursor over buttons to find more information \n"
 "or click this button."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:744
+#: xs/src/slic3r/GUI/Tab.cpp:716
 msgid "It's a default preset."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:745
+#: xs/src/slic3r/GUI/Tab.cpp:717
 msgid "It's a system preset."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:746
+#: xs/src/slic3r/GUI/Tab.cpp:718
 msgid "Current preset is inherited from "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:751
+#: xs/src/slic3r/GUI/Tab.cpp:723
 msgid "It can't be deleted or modified. "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:752
+#: xs/src/slic3r/GUI/Tab.cpp:724
 msgid ""
 "Any modifications should be saved as a new preset inherited from this one. "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:753
+#: xs/src/slic3r/GUI/Tab.cpp:725
 msgid "To do that please specify a new name for the preset."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:757
+#: xs/src/slic3r/GUI/Tab.cpp:729
 msgid "Additional information:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:765
+#: xs/src/slic3r/GUI/Tab.cpp:737
 msgid "printer model"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:767
+#: xs/src/slic3r/GUI/Tab.cpp:739
 msgid "default print profile"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:770
+#: xs/src/slic3r/GUI/Tab.cpp:742
 msgid "default filament profile"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:814
+#: xs/src/slic3r/GUI/Tab.cpp:786
 msgid "Layers and perimeters"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:815 xs/src/libslic3r/PrintConfig.cpp:847
+#: xs/src/slic3r/GUI/Tab.cpp:787 xs/src/libslic3r/PrintConfig.cpp:886
 msgid "Layer height"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:819
+#: xs/src/slic3r/GUI/Tab.cpp:791
 msgid "Vertical shells"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:830
+#: xs/src/slic3r/GUI/Tab.cpp:802
 msgid "Horizontal shells"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:831 xs/src/libslic3r/PrintConfig.cpp:1422
+#: xs/src/slic3r/GUI/Tab.cpp:803 xs/src/libslic3r/PrintConfig.cpp:1562
 msgid "Solid layers"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:836
+#: xs/src/slic3r/GUI/Tab.cpp:808
 msgid "Quality (slower slicing)"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:843 xs/src/slic3r/GUI/Tab.cpp:857
-#: xs/src/slic3r/GUI/Tab.cpp:951 xs/src/slic3r/GUI/Tab.cpp:954
-#: xs/src/slic3r/GUI/Tab.cpp:1303 xs/src/slic3r/GUI/Tab.cpp:1631
-#: xs/src/libslic3r/PrintConfig.cpp:107 xs/src/libslic3r/PrintConfig.cpp:237
-#: xs/src/libslic3r/PrintConfig.cpp:799 xs/src/libslic3r/PrintConfig.cpp:1863
+#: xs/src/slic3r/GUI/Tab.cpp:815 xs/src/slic3r/GUI/Tab.cpp:829
+#: xs/src/slic3r/GUI/Tab.cpp:923 xs/src/slic3r/GUI/Tab.cpp:926
+#: xs/src/slic3r/GUI/Tab.cpp:1276 xs/src/slic3r/GUI/Tab.cpp:1625
+#: xs/src/libslic3r/PrintConfig.cpp:110 xs/src/libslic3r/PrintConfig.cpp:245
+#: xs/src/libslic3r/PrintConfig.cpp:833 xs/src/libslic3r/PrintConfig.cpp:2021
 msgid "Advanced"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:847 xs/src/slic3r/GUI/Tab.cpp:848
-#: xs/src/slic3r/GUI/Tab.cpp:1155 xs/src/libslic3r/PrintConfig.cpp:87
-#: xs/src/libslic3r/PrintConfig.cpp:276 xs/src/libslic3r/PrintConfig.cpp:551
-#: xs/src/libslic3r/PrintConfig.cpp:565 xs/src/libslic3r/PrintConfig.cpp:603
-#: xs/src/libslic3r/PrintConfig.cpp:744 xs/src/libslic3r/PrintConfig.cpp:754
-#: xs/src/libslic3r/PrintConfig.cpp:772 xs/src/libslic3r/PrintConfig.cpp:790
-#: xs/src/libslic3r/PrintConfig.cpp:809 xs/src/libslic3r/PrintConfig.cpp:1371
-#: xs/src/libslic3r/PrintConfig.cpp:1388
+#: xs/src/slic3r/GUI/Tab.cpp:819 xs/src/slic3r/GUI/Tab.cpp:820
+#: xs/src/slic3r/GUI/Tab.cpp:1127 xs/src/libslic3r/PrintConfig.cpp:90
+#: xs/src/libslic3r/PrintConfig.cpp:284 xs/src/libslic3r/PrintConfig.cpp:585
+#: xs/src/libslic3r/PrintConfig.cpp:599 xs/src/libslic3r/PrintConfig.cpp:637
+#: xs/src/libslic3r/PrintConfig.cpp:778 xs/src/libslic3r/PrintConfig.cpp:788
+#: xs/src/libslic3r/PrintConfig.cpp:806 xs/src/libslic3r/PrintConfig.cpp:824
+#: xs/src/libslic3r/PrintConfig.cpp:843 xs/src/libslic3r/PrintConfig.cpp:1511
+#: xs/src/libslic3r/PrintConfig.cpp:1528
 msgid "Infill"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:853
+#: xs/src/slic3r/GUI/Tab.cpp:825
 msgid "Reducing printing time"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:865
+#: xs/src/slic3r/GUI/Tab.cpp:837
 msgid "Skirt and brim"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:866 xs/src/libslic3r/GCode/PreviewData.cpp:166
+#: xs/src/slic3r/GUI/Tab.cpp:838 xs/src/libslic3r/GCode/PreviewData.cpp:171
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:98
 msgid "Skirt"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:875 xs/src/slic3r/GUI/Tab.cpp:876
-#: xs/src/libslic3r/PrintConfig.cpp:220 xs/src/libslic3r/PrintConfig.cpp:1138
-#: xs/src/libslic3r/PrintConfig.cpp:1488 xs/src/libslic3r/PrintConfig.cpp:1495
-#: xs/src/libslic3r/PrintConfig.cpp:1507 xs/src/libslic3r/PrintConfig.cpp:1517
-#: xs/src/libslic3r/PrintConfig.cpp:1525 xs/src/libslic3r/PrintConfig.cpp:1540
-#: xs/src/libslic3r/PrintConfig.cpp:1561 xs/src/libslic3r/PrintConfig.cpp:1572
-#: xs/src/libslic3r/PrintConfig.cpp:1588 xs/src/libslic3r/PrintConfig.cpp:1597
-#: xs/src/libslic3r/PrintConfig.cpp:1606 xs/src/libslic3r/PrintConfig.cpp:1617
-#: xs/src/libslic3r/PrintConfig.cpp:1631 xs/src/libslic3r/PrintConfig.cpp:1639
-#: xs/src/libslic3r/PrintConfig.cpp:1640 xs/src/libslic3r/PrintConfig.cpp:1649
-#: xs/src/libslic3r/PrintConfig.cpp:1657 xs/src/libslic3r/PrintConfig.cpp:1671
-#: xs/src/libslic3r/GCode/PreviewData.cpp:167
+#: xs/src/slic3r/GUI/Tab.cpp:847 xs/src/slic3r/GUI/Tab.cpp:848
+#: xs/src/libslic3r/PrintConfig.cpp:228 xs/src/libslic3r/PrintConfig.cpp:1278
+#: xs/src/libslic3r/PrintConfig.cpp:1628 xs/src/libslic3r/PrintConfig.cpp:1635
+#: xs/src/libslic3r/PrintConfig.cpp:1647 xs/src/libslic3r/PrintConfig.cpp:1657
+#: xs/src/libslic3r/PrintConfig.cpp:1665 xs/src/libslic3r/PrintConfig.cpp:1680
+#: xs/src/libslic3r/PrintConfig.cpp:1701 xs/src/libslic3r/PrintConfig.cpp:1712
+#: xs/src/libslic3r/PrintConfig.cpp:1728 xs/src/libslic3r/PrintConfig.cpp:1737
+#: xs/src/libslic3r/PrintConfig.cpp:1746 xs/src/libslic3r/PrintConfig.cpp:1757
+#: xs/src/libslic3r/PrintConfig.cpp:1771 xs/src/libslic3r/PrintConfig.cpp:1779
+#: xs/src/libslic3r/PrintConfig.cpp:1780 xs/src/libslic3r/PrintConfig.cpp:1789
+#: xs/src/libslic3r/PrintConfig.cpp:1797 xs/src/libslic3r/PrintConfig.cpp:1811
+#: xs/src/libslic3r/GCode/PreviewData.cpp:172
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:99
 msgid "Support material"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:881
+#: xs/src/slic3r/GUI/Tab.cpp:853
 msgid "Raft"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:885
+#: xs/src/slic3r/GUI/Tab.cpp:857
 msgid "Options for support material and raft"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:899 xs/src/libslic3r/PrintConfig.cpp:119
-#: xs/src/libslic3r/PrintConfig.cpp:307 xs/src/libslic3r/PrintConfig.cpp:698
-#: xs/src/libslic3r/PrintConfig.cpp:810 xs/src/libslic3r/PrintConfig.cpp:1072
-#: xs/src/libslic3r/PrintConfig.cpp:1309 xs/src/libslic3r/PrintConfig.cpp:1359
-#: xs/src/libslic3r/PrintConfig.cpp:1410 xs/src/libslic3r/PrintConfig.cpp:1731
+#: xs/src/slic3r/GUI/Tab.cpp:871 xs/src/libslic3r/PrintConfig.cpp:122
+#: xs/src/libslic3r/PrintConfig.cpp:315 xs/src/libslic3r/PrintConfig.cpp:732
+#: xs/src/libslic3r/PrintConfig.cpp:844 xs/src/libslic3r/PrintConfig.cpp:1212
+#: xs/src/libslic3r/PrintConfig.cpp:1449 xs/src/libslic3r/PrintConfig.cpp:1499
+#: xs/src/libslic3r/PrintConfig.cpp:1550 xs/src/libslic3r/PrintConfig.cpp:1871
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:77
 msgid "Speed"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:900
+#: xs/src/slic3r/GUI/Tab.cpp:872
 msgid "Speed for print moves"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:912
+#: xs/src/slic3r/GUI/Tab.cpp:884
 msgid "Speed for non-print moves"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:915
+#: xs/src/slic3r/GUI/Tab.cpp:887
 msgid "Modifiers"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:918
+#: xs/src/slic3r/GUI/Tab.cpp:890
 msgid "Acceleration control (advanced)"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:925
+#: xs/src/slic3r/GUI/Tab.cpp:897
 msgid "Autospeed (advanced)"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:931
+#: xs/src/slic3r/GUI/Tab.cpp:903
 msgid "Multiple Extruders"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:932 xs/src/slic3r/GUI/Tab.cpp:1473
-#: xs/src/libslic3r/PrintConfig.cpp:337 xs/src/libslic3r/PrintConfig.cpp:765
-#: xs/src/libslic3r/PrintConfig.cpp:1051 xs/src/libslic3r/PrintConfig.cpp:1380
-#: xs/src/libslic3r/PrintConfig.cpp:1553 xs/src/libslic3r/PrintConfig.cpp:1579
+#: xs/src/slic3r/GUI/Tab.cpp:904 xs/src/slic3r/GUI/Tab.cpp:1451
+#: xs/src/libslic3r/PrintConfig.cpp:345 xs/src/libslic3r/PrintConfig.cpp:799
+#: xs/src/libslic3r/PrintConfig.cpp:1191 xs/src/libslic3r/PrintConfig.cpp:1520
+#: xs/src/libslic3r/PrintConfig.cpp:1693 xs/src/libslic3r/PrintConfig.cpp:1719
+#: xs/src/libslic3r/PrintConfig.cpp:1995 xs/src/libslic3r/PrintConfig.cpp:2004
 msgid "Extruders"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:939
+#: xs/src/slic3r/GUI/Tab.cpp:911
 msgid "Ooze prevention"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:943 xs/src/libslic3r/GCode/PreviewData.cpp:169
+#: xs/src/slic3r/GUI/Tab.cpp:915 xs/src/libslic3r/GCode/PreviewData.cpp:174
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:101
 msgid "Wipe tower"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:955
+#: xs/src/slic3r/GUI/Tab.cpp:927
 msgid "Extrusion width"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:965
+#: xs/src/slic3r/GUI/Tab.cpp:937
 msgid "Overlap"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:968
+#: xs/src/slic3r/GUI/Tab.cpp:940
 msgid "Flow"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:971
+#: xs/src/slic3r/GUI/Tab.cpp:943
 msgid "Other"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:978
+#: xs/src/slic3r/GUI/Tab.cpp:950
 msgid "Output options"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:979
+#: xs/src/slic3r/GUI/Tab.cpp:951
 msgid "Sequential printing"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:981
+#: xs/src/slic3r/GUI/Tab.cpp:953
 msgid "Extruder clearance (mm)"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:990
+#: xs/src/slic3r/GUI/Tab.cpp:962
 msgid "Output file"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:996 xs/src/libslic3r/PrintConfig.cpp:1094
+#: xs/src/slic3r/GUI/Tab.cpp:968 xs/src/libslic3r/PrintConfig.cpp:1234
 msgid "Post-processing scripts"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1002 xs/src/slic3r/GUI/Tab.cpp:1003
-#: xs/src/slic3r/GUI/Tab.cpp:1352 xs/src/slic3r/GUI/Tab.cpp:1353
-#: xs/src/slic3r/GUI/Tab.cpp:1674 xs/src/slic3r/GUI/Tab.cpp:1675
+#: xs/src/slic3r/GUI/Tab.cpp:974 xs/src/slic3r/GUI/Tab.cpp:975
+#: xs/src/slic3r/GUI/Tab.cpp:1329 xs/src/slic3r/GUI/Tab.cpp:1330
+#: xs/src/slic3r/GUI/Tab.cpp:1668 xs/src/slic3r/GUI/Tab.cpp:1669
 msgid "Notes"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1009 xs/src/slic3r/GUI/Tab.cpp:1360
-#: xs/src/slic3r/GUI/Tab.cpp:1681
+#: xs/src/slic3r/GUI/Tab.cpp:981 xs/src/slic3r/GUI/Tab.cpp:1337
+#: xs/src/slic3r/GUI/Tab.cpp:1675
 msgid "Dependencies"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1010 xs/src/slic3r/GUI/Tab.cpp:1361
-#: xs/src/slic3r/GUI/Tab.cpp:1682
+#: xs/src/slic3r/GUI/Tab.cpp:982 xs/src/slic3r/GUI/Tab.cpp:1338
+#: xs/src/slic3r/GUI/Tab.cpp:1676
 msgid "Profile dependencies"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1011 xs/src/slic3r/GUI/Tab.cpp:1362
-#: xs/src/slic3r/GUI/Tab.cpp:2261 xs/src/libslic3r/PrintConfig.cpp:144
+#: xs/src/slic3r/GUI/Tab.cpp:983 xs/src/slic3r/GUI/Tab.cpp:1339
+#: xs/src/slic3r/GUI/Tab.cpp:2364 xs/src/libslic3r/PrintConfig.cpp:147
 msgid "Compatible printers"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1044
+#: xs/src/slic3r/GUI/Tab.cpp:1016
 #, no-c-format
 msgid ""
 "The Spiral Vase mode requires:\n"
@@ -923,11 +929,11 @@ msgid ""
 "Shall I adjust those settings in order to enable Spiral Vase?"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1051
+#: xs/src/slic3r/GUI/Tab.cpp:1023
 msgid "Spiral Vase"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1072
+#: xs/src/slic3r/GUI/Tab.cpp:1044
 msgid ""
 "The Wipe Tower currently supports the non-soluble supports only\n"
 "if they are printed with the current extruder without triggering a tool "
@@ -938,11 +944,11 @@ msgid ""
 "Shall I adjust those settings in order to enable the Wipe Tower?"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1076 xs/src/slic3r/GUI/Tab.cpp:1093
+#: xs/src/slic3r/GUI/Tab.cpp:1048 xs/src/slic3r/GUI/Tab.cpp:1065
 msgid "Wipe Tower"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1090
+#: xs/src/slic3r/GUI/Tab.cpp:1062
 msgid ""
 "For the Wipe Tower to work with the soluble supports, the support layers\n"
 "need to be synchronized with the object layers.\n"
@@ -950,7 +956,7 @@ msgid ""
 "Shall I synchronize support layers in order to enable the Wipe Tower?"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1108
+#: xs/src/slic3r/GUI/Tab.cpp:1080
 msgid ""
 "Supports work better, if the following feature is enabled:\n"
 "- Detect bridging perimeters\n"
@@ -958,15 +964,15 @@ msgid ""
 "Shall I adjust those settings for supports?"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1111
+#: xs/src/slic3r/GUI/Tab.cpp:1083
 msgid "Support Generator"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1153
+#: xs/src/slic3r/GUI/Tab.cpp:1125
 msgid "The "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1153
+#: xs/src/slic3r/GUI/Tab.cpp:1125
 #, no-c-format
 msgid ""
 " infill pattern is not supposed to work at 100% density.\n"
@@ -974,343 +980,384 @@ msgid ""
 "Shall I switch to rectilinear fill pattern?"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1258 xs/src/slic3r/GUI/Tab.cpp:1259
-#: lib/Slic3r/GUI/Plater.pm:433
+#: xs/src/slic3r/GUI/Tab.cpp:1231 xs/src/slic3r/GUI/Tab.cpp:1232
+#: lib/Slic3r/GUI/Plater.pm:454
 msgid "Filament"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1266
+#: xs/src/slic3r/GUI/Tab.cpp:1239
 msgid "Temperature "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1267 xs/src/libslic3r/PrintConfig.cpp:336
+#: xs/src/slic3r/GUI/Tab.cpp:1240 xs/src/libslic3r/PrintConfig.cpp:344
 msgid "Extruder"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1272
+#: xs/src/slic3r/GUI/Tab.cpp:1245
 msgid "Bed"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1277
+#: xs/src/slic3r/GUI/Tab.cpp:1250
 msgid "Cooling"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1278 xs/src/libslic3r/PrintConfig.cpp:1006
-#: xs/src/libslic3r/PrintConfig.cpp:1801
+#: xs/src/slic3r/GUI/Tab.cpp:1251 xs/src/libslic3r/PrintConfig.cpp:1137
+#: xs/src/libslic3r/PrintConfig.cpp:1941
 msgid "Enable"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1289
+#: xs/src/slic3r/GUI/Tab.cpp:1262
 msgid "Fan settings"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1290
+#: xs/src/slic3r/GUI/Tab.cpp:1263
 msgid "Fan speed"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1298
+#: xs/src/slic3r/GUI/Tab.cpp:1271
 msgid "Cooling thresholds"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1304
+#: xs/src/slic3r/GUI/Tab.cpp:1277
 msgid "Filament properties"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1308
+#: xs/src/slic3r/GUI/Tab.cpp:1281
 msgid "Print speed override"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1318
+#: xs/src/slic3r/GUI/Tab.cpp:1291
 msgid "Toolchange parameters with single extruder MM printers"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1322
+#: xs/src/slic3r/GUI/Tab.cpp:1299
 msgid "Ramming"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1324
+#: xs/src/slic3r/GUI/Tab.cpp:1301
 msgid "Ramming settings"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1339 xs/src/slic3r/GUI/Tab.cpp:1637
+#: xs/src/slic3r/GUI/Tab.cpp:1316 xs/src/slic3r/GUI/Tab.cpp:1631
 msgid "Custom G-code"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1340 xs/src/slic3r/GUI/Tab.cpp:1638
-#: xs/src/libslic3r/PrintConfig.cpp:1450 xs/src/libslic3r/PrintConfig.cpp:1465
+#: xs/src/slic3r/GUI/Tab.cpp:1317 xs/src/slic3r/GUI/Tab.cpp:1632
+#: xs/src/libslic3r/PrintConfig.cpp:1590 xs/src/libslic3r/PrintConfig.cpp:1605
 msgid "Start G-code"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1346 xs/src/slic3r/GUI/Tab.cpp:1644
-#: xs/src/libslic3r/PrintConfig.cpp:246 xs/src/libslic3r/PrintConfig.cpp:256
+#: xs/src/slic3r/GUI/Tab.cpp:1323 xs/src/slic3r/GUI/Tab.cpp:1638
+#: xs/src/libslic3r/PrintConfig.cpp:254 xs/src/libslic3r/PrintConfig.cpp:264
 msgid "End G-code"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1441 xs/src/slic3r/GUI/Preferences.cpp:17
+#: xs/src/slic3r/GUI/Tab.cpp:1419 xs/src/slic3r/GUI/Preferences.cpp:17
 msgid "General"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1442
+#: xs/src/slic3r/GUI/Tab.cpp:1420
 msgid "Size and coordinates"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1444 xs/src/libslic3r/PrintConfig.cpp:34
+#: xs/src/slic3r/GUI/Tab.cpp:1422 xs/src/libslic3r/PrintConfig.cpp:37
 msgid "Bed shape"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1446 xs/src/slic3r/GUI/Tab.cpp:2229
+#: xs/src/slic3r/GUI/Tab.cpp:1424 xs/src/slic3r/GUI/Tab.cpp:2332
 msgid " Set "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1469
+#: xs/src/slic3r/GUI/Tab.cpp:1447
 msgid "Capabilities"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1474
+#: xs/src/slic3r/GUI/Tab.cpp:1452
 msgid "Number of extruders of the printer."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1499
+#: xs/src/slic3r/GUI/Tab.cpp:1477
 msgid "USB/Serial connection"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1500 xs/src/libslic3r/PrintConfig.cpp:1301
+#: xs/src/slic3r/GUI/Tab.cpp:1478 xs/src/libslic3r/PrintConfig.cpp:1441
 msgid "Serial port"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1505
+#: xs/src/slic3r/GUI/Tab.cpp:1483
 msgid "Rescan serial ports"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1514 xs/src/slic3r/GUI/Tab.cpp:1561
+#: xs/src/slic3r/GUI/Tab.cpp:1492 xs/src/slic3r/GUI/Tab.cpp:1539
 msgid "Test"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1527
+#: xs/src/slic3r/GUI/Tab.cpp:1505
 msgid "Connection to printer works correctly."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1527 xs/src/slic3r/GUI/Tab.cpp:1571
+#: xs/src/slic3r/GUI/Tab.cpp:1505 xs/src/slic3r/GUI/Tab.cpp:1549
 msgid "Success!"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1530
+#: xs/src/slic3r/GUI/Tab.cpp:1508
 msgid "Connection failed."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1542 xs/src/slic3r/Utils/OctoPrint.cpp:110
+#: xs/src/slic3r/GUI/Tab.cpp:1520 xs/src/slic3r/Utils/OctoPrint.cpp:110
 msgid "OctoPrint upload"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1545 xs/src/slic3r/GUI/Tab.cpp:1594
+#: xs/src/slic3r/GUI/Tab.cpp:1523 xs/src/slic3r/GUI/Tab.cpp:1572
 msgid " Browse "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1571
+#: xs/src/slic3r/GUI/Tab.cpp:1549
 msgid "Connection to OctoPrint works correctly."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1574
+#: xs/src/slic3r/GUI/Tab.cpp:1552
 msgid "Could not connect to OctoPrint"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1574
+#: xs/src/slic3r/GUI/Tab.cpp:1552
 msgid "Note: OctoPrint version at least 1.1.0 is required."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1600
+#: xs/src/slic3r/GUI/Tab.cpp:1578
 msgid "Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1601
+#: xs/src/slic3r/GUI/Tab.cpp:1579
 msgid "Open CA certificate file"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1615
+#: xs/src/slic3r/GUI/Tab.cpp:1593
 msgid ""
 "HTTPS CA file is optional. It is only needed if you use HTTPS with a self-"
 "signed certificate."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1650 xs/src/libslic3r/PrintConfig.cpp:48
+#: xs/src/slic3r/GUI/Tab.cpp:1644 xs/src/libslic3r/PrintConfig.cpp:51
 msgid "Before layer change G-code"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1656 xs/src/libslic3r/PrintConfig.cpp:836
+#: xs/src/slic3r/GUI/Tab.cpp:1650 xs/src/libslic3r/PrintConfig.cpp:875
 msgid "After layer change G-code"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1662 xs/src/libslic3r/PrintConfig.cpp:1708
+#: xs/src/slic3r/GUI/Tab.cpp:1656 xs/src/libslic3r/PrintConfig.cpp:1848
 msgid "Tool change G-code"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1668
+#: xs/src/slic3r/GUI/Tab.cpp:1662
 msgid "Between objects G-code (for sequential printing)"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1720 xs/src/slic3r/GUI/Tab.cpp:1728
+#: xs/src/slic3r/GUI/Tab.cpp:1717 xs/src/slic3r/GUI/Tab.cpp:1778
+#: xs/src/slic3r/GUI/Tab.cpp:2037 xs/src/libslic3r/PrintConfig.cpp:920
+#: xs/src/libslic3r/PrintConfig.cpp:929 xs/src/libslic3r/PrintConfig.cpp:938
+#: xs/src/libslic3r/PrintConfig.cpp:950 xs/src/libslic3r/PrintConfig.cpp:960
+#: xs/src/libslic3r/PrintConfig.cpp:970 xs/src/libslic3r/PrintConfig.cpp:980
+msgid "Machine limits"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1730
+msgid "Values in this column are for Full Power mode"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1731
+msgid "Full Power"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1736
+msgid "Values in this column are for Silent mode"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1737
+msgid "Silent"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1745
+msgid "Maximum feedrates"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1750
+msgid "Maximum accelerations"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1757
+msgid "Jerk limits"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1762
+msgid "Minimum feedrates"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1800 xs/src/slic3r/GUI/Tab.cpp:1808
+#: xs/src/slic3r/GUI/Tab.cpp:2037
 msgid "Single extruder MM setup"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1729
+#: xs/src/slic3r/GUI/Tab.cpp:1809
 msgid "Single extruder multimaterial parameters"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1741 xs/src/libslic3r/GCode/PreviewData.cpp:440
+#: xs/src/slic3r/GUI/Tab.cpp:1822 xs/src/libslic3r/GCode/PreviewData.cpp:446
 #, possible-c-format
 msgid "Extruder %d"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1748
+#: xs/src/slic3r/GUI/Tab.cpp:1829
 msgid "Layer height limits"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1753
+#: xs/src/slic3r/GUI/Tab.cpp:1834
 msgid "Position (for multi-extruder printers)"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1756
+#: xs/src/slic3r/GUI/Tab.cpp:1837
 msgid "Retraction"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1759
+#: xs/src/slic3r/GUI/Tab.cpp:1840
 msgid "Only lift Z"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1772
+#: xs/src/slic3r/GUI/Tab.cpp:1853
 msgid ""
 "Retraction when tool is disabled (advanced settings for multi-extruder "
 "setups)"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1776 lib/Slic3r/GUI/Plater.pm:192
-#: lib/Slic3r/GUI/Plater.pm:2283
+#: xs/src/slic3r/GUI/Tab.cpp:1857 lib/Slic3r/GUI/Plater.pm:217
+#: lib/Slic3r/GUI/Plater.pm:2324
 msgid "Preview"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1855
+#: xs/src/slic3r/GUI/Tab.cpp:1953
 msgid ""
 "The Wipe option is not available when using the Firmware Retraction mode.\n"
 "\n"
 "Shall I disable it in order to enable Firmware Retraction?"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:1857
+#: xs/src/slic3r/GUI/Tab.cpp:1955
 msgid "Firmware Retraction"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2029
+#: xs/src/slic3r/GUI/Tab.cpp:2130
 msgid "Default "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2029
+#: xs/src/slic3r/GUI/Tab.cpp:2130
 msgid " preset"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2030
+#: xs/src/slic3r/GUI/Tab.cpp:2131
 msgid " preset\n"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2048
+#: xs/src/slic3r/GUI/Tab.cpp:2149
 msgid ""
 "\n"
 "\n"
 "is not compatible with printer\n"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2048
+#: xs/src/slic3r/GUI/Tab.cpp:2149
 msgid ""
 "\n"
 "\n"
 "and it has the following unsaved changes:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2049
+#: xs/src/slic3r/GUI/Tab.cpp:2150
 msgid ""
 "\n"
 "\n"
 "has the following unsaved changes:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2051
+#: xs/src/slic3r/GUI/Tab.cpp:2152
 msgid ""
 "\n"
 "\n"
 "Discard changes and continue anyway?"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2052
+#: xs/src/slic3r/GUI/Tab.cpp:2153
 msgid "Unsaved Changes"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2139
+#: xs/src/slic3r/GUI/Tab.cpp:2240
 msgid "The supplied name is empty. It can't be saved."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2144
+#: xs/src/slic3r/GUI/Tab.cpp:2245
 msgid "Cannot overwrite a system profile."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2148
+#: xs/src/slic3r/GUI/Tab.cpp:2249
 msgid "Cannot overwrite an external profile."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2172
+#: xs/src/slic3r/GUI/Tab.cpp:2275
 msgid "remove"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2172
+#: xs/src/slic3r/GUI/Tab.cpp:2275
 msgid "delete"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2173
+#: xs/src/slic3r/GUI/Tab.cpp:2276
 msgid "Are you sure you want to "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2173
+#: xs/src/slic3r/GUI/Tab.cpp:2276
 msgid " the selected preset?"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2174
+#: xs/src/slic3r/GUI/Tab.cpp:2277
 msgid "Remove"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2174 lib/Slic3r/GUI/Plater.pm:233
-#: lib/Slic3r/GUI/Plater.pm:251 lib/Slic3r/GUI/Plater.pm:2174
+#: xs/src/slic3r/GUI/Tab.cpp:2277 lib/Slic3r/GUI/Plater.pm:251
+#: lib/Slic3r/GUI/Plater.pm:269 lib/Slic3r/GUI/Plater.pm:2215
 msgid "Delete"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2175
+#: xs/src/slic3r/GUI/Tab.cpp:2278
 msgid " Preset"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2228
+#: xs/src/slic3r/GUI/Tab.cpp:2331
 msgid "All"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2260
+#: xs/src/slic3r/GUI/Tab.cpp:2363
 msgid "Select the printers this profile is compatible with."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2306 xs/src/slic3r/GUI/Tab.cpp:2392
-#: xs/src/slic3r/GUI/Preset.cpp:613 xs/src/slic3r/GUI/Preset.cpp:653
-#: xs/src/slic3r/GUI/Preset.cpp:678 xs/src/slic3r/GUI/Preset.cpp:710
-#: xs/src/slic3r/GUI/PresetBundle.cpp:1119
-#: xs/src/slic3r/GUI/PresetBundle.cpp:1172 lib/Slic3r/GUI/Plater.pm:618
+#: xs/src/slic3r/GUI/Tab.cpp:2409 xs/src/slic3r/GUI/Tab.cpp:2495
+#: xs/src/slic3r/GUI/Preset.cpp:702 xs/src/slic3r/GUI/Preset.cpp:742
+#: xs/src/slic3r/GUI/Preset.cpp:770 xs/src/slic3r/GUI/Preset.cpp:802
+#: xs/src/slic3r/GUI/PresetBundle.cpp:1193
+#: xs/src/slic3r/GUI/PresetBundle.cpp:1246 lib/Slic3r/GUI/Plater.pm:603
 msgid "System presets"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2307 xs/src/slic3r/GUI/Tab.cpp:2393
+#: xs/src/slic3r/GUI/Tab.cpp:2410 xs/src/slic3r/GUI/Tab.cpp:2496
 msgid "Default presets"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2462
+#: xs/src/slic3r/GUI/Tab.cpp:2565
 msgid ""
 "LOCKED LOCK;indicates that the settings are the same as the system values "
 "for the current option group"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2465
+#: xs/src/slic3r/GUI/Tab.cpp:2568
 msgid ""
 "UNLOCKED LOCK;indicates that some settings were changed and are not equal to "
 "the system values for the current option group.\n"
@@ -1318,13 +1365,13 @@ msgid ""
 "to the system values."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2471
+#: xs/src/slic3r/GUI/Tab.cpp:2574
 msgid ""
 "WHITE BULLET;for the left button: \tindicates a non-system preset,\n"
 "for the right button: \tindicates that the settings hasn't been modified."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2475
+#: xs/src/slic3r/GUI/Tab.cpp:2578
 msgid ""
 "BACK ARROW;indicates that the settings were changed and are not equal to the "
 "last saved preset for the current option group.\n"
@@ -1332,30 +1379,30 @@ msgid ""
 "to the last saved preset."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2501
+#: xs/src/slic3r/GUI/Tab.cpp:2604
 msgid ""
 "LOCKED LOCK icon indicates that the settings are the same as the system "
 "values for the current option group"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2503
+#: xs/src/slic3r/GUI/Tab.cpp:2606
 msgid ""
 "UNLOCKED LOCK icon indicates that some settings were changed and are not "
 "equal to the system values for the current option group.\n"
 "Click to reset all settings for current option group to the system values."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2506
+#: xs/src/slic3r/GUI/Tab.cpp:2609
 msgid "WHITE BULLET icon indicates a non system preset."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2509
+#: xs/src/slic3r/GUI/Tab.cpp:2612
 msgid ""
 "WHITE BULLET icon indicates that the settings are the same as in the last "
 "saved preset for the current option group."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2511
+#: xs/src/slic3r/GUI/Tab.cpp:2614
 msgid ""
 "BACK ARROW icon indicates that the settings were changed and are not equal "
 "to the last saved preset for the current option group.\n"
@@ -1363,87 +1410,91 @@ msgid ""
 "preset."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2517
+#: xs/src/slic3r/GUI/Tab.cpp:2620
 msgid ""
 "LOCKED LOCK icon indicates that the value is the same as the system value."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2518
+#: xs/src/slic3r/GUI/Tab.cpp:2621
 msgid ""
 "UNLOCKED LOCK icon indicates that the value was changed and is not equal to "
 "the system value.\n"
 "Click to reset current value to the system value."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2524
+#: xs/src/slic3r/GUI/Tab.cpp:2627
 msgid ""
 "WHITE BULLET icon indicates that the value is the same as in the last saved "
 "preset."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2525
+#: xs/src/slic3r/GUI/Tab.cpp:2628
 msgid ""
 "BACK ARROW icon indicates that the value was changed and is not equal to the "
 "last saved preset.\n"
 "Click to reset current value to the last saved preset."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2595 lib/Slic3r/GUI/MainFrame.pm:450
-#: lib/Slic3r/GUI/Plater.pm:1756
+#: xs/src/slic3r/GUI/Tab.cpp:2703 lib/Slic3r/GUI/MainFrame.pm:469
+#: lib/Slic3r/GUI/Plater.pm:1795
 msgid "Save "
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2595
+#: xs/src/slic3r/GUI/Tab.cpp:2703
 msgid " as:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2634 xs/src/slic3r/GUI/Tab.cpp:2638
+#: xs/src/slic3r/GUI/Tab.cpp:2742 xs/src/slic3r/GUI/Tab.cpp:2746
 msgid "The supplied name is not valid;"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2635
+#: xs/src/slic3r/GUI/Tab.cpp:2743
 msgid "the following characters are not allowed:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2639
+#: xs/src/slic3r/GUI/Tab.cpp:2747
 msgid "the following postfix are not allowed:"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.cpp:2642
+#: xs/src/slic3r/GUI/Tab.cpp:2750
 msgid "The supplied name is not available."
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.hpp:283
+#: xs/src/slic3r/GUI/Tab.hpp:286
 msgid "Print Settings"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.hpp:303
+#: xs/src/slic3r/GUI/Tab.hpp:306
 msgid "Filament Settings"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.hpp:326
+#: xs/src/slic3r/GUI/Tab.hpp:332
 msgid "Printer Settings"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Tab.hpp:341
+#: xs/src/slic3r/GUI/Tab.hpp:348
 msgid "Save preset"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Field.cpp:82
+#: xs/src/slic3r/GUI/Field.cpp:98
 msgid "default"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Field.cpp:112
+#: xs/src/slic3r/GUI/Field.cpp:128
 #, possible-c-format
 msgid "%s doesn't support percentage"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Field.cpp:121
+#: xs/src/slic3r/GUI/Field.cpp:137
 msgid "Input value is out of range"
 msgstr ""
 
-#: xs/src/slic3r/GUI/Preset.cpp:657 xs/src/slic3r/GUI/Preset.cpp:714
-#: xs/src/slic3r/GUI/PresetBundle.cpp:1177 lib/Slic3r/GUI/Plater.pm:619
+#: xs/src/slic3r/GUI/Preset.cpp:144
+msgid "modified"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Preset.cpp:746 xs/src/slic3r/GUI/Preset.cpp:806
+#: xs/src/slic3r/GUI/PresetBundle.cpp:1251 lib/Slic3r/GUI/Plater.pm:604
 msgid "User presets"
 msgstr ""
 
@@ -1659,7 +1710,7 @@ msgstr ""
 
 #: xs/src/slic3r/GUI/RammingChart.cpp:76 xs/src/slic3r/GUI/RammingChart.cpp:81
 #: xs/src/slic3r/GUI/WipeTowerDialog.cpp:77
-#: xs/src/libslic3r/PrintConfig.cpp:481
+#: xs/src/libslic3r/PrintConfig.cpp:490
 msgid "s"
 msgstr ""
 
@@ -1876,56 +1927,156 @@ msgstr ""
 msgid "Error while uploading to the OctoPrint server"
 msgstr ""
 
-#: xs/src/slic3r/Utils/OctoPrint.cpp:111 lib/Slic3r/GUI/Plater.pm:1559
+#: xs/src/slic3r/Utils/OctoPrint.cpp:111 lib/Slic3r/GUI/Plater.pm:1558
 msgid "Sending G-code file to the OctoPrint server..."
 msgstr ""
 
-#: xs/src/slic3r/Utils/OctoPrint.cpp:192
-msgid "Invalid API key"
-msgstr ""
-
-#: xs/src/slic3r/Utils/PresetUpdater.cpp:533
+#: xs/src/slic3r/Utils/PresetUpdater.cpp:544
 #, possible-c-format
 msgid "requires min. %s and max. %s"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:26
+#: xs/src/libslic3r/Print.cpp:553
+msgid "All objects are outside of the print volume."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:579
+msgid "Some objects are too close; your extruder will collide with them."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:594
+msgid ""
+"Some objects are too tall and cannot be printed without extruder collisions."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:604
+msgid "The Spiral Vase option can only be used when printing a single object."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:606
+msgid ""
+"The Spiral Vase option can only be used when printing single material "
+"objects."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:612
+msgid ""
+"All extruders must have the same diameter for single extruder multimaterial "
+"printer."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:617
+msgid ""
+"The Wipe Tower is currently only supported for the Marlin and RepRap/"
+"Sprinter G-code flavors."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:619
+msgid ""
+"The Wipe Tower is currently only supported with the relative extruder "
+"addressing (use_relative_e_distances=1)."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:631
+msgid ""
+"The Wipe Tower is only supported for multiple objects if they have equal "
+"layer heigths"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:633
+msgid ""
+"The Wipe Tower is only supported for multiple objects if they are printed "
+"over an equal number of raft layers"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:635
+msgid ""
+"The Wipe Tower is only supported for multiple objects if they are printed "
+"with the same support_material_contact_distance"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:637
+msgid ""
+"The Wipe Tower is only supported for multiple objects if they are sliced "
+"equally."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:661
+msgid ""
+"The Wipe tower is only supported if all objects have the same layer height "
+"profile"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:670
+msgid "The supplied settings will cause an empty print."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:680
+msgid ""
+"One or more object were assigned an extruder that the printer does not have."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:689
+msgid ""
+"Printing with multiple extruders of differing nozzle diameters. If support "
+"is to be printed with the current extruder (support_material_extruder == 0 "
+"or support_material_interface_extruder == 0), all nozzles have to be of the "
+"same diameter."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:695
+msgid "first_layer_height"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:710
+msgid "First layer height can't be greater than nozzle diameter"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:714
+msgid "Layer height can't be greater than nozzle diameter"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:1196
+msgid "Failed processing of the output_filename_format template."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:29
 msgid "Avoid crossing perimeters"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:27
+#: xs/src/libslic3r/PrintConfig.cpp:30
 msgid ""
 "Optimize travel moves in order to minimize the crossing of perimeters. This "
 "is mostly useful with Bowden extruders which suffer from oozing. This "
 "feature slows down both the print and the G-code generation."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:38 xs/src/libslic3r/PrintConfig.cpp:1678
+#: xs/src/libslic3r/PrintConfig.cpp:41 xs/src/libslic3r/PrintConfig.cpp:1818
 msgid "Other layers"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:39
+#: xs/src/libslic3r/PrintConfig.cpp:42
 msgid ""
 "Bed temperature for layers after the first one. Set this to zero to disable "
 "bed temperature control commands in the output."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:42
+#: xs/src/libslic3r/PrintConfig.cpp:45
 msgid "Bed temperature"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:49
+#: xs/src/libslic3r/PrintConfig.cpp:52
 msgid ""
 "This custom code is inserted at every layer change, right before the Z move. "
 "Note that you can use placeholder variables for all Slic3r settings as well "
 "as [layer_num] and [layer_z]."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:59
+#: xs/src/libslic3r/PrintConfig.cpp:62
 msgid "Between objects G-code"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:60
+#: xs/src/libslic3r/PrintConfig.cpp:63
 msgid ""
 "This code is inserted between objects when using sequential printing. By "
 "default extruder and bed temperature are reset using non-wait command; "
@@ -1935,79 +2086,80 @@ msgid ""
 "[first_layer_temperature]\" command wherever you want."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:68 lib/Slic3r/GUI/MainFrame.pm:309
+#: xs/src/libslic3r/PrintConfig.cpp:71 lib/Slic3r/GUI/MainFrame.pm:328
 msgid "Bottom"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:69 xs/src/libslic3r/PrintConfig.cpp:268
-#: xs/src/libslic3r/PrintConfig.cpp:319 xs/src/libslic3r/PrintConfig.cpp:327
-#: xs/src/libslic3r/PrintConfig.cpp:667 xs/src/libslic3r/PrintConfig.cpp:832
-#: xs/src/libslic3r/PrintConfig.cpp:848 xs/src/libslic3r/PrintConfig.cpp:1025
-#: xs/src/libslic3r/PrintConfig.cpp:1082 xs/src/libslic3r/PrintConfig.cpp:1260
-#: xs/src/libslic3r/PrintConfig.cpp:1689 xs/src/libslic3r/PrintConfig.cpp:1745
+#: xs/src/libslic3r/PrintConfig.cpp:72 xs/src/libslic3r/PrintConfig.cpp:276
+#: xs/src/libslic3r/PrintConfig.cpp:327 xs/src/libslic3r/PrintConfig.cpp:335
+#: xs/src/libslic3r/PrintConfig.cpp:701 xs/src/libslic3r/PrintConfig.cpp:871
+#: xs/src/libslic3r/PrintConfig.cpp:887 xs/src/libslic3r/PrintConfig.cpp:1156
+#: xs/src/libslic3r/PrintConfig.cpp:1222 xs/src/libslic3r/PrintConfig.cpp:1400
+#: xs/src/libslic3r/PrintConfig.cpp:1829 xs/src/libslic3r/PrintConfig.cpp:1885
 msgid "Layers and Perimeters"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:70
+#: xs/src/libslic3r/PrintConfig.cpp:73
 msgid "Number of solid layers to generate on bottom surfaces."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:72
+#: xs/src/libslic3r/PrintConfig.cpp:75
 msgid "Bottom solid layers"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:77
+#: xs/src/libslic3r/PrintConfig.cpp:80
 msgid "Bridge"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:78
+#: xs/src/libslic3r/PrintConfig.cpp:81
 msgid ""
 "This is the acceleration your printer will use for bridges. Set zero to "
 "disable acceleration control for bridges."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:80 xs/src/libslic3r/PrintConfig.cpp:191
-#: xs/src/libslic3r/PrintConfig.cpp:639 xs/src/libslic3r/PrintConfig.cpp:747
-#: xs/src/libslic3r/PrintConfig.cpp:1045
+#: xs/src/libslic3r/PrintConfig.cpp:83 xs/src/libslic3r/PrintConfig.cpp:199
+#: xs/src/libslic3r/PrintConfig.cpp:673 xs/src/libslic3r/PrintConfig.cpp:781
+#: xs/src/libslic3r/PrintConfig.cpp:931 xs/src/libslic3r/PrintConfig.cpp:972
+#: xs/src/libslic3r/PrintConfig.cpp:982 xs/src/libslic3r/PrintConfig.cpp:1185
 msgid "mm/s²"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:86
+#: xs/src/libslic3r/PrintConfig.cpp:89
 msgid "Bridging angle"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:88
+#: xs/src/libslic3r/PrintConfig.cpp:91
 msgid ""
 "Bridging angle override. If left to zero, the bridging angle will be "
 "calculated automatically. Otherwise the provided angle will be used for all "
 "bridges. Use 180° for zero angle."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:91 xs/src/libslic3r/PrintConfig.cpp:555
-#: xs/src/libslic3r/PrintConfig.cpp:1278 xs/src/libslic3r/PrintConfig.cpp:1289
-#: xs/src/libslic3r/PrintConfig.cpp:1509 xs/src/libslic3r/PrintConfig.cpp:1663
+#: xs/src/libslic3r/PrintConfig.cpp:94 xs/src/libslic3r/PrintConfig.cpp:589
+#: xs/src/libslic3r/PrintConfig.cpp:1418 xs/src/libslic3r/PrintConfig.cpp:1429
+#: xs/src/libslic3r/PrintConfig.cpp:1649 xs/src/libslic3r/PrintConfig.cpp:1803
 msgid "°"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:97
+#: xs/src/libslic3r/PrintConfig.cpp:100
 msgid "Bridges fan speed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:98
+#: xs/src/libslic3r/PrintConfig.cpp:101
 msgid "This fan speed is enforced during all bridges and overhangs."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:99 xs/src/libslic3r/PrintConfig.cpp:567
-#: xs/src/libslic3r/PrintConfig.cpp:859 xs/src/libslic3r/PrintConfig.cpp:927
-#: xs/src/libslic3r/PrintConfig.cpp:1168
+#: xs/src/libslic3r/PrintConfig.cpp:102 xs/src/libslic3r/PrintConfig.cpp:601
+#: xs/src/libslic3r/PrintConfig.cpp:990 xs/src/libslic3r/PrintConfig.cpp:1058
+#: xs/src/libslic3r/PrintConfig.cpp:1308
 msgid "%"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:106
+#: xs/src/libslic3r/PrintConfig.cpp:109
 msgid "Bridge flow ratio"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:108
+#: xs/src/libslic3r/PrintConfig.cpp:111
 msgid ""
 "This factor affects the amount of plastic for bridging. You can decrease it "
 "slightly to pull the extrudates and prevent sagging, although default "
@@ -2015,60 +2167,63 @@ msgid ""
 "before tweaking this."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:118
+#: xs/src/libslic3r/PrintConfig.cpp:121
 msgid "Bridges"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:120
+#: xs/src/libslic3r/PrintConfig.cpp:123
 msgid "Speed for printing bridges."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:121 xs/src/libslic3r/PrintConfig.cpp:462
-#: xs/src/libslic3r/PrintConfig.cpp:471 xs/src/libslic3r/PrintConfig.cpp:701
-#: xs/src/libslic3r/PrintConfig.cpp:812 xs/src/libslic3r/PrintConfig.cpp:888
-#: xs/src/libslic3r/PrintConfig.cpp:945 xs/src/libslic3r/PrintConfig.cpp:1074
-#: xs/src/libslic3r/PrintConfig.cpp:1245 xs/src/libslic3r/PrintConfig.cpp:1254
-#: xs/src/libslic3r/PrintConfig.cpp:1642 xs/src/libslic3r/PrintConfig.cpp:1755
+#: xs/src/libslic3r/PrintConfig.cpp:124 xs/src/libslic3r/PrintConfig.cpp:471
+#: xs/src/libslic3r/PrintConfig.cpp:480 xs/src/libslic3r/PrintConfig.cpp:508
+#: xs/src/libslic3r/PrintConfig.cpp:516 xs/src/libslic3r/PrintConfig.cpp:735
+#: xs/src/libslic3r/PrintConfig.cpp:846 xs/src/libslic3r/PrintConfig.cpp:922
+#: xs/src/libslic3r/PrintConfig.cpp:940 xs/src/libslic3r/PrintConfig.cpp:952
+#: xs/src/libslic3r/PrintConfig.cpp:962 xs/src/libslic3r/PrintConfig.cpp:1019
+#: xs/src/libslic3r/PrintConfig.cpp:1076 xs/src/libslic3r/PrintConfig.cpp:1214
+#: xs/src/libslic3r/PrintConfig.cpp:1385 xs/src/libslic3r/PrintConfig.cpp:1394
+#: xs/src/libslic3r/PrintConfig.cpp:1782 xs/src/libslic3r/PrintConfig.cpp:1895
 msgid "mm/s"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:128
+#: xs/src/libslic3r/PrintConfig.cpp:131
 msgid "Brim width"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:129
+#: xs/src/libslic3r/PrintConfig.cpp:132
 msgid ""
 "Horizontal width of the brim that will be printed around each object on the "
 "first layer."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:136
+#: xs/src/libslic3r/PrintConfig.cpp:139
 msgid "Clip multi-part objects"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:137
+#: xs/src/libslic3r/PrintConfig.cpp:140
 msgid ""
 "When printing multi-material objects, this settings will make slic3r to clip "
 "the overlapping object parts one by the other (2nd part will be clipped by "
 "the 1st, 3rd part will be clipped by the 1st and 2nd etc)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:148
+#: xs/src/libslic3r/PrintConfig.cpp:151
 msgid "Compatible printers condition"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:149
+#: xs/src/libslic3r/PrintConfig.cpp:152
 msgid ""
 "A boolean expression using the configuration values of an active printer "
 "profile. If this expression evaluates to true, this profile is considered "
 "compatible with the active printer profile."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:155
+#: xs/src/libslic3r/PrintConfig.cpp:163
 msgid "Complete individual objects"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:156
+#: xs/src/libslic3r/PrintConfig.cpp:164
 msgid ""
 "When printing multiple objects or copies, this feature will complete each "
 "object before moving onto next one (and starting it from its bottom layer). "
@@ -2076,113 +2231,113 @@ msgid ""
 "warn and prevent you from extruder collisions, but beware."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:164
+#: xs/src/libslic3r/PrintConfig.cpp:172
 msgid "Enable auto cooling"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:165
+#: xs/src/libslic3r/PrintConfig.cpp:173
 msgid ""
 "This flag enables the automatic cooling logic that adjusts print speed and "
 "fan speed according to layer printing time."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:171
+#: xs/src/libslic3r/PrintConfig.cpp:179
 msgid "Cooling tube position"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:172
+#: xs/src/libslic3r/PrintConfig.cpp:180
 msgid "Distance of the center-point of the cooling tube from the extruder tip "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:179
+#: xs/src/libslic3r/PrintConfig.cpp:187
 msgid "Cooling tube length"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:180
+#: xs/src/libslic3r/PrintConfig.cpp:188
 msgid "Length of the cooling tube to limit space for cooling moves inside it "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:188
+#: xs/src/libslic3r/PrintConfig.cpp:196
 msgid ""
 "This is the acceleration your printer will be reset to after the role-"
 "specific acceleration values are used (perimeter/infill). Set zero to "
 "prevent resetting acceleration at all."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:197
+#: xs/src/libslic3r/PrintConfig.cpp:205
 msgid "Default filament profile"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:198
+#: xs/src/libslic3r/PrintConfig.cpp:206
 msgid ""
 "Default filament profile associated with the current printer profile. On "
 "selection of the current printer profile, this filament profile will be "
 "activated."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:203
+#: xs/src/libslic3r/PrintConfig.cpp:211
 msgid "Default print profile"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:204
+#: xs/src/libslic3r/PrintConfig.cpp:212
 msgid ""
 "Default print profile associated with the current printer profile. On "
 "selection of the current printer profile, this print profile will be "
 "activated."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:209
+#: xs/src/libslic3r/PrintConfig.cpp:217
 msgid "Disable fan for the first"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:210
+#: xs/src/libslic3r/PrintConfig.cpp:218
 msgid ""
 "You can set this to a positive value to disable fan at all during the first "
 "layers, so that it does not make adhesion worse."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:212 xs/src/libslic3r/PrintConfig.cpp:757
-#: xs/src/libslic3r/PrintConfig.cpp:1141 xs/src/libslic3r/PrintConfig.cpp:1332
-#: xs/src/libslic3r/PrintConfig.cpp:1393 xs/src/libslic3r/PrintConfig.cpp:1545
-#: xs/src/libslic3r/PrintConfig.cpp:1590
+#: xs/src/libslic3r/PrintConfig.cpp:220 xs/src/libslic3r/PrintConfig.cpp:791
+#: xs/src/libslic3r/PrintConfig.cpp:1281 xs/src/libslic3r/PrintConfig.cpp:1472
+#: xs/src/libslic3r/PrintConfig.cpp:1533 xs/src/libslic3r/PrintConfig.cpp:1685
+#: xs/src/libslic3r/PrintConfig.cpp:1730
 msgid "layers"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:219
+#: xs/src/libslic3r/PrintConfig.cpp:227
 msgid "Don't support bridges"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:221
+#: xs/src/libslic3r/PrintConfig.cpp:229
 msgid ""
 "Experimental option for preventing support material from being generated "
 "under bridged areas."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:227
+#: xs/src/libslic3r/PrintConfig.cpp:235
 msgid "Distance between copies"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:228
+#: xs/src/libslic3r/PrintConfig.cpp:236
 msgid "Distance used for the auto-arrange feature of the plater."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:236
+#: xs/src/libslic3r/PrintConfig.cpp:244
 msgid "Elephant foot compensation"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:238
+#: xs/src/libslic3r/PrintConfig.cpp:246
 msgid ""
 "The first layer will be shrunk in the XY plane by the configured value to "
 "compensate for the 1st layer squish aka an Elephant Foot effect."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:247
+#: xs/src/libslic3r/PrintConfig.cpp:255
 msgid ""
 "This end procedure is inserted at the end of the output file. Note that you "
 "can use placeholder variables for all Slic3r settings."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:257
+#: xs/src/libslic3r/PrintConfig.cpp:265
 msgid ""
 "This end procedure is inserted at the end of the output file, before the "
 "printer end gcode. Note that you can use placeholder variables for all "
@@ -2190,38 +2345,59 @@ msgid ""
 "extruder order."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:267
+#: xs/src/libslic3r/PrintConfig.cpp:275
 msgid "Ensure vertical shell thickness"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:269
+#: xs/src/libslic3r/PrintConfig.cpp:277
 msgid ""
 "Add solid infill near sloping surfaces to guarantee the vertical shell "
 "thickness (top+bottom solid layers)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:275
+#: xs/src/libslic3r/PrintConfig.cpp:283
 msgid "Top/bottom fill pattern"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:277
+#: xs/src/libslic3r/PrintConfig.cpp:285
 msgid ""
 "Fill pattern for top/bottom infill. This only affects the external visible "
 "layer, and not its adjacent solid shells."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:296 xs/src/libslic3r/PrintConfig.cpp:306
+#: xs/src/libslic3r/PrintConfig.cpp:294 xs/src/libslic3r/PrintConfig.cpp:654
+#: xs/src/libslic3r/PrintConfig.cpp:1764
+msgid "Rectilinear"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:295 xs/src/libslic3r/PrintConfig.cpp:660
+msgid "Concentric"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:296 xs/src/libslic3r/PrintConfig.cpp:664
+msgid "Hilbert Curve"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:297 xs/src/libslic3r/PrintConfig.cpp:665
+msgid "Archimedean Chords"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:298 xs/src/libslic3r/PrintConfig.cpp:666
+msgid "Octagram Spiral"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:304 xs/src/libslic3r/PrintConfig.cpp:314
 msgid "External perimeters"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:297 xs/src/libslic3r/PrintConfig.cpp:406
-#: xs/src/libslic3r/PrintConfig.cpp:655 xs/src/libslic3r/PrintConfig.cpp:773
-#: xs/src/libslic3r/PrintConfig.cpp:1060 xs/src/libslic3r/PrintConfig.cpp:1400
-#: xs/src/libslic3r/PrintConfig.cpp:1562 xs/src/libslic3r/PrintConfig.cpp:1720
+#: xs/src/libslic3r/PrintConfig.cpp:305 xs/src/libslic3r/PrintConfig.cpp:415
+#: xs/src/libslic3r/PrintConfig.cpp:689 xs/src/libslic3r/PrintConfig.cpp:807
+#: xs/src/libslic3r/PrintConfig.cpp:1200 xs/src/libslic3r/PrintConfig.cpp:1540
+#: xs/src/libslic3r/PrintConfig.cpp:1702 xs/src/libslic3r/PrintConfig.cpp:1860
 msgid "Extrusion Width"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:298
+#: xs/src/libslic3r/PrintConfig.cpp:306
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for external "
 "perimeters. If left zero, default extrusion width will be used if set, "
@@ -2229,41 +2405,41 @@ msgid ""
 "(for example 200%), it will be computed over layer height."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:301 xs/src/libslic3r/PrintConfig.cpp:660
-#: xs/src/libslic3r/PrintConfig.cpp:778 xs/src/libslic3r/PrintConfig.cpp:1065
-#: xs/src/libslic3r/PrintConfig.cpp:1404 xs/src/libslic3r/PrintConfig.cpp:1566
-#: xs/src/libslic3r/PrintConfig.cpp:1725
+#: xs/src/libslic3r/PrintConfig.cpp:309 xs/src/libslic3r/PrintConfig.cpp:694
+#: xs/src/libslic3r/PrintConfig.cpp:812 xs/src/libslic3r/PrintConfig.cpp:1205
+#: xs/src/libslic3r/PrintConfig.cpp:1544 xs/src/libslic3r/PrintConfig.cpp:1706
+#: xs/src/libslic3r/PrintConfig.cpp:1865
 msgid "mm or % (leave 0 for default)"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:308
+#: xs/src/libslic3r/PrintConfig.cpp:316
 msgid ""
 "This separate setting will affect the speed of external perimeters (the "
 "visible ones). If expressed as percentage (for example: 80%) it will be "
 "calculated on the perimeters speed setting above. Set to zero for auto."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:311 xs/src/libslic3r/PrintConfig.cpp:682
-#: xs/src/libslic3r/PrintConfig.cpp:1363 xs/src/libslic3r/PrintConfig.cpp:1414
-#: xs/src/libslic3r/PrintConfig.cpp:1609 xs/src/libslic3r/PrintConfig.cpp:1737
+#: xs/src/libslic3r/PrintConfig.cpp:319 xs/src/libslic3r/PrintConfig.cpp:716
+#: xs/src/libslic3r/PrintConfig.cpp:1503 xs/src/libslic3r/PrintConfig.cpp:1554
+#: xs/src/libslic3r/PrintConfig.cpp:1749 xs/src/libslic3r/PrintConfig.cpp:1877
 msgid "mm/s or %"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:318
+#: xs/src/libslic3r/PrintConfig.cpp:326
 msgid "External perimeters first"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:320
+#: xs/src/libslic3r/PrintConfig.cpp:328
 msgid ""
 "Print contour perimeters from the outermost one to the innermost one instead "
 "of the default inverse order."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:326
+#: xs/src/libslic3r/PrintConfig.cpp:334
 msgid "Extra perimeters if needed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:328
+#: xs/src/libslic3r/PrintConfig.cpp:336
 #, no-c-format
 msgid ""
 "Add more perimeters when needed for avoiding gaps in sloping walls. Slic3r "
@@ -2271,18 +2447,18 @@ msgid ""
 "is supported."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:338
+#: xs/src/libslic3r/PrintConfig.cpp:346
 msgid ""
 "The extruder to use (unless more specific extruder settings are specified). "
 "This value overrides perimeter and infill extruders, but not the support "
 "extruders."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:349 lib/Slic3r/GUI/Plater/3DPreview.pm:75
+#: xs/src/libslic3r/PrintConfig.cpp:358 lib/Slic3r/GUI/Plater/3DPreview.pm:75
 msgid "Height"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:350
+#: xs/src/libslic3r/PrintConfig.cpp:359
 msgid ""
 "Set this to the vertical distance between your nozzle tip and (usually) the "
 "X carriage rods. In other words, this is the height of the clearance "
@@ -2290,30 +2466,30 @@ msgid ""
 "extruder can peek before colliding with other printed objects."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:360
+#: xs/src/libslic3r/PrintConfig.cpp:369
 msgid "Radius"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:361
+#: xs/src/libslic3r/PrintConfig.cpp:370
 msgid ""
 "Set this to the clearance radius around your extruder. If the extruder is "
 "not centered, choose the largest value for safety. This setting is used to "
 "check for collisions and to display the graphical preview in the plater."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:371
+#: xs/src/libslic3r/PrintConfig.cpp:380
 msgid "Extruder Color"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:372 xs/src/libslic3r/PrintConfig.cpp:435
+#: xs/src/libslic3r/PrintConfig.cpp:381 xs/src/libslic3r/PrintConfig.cpp:444
 msgid "This is only used in the Slic3r interface as a visual help."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:379
+#: xs/src/libslic3r/PrintConfig.cpp:388
 msgid "Extruder offset"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:380
+#: xs/src/libslic3r/PrintConfig.cpp:389
 msgid ""
 "If your firmware doesn't handle the extruder displacement you need the G-"
 "code to take it into account. This option lets you specify the displacement "
@@ -2321,21 +2497,21 @@ msgid ""
 "coordinates (they will be subtracted from the XY coordinate)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:389
+#: xs/src/libslic3r/PrintConfig.cpp:398
 msgid "Extrusion axis"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:390
+#: xs/src/libslic3r/PrintConfig.cpp:399
 msgid ""
 "Use this option to set the axis letter associated to your printer's extruder "
 "(usually E but some printers use A)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:396
+#: xs/src/libslic3r/PrintConfig.cpp:405
 msgid "Extrusion multiplier"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:397
+#: xs/src/libslic3r/PrintConfig.cpp:406
 msgid ""
 "This factor changes the amount of flow proportionally. You may need to tweak "
 "this setting to get nice surface finish and correct single wall widths. "
@@ -2343,11 +2519,11 @@ msgid ""
 "more, check filament diameter and your firmware E steps."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:405
+#: xs/src/libslic3r/PrintConfig.cpp:414
 msgid "Default extrusion width"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:407
+#: xs/src/libslic3r/PrintConfig.cpp:416
 msgid ""
 "Set this to a non-zero value to allow a manual extrusion width. If left to "
 "zero, Slic3r derives extrusion widths from the nozzle diameter (see the "
@@ -2356,113 +2532,139 @@ msgid ""
 "height."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:411
+#: xs/src/libslic3r/PrintConfig.cpp:420
 msgid "mm or % (leave 0 for auto)"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:416
+#: xs/src/libslic3r/PrintConfig.cpp:425
 msgid "Keep fan always on"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:417
+#: xs/src/libslic3r/PrintConfig.cpp:426
 msgid ""
 "If this is enabled, fan will never be disabled and will be kept running at "
 "least at its minimum speed. Useful for PLA, harmful for ABS."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:423
+#: xs/src/libslic3r/PrintConfig.cpp:432
 msgid "Enable fan if layer print time is below"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:424
+#: xs/src/libslic3r/PrintConfig.cpp:433
 msgid ""
 "If layer print time is estimated below this number of seconds, fan will be "
 "enabled and its speed will be calculated by interpolating the minimum and "
 "maximum speeds."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:426 xs/src/libslic3r/PrintConfig.cpp:1350
+#: xs/src/libslic3r/PrintConfig.cpp:435 xs/src/libslic3r/PrintConfig.cpp:1490
 msgid "approximate seconds"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:434
+#: xs/src/libslic3r/PrintConfig.cpp:443
 msgid "Color"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:441
+#: xs/src/libslic3r/PrintConfig.cpp:450
 msgid "Filament notes"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:442
+#: xs/src/libslic3r/PrintConfig.cpp:451
 msgid "You can put your notes regarding the filament here."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:450 xs/src/libslic3r/PrintConfig.cpp:894
+#: xs/src/libslic3r/PrintConfig.cpp:459 xs/src/libslic3r/PrintConfig.cpp:1025
 msgid "Max volumetric speed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:451
+#: xs/src/libslic3r/PrintConfig.cpp:460
 msgid ""
 "Maximum volumetric speed allowed for this filament. Limits the maximum "
 "volumetric speed of a print to the minimum of print and filament volumetric "
 "speed. Set to zero for no limit."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:454 xs/src/libslic3r/PrintConfig.cpp:897
+#: xs/src/libslic3r/PrintConfig.cpp:463 xs/src/libslic3r/PrintConfig.cpp:1028
 msgid "mm³/s"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:460
+#: xs/src/libslic3r/PrintConfig.cpp:469
 msgid "Loading speed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:461
+#: xs/src/libslic3r/PrintConfig.cpp:470
 msgid "Speed used for loading the filament on the wipe tower. "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:468
+#: xs/src/libslic3r/PrintConfig.cpp:477
 msgid "Unloading speed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:469
+#: xs/src/libslic3r/PrintConfig.cpp:478
 msgid ""
 "Speed used for unloading the filament on the wipe tower (does not affect  "
 "initial part of unloading just after ramming). "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:477
+#: xs/src/libslic3r/PrintConfig.cpp:486
 msgid "Delay after unloading"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:478
+#: xs/src/libslic3r/PrintConfig.cpp:487
 msgid ""
 "Time to wait after the filament is unloaded. May help to get reliable "
 "toolchanges with flexible materials that may need more time to shrink to "
 "original dimensions. "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:487
+#: xs/src/libslic3r/PrintConfig.cpp:496
+msgid "Number of cooling moves"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:497
+msgid ""
+"Filament is cooled by being moved back and forth in the cooling tubes. "
+"Specify desired number of these moves "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:505
+msgid "Speed of the first cooling move"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:506
+msgid "Cooling moves are gradually accelerating beginning at this speed. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:513
+msgid "Speed of the last cooling move"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:514
+msgid "Cooling moves are gradually accelerating towards this speed. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:521
 msgid "Ramming parameters"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:488
+#: xs/src/libslic3r/PrintConfig.cpp:522
 msgid ""
 "This string is edited by RammingDialog and contains ramming specific "
 "parameters "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:495
+#: xs/src/libslic3r/PrintConfig.cpp:529
 msgid ""
 "Enter your filament diameter here. Good precision is required, so use a "
 "caliper and do multiple measurements along the filament, then compute the "
 "average."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:503
+#: xs/src/libslic3r/PrintConfig.cpp:537
 msgid "Density"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:504
+#: xs/src/libslic3r/PrintConfig.cpp:538
 msgid ""
 "Enter your filament density here. This is only for statistical information. "
 "A decent way is to weigh a known length of filament and compute the ratio of "
@@ -2470,15 +2672,15 @@ msgid ""
 "displacement."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:507
+#: xs/src/libslic3r/PrintConfig.cpp:541
 msgid "g/cm³"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:513
+#: xs/src/libslic3r/PrintConfig.cpp:547
 msgid "Filament type"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:514 xs/src/libslic3r/PrintConfig.cpp:1095
+#: xs/src/libslic3r/PrintConfig.cpp:548 xs/src/libslic3r/PrintConfig.cpp:1235
 msgid ""
 "If you want to process the output G-code through custom scripts, just list "
 "their absolute paths here. Separate multiple scripts with a semicolon. "
@@ -2487,74 +2689,106 @@ msgid ""
 "environment variables."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:533
+#: xs/src/libslic3r/PrintConfig.cpp:567
 msgid "Soluble material"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:534
+#: xs/src/libslic3r/PrintConfig.cpp:568
 msgid "Soluble material is most likely used for a soluble support."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:539 lib/Slic3r/GUI/Plater.pm:519
+#: xs/src/libslic3r/PrintConfig.cpp:573 lib/Slic3r/GUI/Plater.pm:1616
 msgid "Cost"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:540
+#: xs/src/libslic3r/PrintConfig.cpp:574
 msgid ""
 "Enter your filament cost per kg here. This is only for statistical "
 "information."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:541
+#: xs/src/libslic3r/PrintConfig.cpp:575
 msgid "money/kg"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:550
+#: xs/src/libslic3r/PrintConfig.cpp:584
 msgid "Fill angle"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:552
+#: xs/src/libslic3r/PrintConfig.cpp:586
 msgid ""
 "Default base angle for infill orientation. Cross-hatching will be applied to "
 "this. Bridges will be infilled using the best direction Slic3r can detect, "
 "so this setting does not affect them."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:564
+#: xs/src/libslic3r/PrintConfig.cpp:598
 msgid "Fill density"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:566
+#: xs/src/libslic3r/PrintConfig.cpp:600
 #, no-c-format
 msgid "Density of internal infill, expressed in the range 0% - 100%."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:602
+#: xs/src/libslic3r/PrintConfig.cpp:636
 msgid "Fill pattern"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:604
+#: xs/src/libslic3r/PrintConfig.cpp:638
 msgid "Fill pattern for general low-density infill."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:636 xs/src/libslic3r/PrintConfig.cpp:645
-#: xs/src/libslic3r/PrintConfig.cpp:654 xs/src/libslic3r/PrintConfig.cpp:688
+#: xs/src/libslic3r/PrintConfig.cpp:655
+msgid "Grid"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:656
+msgid "Triangles"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:657
+msgid "Stars"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:658
+msgid "Cubic"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:659
+msgid "Line"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:661 xs/src/libslic3r/PrintConfig.cpp:1766
+msgid "Honeycomb"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:662
+msgid "3D Honeycomb"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:663
+msgid "Gyroid"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:670 xs/src/libslic3r/PrintConfig.cpp:679
+#: xs/src/libslic3r/PrintConfig.cpp:688 xs/src/libslic3r/PrintConfig.cpp:722
 msgid "First layer"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:637
+#: xs/src/libslic3r/PrintConfig.cpp:671
 msgid ""
 "This is the acceleration your printer will use for first layer. Set zero to "
 "disable acceleration control for first layer."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:646
+#: xs/src/libslic3r/PrintConfig.cpp:680
 msgid ""
 "Heated build plate temperature for the first layer. Set this to zero to "
 "disable bed temperature control commands in the output."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:656
+#: xs/src/libslic3r/PrintConfig.cpp:690
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for first "
 "layer. You can use this to force fatter extrudates for better adhesion. If "
@@ -2562,11 +2796,11 @@ msgid ""
 "layer height. If set to zero, it will use the default extrusion width."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:666
+#: xs/src/libslic3r/PrintConfig.cpp:700
 msgid "First layer height"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:668
+#: xs/src/libslic3r/PrintConfig.cpp:702
 msgid ""
 "When printing with very low layer heights, you might still want to print a "
 "thicker bottom layer to improve adhesion and tolerance for non perfect build "
@@ -2574,58 +2808,58 @@ msgid ""
 "example: 150%) over the default layer height."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:672 xs/src/libslic3r/PrintConfig.cpp:803
-#: xs/src/libslic3r/PrintConfig.cpp:1498
+#: xs/src/libslic3r/PrintConfig.cpp:706 xs/src/libslic3r/PrintConfig.cpp:837
+#: xs/src/libslic3r/PrintConfig.cpp:1638
 msgid "mm or %"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:678
+#: xs/src/libslic3r/PrintConfig.cpp:712
 msgid "First layer speed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:679
+#: xs/src/libslic3r/PrintConfig.cpp:713
 msgid ""
 "If expressed as absolute value in mm/s, this speed will be applied to all "
 "the print moves of the first layer, regardless of their type. If expressed "
 "as a percentage (for example: 40%) it will scale the default speeds."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:689
+#: xs/src/libslic3r/PrintConfig.cpp:723
 msgid ""
 "Extruder temperature for first layer. If you want to control temperature "
 "manually during print, set this to zero to disable temperature control "
 "commands in the output file."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:697
-#: xs/src/libslic3r/GCode/PreviewData.cpp:165
+#: xs/src/libslic3r/PrintConfig.cpp:731
+#: xs/src/libslic3r/GCode/PreviewData.cpp:170
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:97
 msgid "Gap fill"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:699
+#: xs/src/libslic3r/PrintConfig.cpp:733
 msgid ""
 "Speed for filling small gaps using short zigzag moves. Keep this reasonably "
 "low to avoid too much shaking and resonance issues. Set zero to disable gaps "
 "filling."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:707
+#: xs/src/libslic3r/PrintConfig.cpp:741
 msgid "Verbose G-code"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:708
+#: xs/src/libslic3r/PrintConfig.cpp:742
 msgid ""
 "Enable this to get a commented G-code file, with each line explained by a "
 "descriptive text. If you print from SD card, the additional weight of the "
 "file could make your firmware slow down."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:715
+#: xs/src/libslic3r/PrintConfig.cpp:749
 msgid "G-code flavor"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:716
+#: xs/src/libslic3r/PrintConfig.cpp:750
 msgid ""
 "Some G/M-code commands, including temperature control and others, are not "
 "universal. Set this option to your printer's firmware to get a compatible "
@@ -2633,35 +2867,39 @@ msgid ""
 "extrusion value at all."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:745
+#: xs/src/libslic3r/PrintConfig.cpp:774
+msgid "No extrusion"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:779
 msgid ""
 "This is the acceleration your printer will use for infill. Set zero to "
 "disable acceleration control for infill."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:753
+#: xs/src/libslic3r/PrintConfig.cpp:787
 msgid "Combine infill every"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:755
+#: xs/src/libslic3r/PrintConfig.cpp:789
 msgid ""
 "This feature allows to combine infill and speed up your print by extruding "
 "thicker infill layers while preserving thin perimeters, thus accuracy."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:759
+#: xs/src/libslic3r/PrintConfig.cpp:793
 msgid "Combine infill every n layers"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:764
+#: xs/src/libslic3r/PrintConfig.cpp:798
 msgid "Infill extruder"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:766
+#: xs/src/libslic3r/PrintConfig.cpp:800
 msgid "The extruder to use when printing infill."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:774
+#: xs/src/libslic3r/PrintConfig.cpp:808
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for infill. If "
 "left zero, default extrusion width will be used if set, otherwise 1.125 x "
@@ -2670,32 +2908,32 @@ msgid ""
 "example 90%) it will be computed over layer height."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:783
+#: xs/src/libslic3r/PrintConfig.cpp:817
 msgid "Infill before perimeters"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:784
+#: xs/src/libslic3r/PrintConfig.cpp:818
 msgid ""
 "This option will switch the print order of perimeters and infill, making the "
 "latter first."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:789
+#: xs/src/libslic3r/PrintConfig.cpp:823
 msgid "Only infill where needed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:791
+#: xs/src/libslic3r/PrintConfig.cpp:825
 msgid ""
 "This option will limit infill to the areas actually needed for supporting "
 "ceilings (it will act as internal support material). If enabled, slows down "
 "the G-code generation due to the multiple checks involved."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:798
+#: xs/src/libslic3r/PrintConfig.cpp:832
 msgid "Infill/perimeters overlap"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:800
+#: xs/src/libslic3r/PrintConfig.cpp:834
 msgid ""
 "This setting applies an additional overlap between infill and perimeters for "
 "better bonding. Theoretically this shouldn't be needed, but backlash might "
@@ -2703,30 +2941,30 @@ msgid ""
 "perimeter extrusion width."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:811
+#: xs/src/libslic3r/PrintConfig.cpp:845
 msgid "Speed for printing the internal fill. Set to zero for auto."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:820
+#: xs/src/libslic3r/PrintConfig.cpp:854
 msgid "Inherits profile"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:821
+#: xs/src/libslic3r/PrintConfig.cpp:855
 msgid "Name of the profile, from which this profile inherits."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:827
+#: xs/src/libslic3r/PrintConfig.cpp:866
 msgid "Interface shells"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:828
+#: xs/src/libslic3r/PrintConfig.cpp:867
 msgid ""
 "Force the generation of solid shells between adjacent materials/volumes. "
 "Useful for multi-extruder prints with translucent materials or manual "
 "soluble support material."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:837
+#: xs/src/libslic3r/PrintConfig.cpp:876
 msgid ""
 "This custom code is inserted at every layer change, right after the Z move "
 "and before the extruder moves to the first layer point. Note that you can "
@@ -2734,21 +2972,75 @@ msgid ""
 "[layer_z]."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:849
+#: xs/src/libslic3r/PrintConfig.cpp:888
 msgid ""
 "This setting controls the height (and thus the total number) of the slices/"
 "layers. Thinner layers give better accuracy but take more time to print."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:857 xs/src/libslic3r/PrintConfig.cpp:866
+#: xs/src/libslic3r/PrintConfig.cpp:896
+msgid "Support silent mode"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:897
+msgid "Set silent mode for the G-code flavor"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:919
+#, possible-c-format
+msgid "Maximum feedrate %1%"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:921
+#, possible-c-format
+msgid "Maximum feedrate of the %1% axis"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:928
+#, possible-c-format
+msgid "Maximum acceleration %1%"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:930
+#, possible-c-format
+msgid "Maximum acceleration of the %1% axis"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:937
+#, possible-c-format
+msgid "Maximum jerk %1%"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:939
+#, possible-c-format
+msgid "Maximum jerk of the %1% axis"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:949 xs/src/libslic3r/PrintConfig.cpp:951
+msgid "Minimum feedrate when extruding"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:959 xs/src/libslic3r/PrintConfig.cpp:961
+msgid "Minimum travel feedrate"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:969 xs/src/libslic3r/PrintConfig.cpp:971
+msgid "Maximum acceleration when extruding"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:979 xs/src/libslic3r/PrintConfig.cpp:981
+msgid "Maximum acceleration when retracting"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:988 xs/src/libslic3r/PrintConfig.cpp:997
 msgid "Max"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:858
+#: xs/src/libslic3r/PrintConfig.cpp:989
 msgid "This setting represents the maximum speed of your fan."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:867
+#: xs/src/libslic3r/PrintConfig.cpp:998
 #, no-c-format
 msgid ""
 "This is the highest printable layer height for this extruder, used to cap "
@@ -2757,38 +3049,38 @@ msgid ""
 "adhesion. If set to 0, layer height is limited to 75% of the nozzle diameter."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:877
+#: xs/src/libslic3r/PrintConfig.cpp:1008
 msgid "Max print height"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:878
+#: xs/src/libslic3r/PrintConfig.cpp:1009
 msgid ""
 "Set this to the maximum height that can be reached by your extruder while "
 "printing."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:884
+#: xs/src/libslic3r/PrintConfig.cpp:1015
 msgid "Max print speed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:885
+#: xs/src/libslic3r/PrintConfig.cpp:1016
 msgid ""
 "When setting other speed settings to 0 Slic3r will autocalculate the optimal "
 "speed in order to keep constant extruder pressure. This experimental setting "
 "is used to set the highest print speed you want to allow."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:895
+#: xs/src/libslic3r/PrintConfig.cpp:1026
 msgid ""
 "This experimental setting is used to set the maximum volumetric speed your "
 "extruder supports."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:903
+#: xs/src/libslic3r/PrintConfig.cpp:1034
 msgid "Max volumetric slope positive"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:904 xs/src/libslic3r/PrintConfig.cpp:915
+#: xs/src/libslic3r/PrintConfig.cpp:1035 xs/src/libslic3r/PrintConfig.cpp:1046
 msgid ""
 "This experimental setting is used to limit the speed of change in extrusion "
 "rate. A value of 1.8 mm³/s² ensures, that a change from the extrusion rate "
@@ -2796,109 +3088,109 @@ msgid ""
 "s) to 5.4 mm³/s (feedrate 60 mm/s) will take at least 2 seconds."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:908 xs/src/libslic3r/PrintConfig.cpp:919
+#: xs/src/libslic3r/PrintConfig.cpp:1039 xs/src/libslic3r/PrintConfig.cpp:1050
 msgid "mm³/s²"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:914
+#: xs/src/libslic3r/PrintConfig.cpp:1045
 msgid "Max volumetric slope negative"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:925 xs/src/libslic3r/PrintConfig.cpp:934
+#: xs/src/libslic3r/PrintConfig.cpp:1056 xs/src/libslic3r/PrintConfig.cpp:1065
 msgid "Min"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:926
+#: xs/src/libslic3r/PrintConfig.cpp:1057
 msgid "This setting represents the minimum PWM your fan needs to work."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:935
+#: xs/src/libslic3r/PrintConfig.cpp:1066
 msgid ""
 "This is the lowest printable layer height for this extruder and limits the "
 "resolution for variable layer height. Typical values are between 0.05 mm and "
 "0.1 mm."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:943
+#: xs/src/libslic3r/PrintConfig.cpp:1074
 msgid "Min print speed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:944
+#: xs/src/libslic3r/PrintConfig.cpp:1075
 msgid "Slic3r will not scale speed down below this speed."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:951
+#: xs/src/libslic3r/PrintConfig.cpp:1082
 msgid "Minimal filament extrusion length"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:952
+#: xs/src/libslic3r/PrintConfig.cpp:1083
 msgid ""
 "Generate no less than the number of skirt loops required to consume the "
 "specified amount of filament on the bottom layer. For multi-extruder "
 "machines, this minimum applies to each extruder."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:961
+#: xs/src/libslic3r/PrintConfig.cpp:1092
 msgid "Configuration notes"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:962
+#: xs/src/libslic3r/PrintConfig.cpp:1093
 msgid ""
 "You can put here your personal notes. This text will be added to the G-code "
 "header comments."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:971
+#: xs/src/libslic3r/PrintConfig.cpp:1102
 msgid "Nozzle diameter"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:972
+#: xs/src/libslic3r/PrintConfig.cpp:1103
 msgid ""
 "This is the diameter of your extruder nozzle (for example: 0.5, 0.35 etc.)"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:978
+#: xs/src/libslic3r/PrintConfig.cpp:1109
 msgid "API Key"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:979
+#: xs/src/libslic3r/PrintConfig.cpp:1110
 msgid ""
 "Slic3r can upload G-code files to OctoPrint. This field should contain the "
 "API Key required for authentication."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:992
+#: xs/src/libslic3r/PrintConfig.cpp:1123
 msgid "Hostname, IP or URL"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:993
+#: xs/src/libslic3r/PrintConfig.cpp:1124
 msgid ""
 "Slic3r can upload G-code files to OctoPrint. This field should contain the "
 "hostname, IP address or URL of the OctoPrint instance."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:999
+#: xs/src/libslic3r/PrintConfig.cpp:1130
 msgid "Only retract when crossing perimeters"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1000
+#: xs/src/libslic3r/PrintConfig.cpp:1131
 msgid ""
 "Disables retraction when the travel path does not exceed the upper layer's "
 "perimeters (and thus any ooze will be probably invisible)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1007
+#: xs/src/libslic3r/PrintConfig.cpp:1138
 msgid ""
 "This option will drop the temperature of the inactive extruders to prevent "
 "oozing. It will enable a tall skirt automatically and move extruders outside "
 "such skirt when changing temperatures."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1014
+#: xs/src/libslic3r/PrintConfig.cpp:1145
 msgid "Output filename format"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1015
+#: xs/src/libslic3r/PrintConfig.cpp:1146
 msgid ""
 "You can use all configuration options as variables inside this template. For "
 "example: [layer_height], [fill_density] etc. You can also use [timestamp], "
@@ -2906,48 +3198,60 @@ msgid ""
 "[input_filename], [input_filename_base]."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1024
+#: xs/src/libslic3r/PrintConfig.cpp:1155
 msgid "Detect bridging perimeters"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1026
+#: xs/src/libslic3r/PrintConfig.cpp:1157
 msgid ""
 "Experimental option to adjust flow for overhangs (bridge flow will be used), "
 "to apply bridge speed to them and enable fan."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1032
+#: xs/src/libslic3r/PrintConfig.cpp:1163
 msgid "Filament parking position"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1033
+#: xs/src/libslic3r/PrintConfig.cpp:1164
 msgid ""
 "Distance of the extruder tip from the position where the filament is parked "
 "when unloaded. This should match the value in printer firmware. "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1041 xs/src/libslic3r/PrintConfig.cpp:1059
-#: xs/src/libslic3r/PrintConfig.cpp:1071 xs/src/libslic3r/PrintConfig.cpp:1081
+#: xs/src/libslic3r/PrintConfig.cpp:1172
+msgid "Extra loading distance"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1173
+msgid ""
+"When set to zero, the distance the filament is moved from parking position "
+"during load is exactly the same as it was moved back during unload. When "
+"positive, it is loaded further,  if negative, the loading move is shorter "
+"than unloading. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1181 xs/src/libslic3r/PrintConfig.cpp:1199
+#: xs/src/libslic3r/PrintConfig.cpp:1211 xs/src/libslic3r/PrintConfig.cpp:1221
 msgid "Perimeters"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1042
+#: xs/src/libslic3r/PrintConfig.cpp:1182
 msgid ""
 "This is the acceleration your printer will use for perimeters. A high value "
 "like 9000 usually gives good results if your hardware is up to the job. Set "
 "zero to disable acceleration control for perimeters."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1050
+#: xs/src/libslic3r/PrintConfig.cpp:1190
 msgid "Perimeter extruder"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1052
+#: xs/src/libslic3r/PrintConfig.cpp:1192
 msgid ""
 "The extruder to use when printing perimeters and brim. First extruder is 1."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1061
+#: xs/src/libslic3r/PrintConfig.cpp:1201
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for perimeters. "
 "You may want to use thinner extrudates to get more accurate surfaces. If "
@@ -2956,12 +3260,12 @@ msgid ""
 "it will be computed over layer height."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1073
+#: xs/src/libslic3r/PrintConfig.cpp:1213
 msgid ""
 "Speed for perimeters (contours, aka vertical shells). Set to zero for auto."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1083
+#: xs/src/libslic3r/PrintConfig.cpp:1223
 msgid ""
 "This option sets the number of perimeters to generate for each layer. Note "
 "that Slic3r may increase this number automatically when it detects sloping "
@@ -2969,59 +3273,59 @@ msgid ""
 "Perimeters option is enabled."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1087
+#: xs/src/libslic3r/PrintConfig.cpp:1227
 msgid "(minimum)"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1107
+#: xs/src/libslic3r/PrintConfig.cpp:1247
 msgid "Printer type"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1108
+#: xs/src/libslic3r/PrintConfig.cpp:1248
 msgid "Type of the printer."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1112
+#: xs/src/libslic3r/PrintConfig.cpp:1252
 msgid "Printer notes"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1113
+#: xs/src/libslic3r/PrintConfig.cpp:1253
 msgid "You can put your notes regarding the printer here."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1121
+#: xs/src/libslic3r/PrintConfig.cpp:1261
 msgid "Printer vendor"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1122
+#: xs/src/libslic3r/PrintConfig.cpp:1262
 msgid "Name of the printer vendor."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1126
+#: xs/src/libslic3r/PrintConfig.cpp:1266
 msgid "Printer variant"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1127
+#: xs/src/libslic3r/PrintConfig.cpp:1267
 msgid ""
 "Name of the printer variant. For example, the printer variants may be "
 "differentiated by a nozzle diameter."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1137
+#: xs/src/libslic3r/PrintConfig.cpp:1277
 msgid "Raft layers"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1139
+#: xs/src/libslic3r/PrintConfig.cpp:1279
 msgid ""
 "The object will be raised by this number of layers, and support material "
 "will be generated under it."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1147
+#: xs/src/libslic3r/PrintConfig.cpp:1287
 msgid "Resolution"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1148
+#: xs/src/libslic3r/PrintConfig.cpp:1288
 msgid ""
 "Minimum detail resolution, used to simplify the input file for speeding up "
 "the slicing job and reducing memory usage. High-resolution models often "
@@ -3029,266 +3333,282 @@ msgid ""
 "simplification and use full resolution from input."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1158
+#: xs/src/libslic3r/PrintConfig.cpp:1298
 msgid "Minimum travel after retraction"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1159
+#: xs/src/libslic3r/PrintConfig.cpp:1299
 msgid ""
 "Retraction is not triggered when travel moves are shorter than this length."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1165
+#: xs/src/libslic3r/PrintConfig.cpp:1305
 msgid "Retract amount before wipe"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1166
+#: xs/src/libslic3r/PrintConfig.cpp:1306
 msgid ""
 "With bowden extruders, it may be wise to do some amount of quick retract "
 "before doing the wipe movement."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1173
+#: xs/src/libslic3r/PrintConfig.cpp:1313
 msgid "Retract on layer change"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1174
+#: xs/src/libslic3r/PrintConfig.cpp:1314
 msgid "This flag enforces a retraction whenever a Z move is done."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1179 xs/src/libslic3r/PrintConfig.cpp:1188
+#: xs/src/libslic3r/PrintConfig.cpp:1319 xs/src/libslic3r/PrintConfig.cpp:1328
 msgid "Length"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1180
+#: xs/src/libslic3r/PrintConfig.cpp:1320
 msgid "Retraction Length"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1181
+#: xs/src/libslic3r/PrintConfig.cpp:1321
 msgid ""
 "When retraction is triggered, filament is pulled back by the specified "
 "amount (the length is measured on raw filament, before it enters the "
 "extruder)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1183 xs/src/libslic3r/PrintConfig.cpp:1193
+#: xs/src/libslic3r/PrintConfig.cpp:1323 xs/src/libslic3r/PrintConfig.cpp:1333
 msgid "mm (zero to disable)"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1189
+#: xs/src/libslic3r/PrintConfig.cpp:1329
 msgid "Retraction Length (Toolchange)"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1190
+#: xs/src/libslic3r/PrintConfig.cpp:1330
 msgid ""
 "When retraction is triggered before changing tool, filament is pulled back "
 "by the specified amount (the length is measured on raw filament, before it "
 "enters the extruder)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1198
+#: xs/src/libslic3r/PrintConfig.cpp:1338
 msgid "Lift Z"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1199
+#: xs/src/libslic3r/PrintConfig.cpp:1339
 msgid ""
 "If you set this to a positive value, Z is quickly raised every time a "
 "retraction is triggered. When using multiple extruders, only the setting for "
 "the first extruder will be considered."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1207
+#: xs/src/libslic3r/PrintConfig.cpp:1347
 msgid "Above Z"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1208
+#: xs/src/libslic3r/PrintConfig.cpp:1348
 msgid "Only lift Z above"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1209
+#: xs/src/libslic3r/PrintConfig.cpp:1349
 msgid ""
 "If you set this to a positive value, Z lift will only take place above the "
 "specified absolute Z. You can tune this setting for skipping lift on the "
 "first layers."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1216
+#: xs/src/libslic3r/PrintConfig.cpp:1356
 msgid "Below Z"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1217
+#: xs/src/libslic3r/PrintConfig.cpp:1357
 msgid "Only lift Z below"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1218
+#: xs/src/libslic3r/PrintConfig.cpp:1358
 msgid ""
 "If you set this to a positive value, Z lift will only take place below the "
 "specified absolute Z. You can tune this setting for limiting lift to the "
 "first layers."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1226 xs/src/libslic3r/PrintConfig.cpp:1234
+#: xs/src/libslic3r/PrintConfig.cpp:1366 xs/src/libslic3r/PrintConfig.cpp:1374
 msgid "Extra length on restart"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1227
+#: xs/src/libslic3r/PrintConfig.cpp:1367
 msgid ""
 "When the retraction is compensated after the travel move, the extruder will "
 "push this additional amount of filament. This setting is rarely needed."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1235
+#: xs/src/libslic3r/PrintConfig.cpp:1375
 msgid ""
 "When the retraction is compensated after changing tool, the extruder will "
 "push this additional amount of filament."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1242 xs/src/libslic3r/PrintConfig.cpp:1243
+#: xs/src/libslic3r/PrintConfig.cpp:1382 xs/src/libslic3r/PrintConfig.cpp:1383
 msgid "Retraction Speed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1244
+#: xs/src/libslic3r/PrintConfig.cpp:1384
 msgid "The speed for retractions (it only applies to the extruder motor)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1250 xs/src/libslic3r/PrintConfig.cpp:1251
+#: xs/src/libslic3r/PrintConfig.cpp:1390 xs/src/libslic3r/PrintConfig.cpp:1391
 msgid "Deretraction Speed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1252
+#: xs/src/libslic3r/PrintConfig.cpp:1392
 msgid ""
 "The speed for loading of a filament into extruder after retraction (it only "
 "applies to the extruder motor). If left to zero, the retraction speed is "
 "used."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1259
+#: xs/src/libslic3r/PrintConfig.cpp:1399
 msgid "Seam position"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1261
+#: xs/src/libslic3r/PrintConfig.cpp:1401
 msgid "Position of perimeters starting points."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1277
+#: xs/src/libslic3r/PrintConfig.cpp:1408
+msgid "Random"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1409
+msgid "Nearest"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1410
+msgid "Aligned"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1411 lib/Slic3r/GUI/MainFrame.pm:330
+msgid "Rear"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1417
 msgid "Direction"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1279
+#: xs/src/libslic3r/PrintConfig.cpp:1419
 msgid "Preferred direction of the seam"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1280
+#: xs/src/libslic3r/PrintConfig.cpp:1420
 msgid "Seam preferred direction"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1288
+#: xs/src/libslic3r/PrintConfig.cpp:1428
 msgid "Jitter"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1290
+#: xs/src/libslic3r/PrintConfig.cpp:1430
 msgid "Seam preferred direction jitter"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1291
+#: xs/src/libslic3r/PrintConfig.cpp:1431
 msgid "Preferred direction of the seam - jitter"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1302
+#: xs/src/libslic3r/PrintConfig.cpp:1442
 msgid "USB/serial port for printer connection."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1310
+#: xs/src/libslic3r/PrintConfig.cpp:1450
 msgid "Serial port speed"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1311
+#: xs/src/libslic3r/PrintConfig.cpp:1451
 msgid "Speed (baud) of USB/serial port for printer connection."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1320
+#: xs/src/libslic3r/PrintConfig.cpp:1460
 msgid "Distance from object"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1321
+#: xs/src/libslic3r/PrintConfig.cpp:1461
 msgid ""
 "Distance between skirt and object(s). Set this to zero to attach the skirt "
 "to the object(s) and get a brim for better adhesion."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1329
+#: xs/src/libslic3r/PrintConfig.cpp:1469
 msgid "Skirt height"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1330
+#: xs/src/libslic3r/PrintConfig.cpp:1470
 msgid ""
 "Height of skirt expressed in layers. Set this to a tall value to use skirt "
 "as a shield against drafts."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1337
+#: xs/src/libslic3r/PrintConfig.cpp:1477
 msgid "Loops (minimum)"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1338
+#: xs/src/libslic3r/PrintConfig.cpp:1478
 msgid "Skirt Loops"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1339
+#: xs/src/libslic3r/PrintConfig.cpp:1479
 msgid ""
 "Number of loops for the skirt. If the Minimum Extrusion Length option is "
 "set, the number of loops might be greater than the one configured here. Set "
 "this to zero to disable skirt completely."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1347
+#: xs/src/libslic3r/PrintConfig.cpp:1487
 msgid "Slow down if layer print time is below"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1348
+#: xs/src/libslic3r/PrintConfig.cpp:1488
 msgid ""
 "If layer print time is estimated below this number of seconds, print moves "
 "speed will be scaled down to extend duration to this value."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1358
+#: xs/src/libslic3r/PrintConfig.cpp:1498
 msgid "Small perimeters"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1360
+#: xs/src/libslic3r/PrintConfig.cpp:1500
 msgid ""
 "This separate setting will affect the speed of perimeters having radius <= "
 "6.5mm (usually holes). If expressed as percentage (for example: 80%) it will "
 "be calculated on the perimeters speed setting above. Set to zero for auto."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1370
+#: xs/src/libslic3r/PrintConfig.cpp:1510
 msgid "Solid infill threshold area"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1372
+#: xs/src/libslic3r/PrintConfig.cpp:1512
 msgid ""
 "Force solid infill for regions having a smaller area than the specified "
 "threshold."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1373
+#: xs/src/libslic3r/PrintConfig.cpp:1513
 msgid "mm²"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1379
+#: xs/src/libslic3r/PrintConfig.cpp:1519
 msgid "Solid infill extruder"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1381
+#: xs/src/libslic3r/PrintConfig.cpp:1521
 msgid "The extruder to use when printing solid infill."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1387
+#: xs/src/libslic3r/PrintConfig.cpp:1527
 msgid "Solid infill every"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1389
+#: xs/src/libslic3r/PrintConfig.cpp:1529
 msgid ""
 "This feature allows to force a solid layer every given number of layers. "
 "Zero to disable. You can set this to any value (for example 9999); Slic3r "
@@ -3296,13 +3616,13 @@ msgid ""
 "according to nozzle diameter and layer height."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1399 xs/src/libslic3r/PrintConfig.cpp:1409
-#: xs/src/libslic3r/GCode/PreviewData.cpp:162
+#: xs/src/libslic3r/PrintConfig.cpp:1539 xs/src/libslic3r/PrintConfig.cpp:1549
+#: xs/src/libslic3r/GCode/PreviewData.cpp:167
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:94
 msgid "Solid infill"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1401
+#: xs/src/libslic3r/PrintConfig.cpp:1541
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for infill for "
 "solid surfaces. If left zero, default extrusion width will be used if set, "
@@ -3310,22 +3630,22 @@ msgid ""
 "(for example 90%) it will be computed over layer height."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1411
+#: xs/src/libslic3r/PrintConfig.cpp:1551
 msgid ""
 "Speed for printing solid regions (top/bottom/internal horizontal shells). "
 "This can be expressed as a percentage (for example: 80%) over the default "
 "infill speed above. Set to zero for auto."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1423
+#: xs/src/libslic3r/PrintConfig.cpp:1563
 msgid "Number of solid layers to generate on top and bottom surfaces."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1430
+#: xs/src/libslic3r/PrintConfig.cpp:1570
 msgid "Spiral vase"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1431
+#: xs/src/libslic3r/PrintConfig.cpp:1571
 msgid ""
 "This feature will raise Z gradually while printing a single-walled object in "
 "order to remove any visible seam. This option requires a single perimeter, "
@@ -3334,18 +3654,18 @@ msgid ""
 "when printing more than an object."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1440
+#: xs/src/libslic3r/PrintConfig.cpp:1580
 msgid "Temperature variation"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1441
+#: xs/src/libslic3r/PrintConfig.cpp:1581
 msgid ""
 "Temperature difference to be applied when an extruder is not active. Enables "
 "a full-height \"sacrificial\" skirt on which the nozzles are periodically "
 "wiped."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1451
+#: xs/src/libslic3r/PrintConfig.cpp:1591
 msgid ""
 "This start procedure is inserted at the beginning, after bed has reached the "
 "target temperature and extruder just started heating, and before extruder "
@@ -3356,7 +3676,7 @@ msgid ""
 "\"M109 S[first_layer_temperature]\" command wherever you want."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1466
+#: xs/src/libslic3r/PrintConfig.cpp:1606
 msgid ""
 "This start procedure is inserted at the beginning, after any printer start "
 "gcode. This is used to override settings for a specific filament. If Slic3r "
@@ -3368,64 +3688,72 @@ msgid ""
 "extruders, the gcode is processed in extruder order."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1481
+#: xs/src/libslic3r/PrintConfig.cpp:1621
 msgid "Single Extruder Multi Material"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1482
+#: xs/src/libslic3r/PrintConfig.cpp:1622
 msgid "The printer multiplexes filaments into a single hot end."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1487
+#: xs/src/libslic3r/PrintConfig.cpp:1627
 msgid "Generate support material"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1489
+#: xs/src/libslic3r/PrintConfig.cpp:1629
 msgid "Enable support material generation."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1494
+#: xs/src/libslic3r/PrintConfig.cpp:1634
 msgid "XY separation between an object and its support"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1496
+#: xs/src/libslic3r/PrintConfig.cpp:1636
 msgid ""
 "XY separation between an object and its support. If expressed as percentage "
 "(for example 50%), it will be calculated over external perimeter width."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1506
+#: xs/src/libslic3r/PrintConfig.cpp:1646
 msgid "Pattern angle"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1508
+#: xs/src/libslic3r/PrintConfig.cpp:1648
 msgid ""
 "Use this setting to rotate the support material pattern on the horizontal "
 "plane."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1518
+#: xs/src/libslic3r/PrintConfig.cpp:1658
 msgid ""
 "Only create support if it lies on a build plate. Don't create support on a "
 "print."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1524
+#: xs/src/libslic3r/PrintConfig.cpp:1664
 msgid "Contact Z distance"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1526
+#: xs/src/libslic3r/PrintConfig.cpp:1666
 msgid ""
 "The vertical distance between object and support material interface. Setting "
 "this to 0 will also prevent Slic3r from using bridge flow and speed for the "
 "first object layer."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1539
+#: xs/src/libslic3r/PrintConfig.cpp:1674
+msgid "soluble"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1675
+msgid "detachable"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1679
 msgid "Enforce support for the first"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1541
+#: xs/src/libslic3r/PrintConfig.cpp:1681
 msgid ""
 "Generate support material for the specified number of layers counting from "
 "bottom, regardless of whether normal support material is enabled or not and "
@@ -3433,21 +3761,21 @@ msgid ""
 "of objects having a very thin or poor footprint on the build plate."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1547
+#: xs/src/libslic3r/PrintConfig.cpp:1687
 msgid "Enforce support for the first n layers"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1552
+#: xs/src/libslic3r/PrintConfig.cpp:1692
 msgid "Support material/raft/skirt extruder"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1554
+#: xs/src/libslic3r/PrintConfig.cpp:1694
 msgid ""
 "The extruder to use when printing support material, raft and skirt (1+, 0 to "
 "use the current extruder to minimize tool changes)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1563
+#: xs/src/libslic3r/PrintConfig.cpp:1703
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for support "
 "material. If left zero, default extrusion width will be used if set, "
@@ -3455,91 +3783,95 @@ msgid ""
 "example 90%) it will be computed over layer height."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1571
+#: xs/src/libslic3r/PrintConfig.cpp:1711
 msgid "Interface loops"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1573
+#: xs/src/libslic3r/PrintConfig.cpp:1713
 msgid ""
 "Cover the top contact layer of the supports with loops. Disabled by default."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1578
+#: xs/src/libslic3r/PrintConfig.cpp:1718
 msgid "Support material/raft interface extruder"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1580
+#: xs/src/libslic3r/PrintConfig.cpp:1720
 msgid ""
 "The extruder to use when printing support material interface (1+, 0 to use "
 "the current extruder to minimize tool changes). This affects raft too."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1587
+#: xs/src/libslic3r/PrintConfig.cpp:1727
 msgid "Interface layers"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1589
+#: xs/src/libslic3r/PrintConfig.cpp:1729
 msgid ""
 "Number of interface layers to insert between the object(s) and support "
 "material."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1596
+#: xs/src/libslic3r/PrintConfig.cpp:1736
 msgid "Interface pattern spacing"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1598
+#: xs/src/libslic3r/PrintConfig.cpp:1738
 msgid "Spacing between interface lines. Set zero to get a solid interface."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1605
-#: xs/src/libslic3r/GCode/PreviewData.cpp:168
+#: xs/src/libslic3r/PrintConfig.cpp:1745
+#: xs/src/libslic3r/GCode/PreviewData.cpp:173
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:100
 msgid "Support material interface"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1607
+#: xs/src/libslic3r/PrintConfig.cpp:1747
 msgid ""
 "Speed for printing support material interface layers. If expressed as "
 "percentage (for example 50%) it will be calculated over support material "
 "speed."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1616
+#: xs/src/libslic3r/PrintConfig.cpp:1756
 msgid "Pattern"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1618
+#: xs/src/libslic3r/PrintConfig.cpp:1758
 msgid "Pattern used to generate support material."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1630
+#: xs/src/libslic3r/PrintConfig.cpp:1765
+msgid "Rectilinear grid"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1770
 msgid "Pattern spacing"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1632
+#: xs/src/libslic3r/PrintConfig.cpp:1772
 msgid "Spacing between support material lines."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1641
+#: xs/src/libslic3r/PrintConfig.cpp:1781
 msgid "Speed for printing support material."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1648
+#: xs/src/libslic3r/PrintConfig.cpp:1788
 msgid "Synchronize with object layers"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1650
+#: xs/src/libslic3r/PrintConfig.cpp:1790
 msgid ""
 "Synchronize support layers with the object print layers. This is useful with "
 "multi-material printers, where the extruder switch is expensive."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1656
+#: xs/src/libslic3r/PrintConfig.cpp:1796
 msgid "Overhang threshold"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1658
+#: xs/src/libslic3r/PrintConfig.cpp:1798
 msgid ""
 "Support material will not be generated for overhangs whose slope angle (90° "
 "= vertical) is above the given threshold. In other words, this value "
@@ -3548,60 +3880,60 @@ msgid ""
 "detection (recommended)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1670
+#: xs/src/libslic3r/PrintConfig.cpp:1810
 msgid "With sheath around the support"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1672
+#: xs/src/libslic3r/PrintConfig.cpp:1812
 msgid ""
 "Add a sheath (a single perimeter line) around the base support. This makes "
 "the support more reliable, but also more difficult to remove."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1679
+#: xs/src/libslic3r/PrintConfig.cpp:1819
 msgid ""
 "Extruder temperature for layers after the first one. Set this to zero to "
 "disable temperature control commands in the output."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1682
+#: xs/src/libslic3r/PrintConfig.cpp:1822
 msgid "Temperature"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1688
+#: xs/src/libslic3r/PrintConfig.cpp:1828
 msgid "Detect thin walls"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1690
+#: xs/src/libslic3r/PrintConfig.cpp:1830
 msgid ""
 "Detect single-width walls (parts where two extrusions don't fit and we need "
 "to collapse them into a single trace)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1696
+#: xs/src/libslic3r/PrintConfig.cpp:1836
 msgid "Threads"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1697
+#: xs/src/libslic3r/PrintConfig.cpp:1837
 msgid ""
 "Threads are used to parallelize long-running tasks. Optimal threads number "
 "is slightly above the number of available cores/processors."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1709
+#: xs/src/libslic3r/PrintConfig.cpp:1849
 msgid ""
 "This custom code is inserted right before every extruder change. Note that "
 "you can use placeholder variables for all Slic3r settings as well as "
 "[previous_extruder] and [next_extruder]."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1719 xs/src/libslic3r/PrintConfig.cpp:1730
-#: xs/src/libslic3r/GCode/PreviewData.cpp:163
+#: xs/src/libslic3r/PrintConfig.cpp:1859 xs/src/libslic3r/PrintConfig.cpp:1870
+#: xs/src/libslic3r/GCode/PreviewData.cpp:168
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:95
 msgid "Top solid infill"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1721
+#: xs/src/libslic3r/PrintConfig.cpp:1861
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for infill for "
 "top surfaces. You may want to use thinner extrudates to fill all narrow "
@@ -3610,7 +3942,7 @@ msgid ""
 "percentage (for example 90%) it will be computed over layer height."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1732
+#: xs/src/libslic3r/PrintConfig.cpp:1872
 msgid ""
 "Speed for printing top solid layers (it only applies to the uppermost "
 "external layers and not to their internal solid layers). You may want to "
@@ -3619,52 +3951,52 @@ msgid ""
 "for auto."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1744 lib/Slic3r/GUI/MainFrame.pm:308
+#: xs/src/libslic3r/PrintConfig.cpp:1884 lib/Slic3r/GUI/MainFrame.pm:327
 msgid "Top"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1746
+#: xs/src/libslic3r/PrintConfig.cpp:1886
 msgid "Number of solid layers to generate on top surfaces."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1748
+#: xs/src/libslic3r/PrintConfig.cpp:1888
 msgid "Top solid layers"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1753
+#: xs/src/libslic3r/PrintConfig.cpp:1893
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:105
 msgid "Travel"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1754
+#: xs/src/libslic3r/PrintConfig.cpp:1894
 msgid "Speed for travel moves (jumps between distant extrusion points)."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1762
+#: xs/src/libslic3r/PrintConfig.cpp:1902
 msgid "Use firmware retraction"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1763
+#: xs/src/libslic3r/PrintConfig.cpp:1903
 msgid ""
 "This experimental setting uses G10 and G11 commands to have the firmware "
 "handle the retraction. This is only supported in recent Marlin."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1769
+#: xs/src/libslic3r/PrintConfig.cpp:1909
 msgid "Use relative E distances"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1770
+#: xs/src/libslic3r/PrintConfig.cpp:1910
 msgid ""
 "If your firmware requires relative E values, check this, otherwise leave it "
 "unchecked. Most firmwares use absolute values."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1776
+#: xs/src/libslic3r/PrintConfig.cpp:1916
 msgid "Use volumetric E"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1777
+#: xs/src/libslic3r/PrintConfig.cpp:1917
 msgid ""
 "This experimental setting uses outputs the E values in cubic millimeters "
 "instead of linear millimeters. If your firmware doesn't already know "
@@ -3674,113 +4006,135 @@ msgid ""
 "only supported in recent Marlin."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1787
+#: xs/src/libslic3r/PrintConfig.cpp:1927
 msgid "Enable variable layer height feature"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1788
+#: xs/src/libslic3r/PrintConfig.cpp:1928
 msgid ""
 "Some printers or printer setups may have difficulties printing with a "
 "variable layer height. Enabled by default."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1794
+#: xs/src/libslic3r/PrintConfig.cpp:1934
 msgid "Wipe while retracting"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1795
+#: xs/src/libslic3r/PrintConfig.cpp:1935
 msgid ""
 "This flag will move the nozzle while retracting to minimize the possible "
 "blob on leaky extruders."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1802
+#: xs/src/libslic3r/PrintConfig.cpp:1942
 msgid ""
 "Multi material printers may need to prime or purge extruders on tool "
 "changes. Extrude the excess material into the wipe tower."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1808
+#: xs/src/libslic3r/PrintConfig.cpp:1948
 msgid "Purging volumes - load/unload volumes"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1809
+#: xs/src/libslic3r/PrintConfig.cpp:1949
 msgid ""
 "This vector saves required volumes to change from/to each tool used on the "
 "wipe tower. These values are used to simplify creation of the full purging "
 "volumes below. "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1816
+#: xs/src/libslic3r/PrintConfig.cpp:1956
 msgid "Purging volumes - matrix"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1817
+#: xs/src/libslic3r/PrintConfig.cpp:1957
 msgid ""
 "This matrix describes volumes (in cubic milimetres) required to purge the "
 "new filament on the wipe tower for any given pair of tools. "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1827
+#: xs/src/libslic3r/PrintConfig.cpp:1967
 msgid "Position X"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1828
+#: xs/src/libslic3r/PrintConfig.cpp:1968
 msgid "X coordinate of the left front corner of a wipe tower"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1834
+#: xs/src/libslic3r/PrintConfig.cpp:1974
 msgid "Position Y"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1835
+#: xs/src/libslic3r/PrintConfig.cpp:1975
 msgid "Y coordinate of the left front corner of a wipe tower"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1841 lib/Slic3r/GUI/Plater/3DPreview.pm:76
+#: xs/src/libslic3r/PrintConfig.cpp:1981 lib/Slic3r/GUI/Plater/3DPreview.pm:76
 msgid "Width"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1842
+#: xs/src/libslic3r/PrintConfig.cpp:1982
 msgid "Width of a wipe tower"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1848
+#: xs/src/libslic3r/PrintConfig.cpp:1988
 msgid "Wipe tower rotation angle"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1849
+#: xs/src/libslic3r/PrintConfig.cpp:1989
 msgid "Wipe tower rotation angle with respect to x-axis "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1850
+#: xs/src/libslic3r/PrintConfig.cpp:1990
 msgid "degrees"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1855
+#: xs/src/libslic3r/PrintConfig.cpp:1996
+msgid "Purging into infill"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1997
+msgid ""
+"Wiping after toolchange will be preferentially done inside infills. This "
+"lowers the amount of waste but may result in longer print time  due to "
+"additional travel moves."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:2005
+msgid "Purging into objects"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:2006
+msgid ""
+"Objects will be used to wipe the nozzle after a toolchange to save material "
+"that would otherwise end up in the wipe tower and decrease print time. "
+"Colours of the objects will be mixed as a result."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:2013
 msgid "Maximal bridging distance"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1856
+#: xs/src/libslic3r/PrintConfig.cpp:2014
 msgid "Maximal distance between supports on sparse infill sections. "
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1862
+#: xs/src/libslic3r/PrintConfig.cpp:2020
 msgid "XY Size Compensation"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1864
+#: xs/src/libslic3r/PrintConfig.cpp:2022
 msgid ""
 "The object will be grown/shrunk in the XY plane by the configured value "
 "(negative = inwards, positive = outwards). This might be useful for fine-"
 "tuning hole sizes."
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1872
+#: xs/src/libslic3r/PrintConfig.cpp:2030
 msgid "Z offset"
 msgstr ""
 
-#: xs/src/libslic3r/PrintConfig.cpp:1873
+#: xs/src/libslic3r/PrintConfig.cpp:2031
 msgid ""
 "This value will be added (or subtracted) from all the Z coordinates in the "
 "output G-code. It is used to compensate for bad Z endstop position: for "
@@ -3788,962 +4142,962 @@ msgid ""
 "print bed, set this to -0.3 (or fix your endstop)."
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:158
+#: xs/src/libslic3r/GCode/PreviewData.cpp:163
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:90
 msgid "Perimeter"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:159
+#: xs/src/libslic3r/GCode/PreviewData.cpp:164
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:91
 msgid "External perimeter"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:160
+#: xs/src/libslic3r/GCode/PreviewData.cpp:165
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:92
 msgid "Overhang perimeter"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:161
+#: xs/src/libslic3r/GCode/PreviewData.cpp:166
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:93
 msgid "Internal infill"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:164
+#: xs/src/libslic3r/GCode/PreviewData.cpp:169
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:96
 msgid "Bridge infill"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:171
+#: xs/src/libslic3r/GCode/PreviewData.cpp:176
 msgid "Mixed"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:362
+#: xs/src/libslic3r/GCode/PreviewData.cpp:367
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:74
 msgid "Feature type"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:364
+#: xs/src/libslic3r/GCode/PreviewData.cpp:369
 msgid "Height (mm)"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:366
+#: xs/src/libslic3r/GCode/PreviewData.cpp:371
 msgid "Width (mm)"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:368
+#: xs/src/libslic3r/GCode/PreviewData.cpp:373
 msgid "Speed (mm/s)"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:370
+#: xs/src/libslic3r/GCode/PreviewData.cpp:375
 msgid "Volumetric flow rate (mm3/s)"
 msgstr ""
 
-#: xs/src/libslic3r/GCode/PreviewData.cpp:372
+#: xs/src/libslic3r/GCode/PreviewData.cpp:377
 #: lib/Slic3r/GUI/Plater/3DPreview.pm:79
 msgid "Tool"
 msgstr ""
 
-#: lib/Slic3r/GUI.pm:307
+#: lib/Slic3r/GUI.pm:308
 msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:62
+#: lib/Slic3r/GUI/MainFrame.pm:66
 msgid "Version "
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:62
+#: lib/Slic3r/GUI/MainFrame.pm:66
 msgid ""
 " - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:116
+#: lib/Slic3r/GUI/MainFrame.pm:135
 msgid "Plater"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:118
+#: lib/Slic3r/GUI/MainFrame.pm:137
 msgid "Controller"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:196
+#: lib/Slic3r/GUI/MainFrame.pm:215
 msgid "Open STL/OBJ/AMF/3MF…\tCtrl+O"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:196
+#: lib/Slic3r/GUI/MainFrame.pm:215
 msgid "Open a model"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:199
+#: lib/Slic3r/GUI/MainFrame.pm:218
 msgid "&Load Config…\tCtrl+L"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:199
+#: lib/Slic3r/GUI/MainFrame.pm:218
 msgid "Load exported configuration file"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:202
+#: lib/Slic3r/GUI/MainFrame.pm:221
 msgid "&Export Config…\tCtrl+E"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:202
+#: lib/Slic3r/GUI/MainFrame.pm:221
 msgid "Export current configuration to file"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:205
+#: lib/Slic3r/GUI/MainFrame.pm:224
 msgid "&Load Config Bundle…"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:205
+#: lib/Slic3r/GUI/MainFrame.pm:224
 msgid "Load presets from a bundle"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:208
+#: lib/Slic3r/GUI/MainFrame.pm:227
 msgid "&Export Config Bundle…"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:208
+#: lib/Slic3r/GUI/MainFrame.pm:227
 msgid "Export all presets to file"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:213
+#: lib/Slic3r/GUI/MainFrame.pm:232
 msgid "Q&uick Slice…\tCtrl+U"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:213
+#: lib/Slic3r/GUI/MainFrame.pm:232
 msgid "Slice a file into a G-code"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:219
+#: lib/Slic3r/GUI/MainFrame.pm:238
 msgid "Quick Slice and Save &As…\tCtrl+Alt+U"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:219
+#: lib/Slic3r/GUI/MainFrame.pm:238
 msgid "Slice a file into a G-code, save as"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:225
+#: lib/Slic3r/GUI/MainFrame.pm:244
 msgid "&Repeat Last Quick Slice\tCtrl+Shift+U"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:225
+#: lib/Slic3r/GUI/MainFrame.pm:244
 msgid "Repeat last quick slice"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:232
+#: lib/Slic3r/GUI/MainFrame.pm:251
 msgid "Slice to SV&G…\tCtrl+G"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:232
+#: lib/Slic3r/GUI/MainFrame.pm:251
 msgid "Slice file to a multi-layer SVG"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:236
+#: lib/Slic3r/GUI/MainFrame.pm:255
 msgid "(&Re)Slice Now\tCtrl+S"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:236
+#: lib/Slic3r/GUI/MainFrame.pm:255
 msgid "Start new slicing process"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:239
+#: lib/Slic3r/GUI/MainFrame.pm:258
 msgid "Repair STL file…"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:239
+#: lib/Slic3r/GUI/MainFrame.pm:258
 msgid "Automatically repair an STL file"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:243
+#: lib/Slic3r/GUI/MainFrame.pm:262
 msgid "&Quit"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:243
+#: lib/Slic3r/GUI/MainFrame.pm:262
 msgid "Quit Slic3r"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:253
+#: lib/Slic3r/GUI/MainFrame.pm:272
 msgid "Export G-code..."
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:253
+#: lib/Slic3r/GUI/MainFrame.pm:272
 msgid "Export current plate as G-code"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:256
+#: lib/Slic3r/GUI/MainFrame.pm:275
 msgid "Export plate as STL..."
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:256
+#: lib/Slic3r/GUI/MainFrame.pm:275
 msgid "Export current plate as STL"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:259
+#: lib/Slic3r/GUI/MainFrame.pm:278
 msgid "Export plate as AMF..."
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:259
+#: lib/Slic3r/GUI/MainFrame.pm:278
 msgid "Export current plate as AMF"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:262
+#: lib/Slic3r/GUI/MainFrame.pm:281
 msgid "Export plate as 3MF..."
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:262
+#: lib/Slic3r/GUI/MainFrame.pm:281
 msgid "Export current plate as 3MF"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:275
+#: lib/Slic3r/GUI/MainFrame.pm:294
 msgid "Select &Plater Tab\tCtrl+1"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:275
+#: lib/Slic3r/GUI/MainFrame.pm:294
 msgid "Show the plater"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:281
+#: lib/Slic3r/GUI/MainFrame.pm:300
 msgid "Select &Controller Tab\tCtrl+T"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:281
+#: lib/Slic3r/GUI/MainFrame.pm:300
 msgid "Show the printer controller"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:289
+#: lib/Slic3r/GUI/MainFrame.pm:308
 msgid "Select P&rint Settings Tab\tCtrl+2"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:289
+#: lib/Slic3r/GUI/MainFrame.pm:308
 msgid "Show the print settings"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:292
+#: lib/Slic3r/GUI/MainFrame.pm:311
 msgid "Select &Filament Settings Tab\tCtrl+3"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:292
+#: lib/Slic3r/GUI/MainFrame.pm:311
 msgid "Show the filament settings"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:295
+#: lib/Slic3r/GUI/MainFrame.pm:314
 msgid "Select Print&er Settings Tab\tCtrl+4"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:295
+#: lib/Slic3r/GUI/MainFrame.pm:314
 msgid "Show the printer settings"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:307
+#: lib/Slic3r/GUI/MainFrame.pm:326
 msgid "Iso"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:307
+#: lib/Slic3r/GUI/MainFrame.pm:326
 msgid "Iso View"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:308
+#: lib/Slic3r/GUI/MainFrame.pm:327
 msgid "Top View"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:309
+#: lib/Slic3r/GUI/MainFrame.pm:328
 msgid "Bottom View"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:310
+#: lib/Slic3r/GUI/MainFrame.pm:329
 msgid "Front"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:310
+#: lib/Slic3r/GUI/MainFrame.pm:329
 msgid "Front View"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:311
-msgid "Rear"
-msgstr ""
-
-#: lib/Slic3r/GUI/MainFrame.pm:311
+#: lib/Slic3r/GUI/MainFrame.pm:330
 msgid "Rear View"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:312
+#: lib/Slic3r/GUI/MainFrame.pm:331
 msgid "Left"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:312
+#: lib/Slic3r/GUI/MainFrame.pm:331
 msgid "Left View"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:313
+#: lib/Slic3r/GUI/MainFrame.pm:332
 msgid "Right"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:313
+#: lib/Slic3r/GUI/MainFrame.pm:332
 msgid "Right View"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:319
+#: lib/Slic3r/GUI/MainFrame.pm:338
 msgid "Prusa 3D Drivers"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:319
+#: lib/Slic3r/GUI/MainFrame.pm:338
 msgid "Open the Prusa3D drivers download page in your browser"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:322
+#: lib/Slic3r/GUI/MainFrame.pm:341
 msgid "Prusa Edition Releases"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:322
+#: lib/Slic3r/GUI/MainFrame.pm:341
 msgid "Open the Prusa Edition releases page in your browser"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:329
+#: lib/Slic3r/GUI/MainFrame.pm:348
 msgid "Slic3r &Website"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:329
+#: lib/Slic3r/GUI/MainFrame.pm:348
 msgid "Open the Slic3r website in your browser"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:332
+#: lib/Slic3r/GUI/MainFrame.pm:351
 msgid "Slic3r &Manual"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:332
+#: lib/Slic3r/GUI/MainFrame.pm:351
 msgid "Open the Slic3r manual in your browser"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:336
+#: lib/Slic3r/GUI/MainFrame.pm:355
 msgid "System Info"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:336
+#: lib/Slic3r/GUI/MainFrame.pm:355
 msgid "Show system information"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:339
+#: lib/Slic3r/GUI/MainFrame.pm:358
 msgid "Show &Configuration Folder"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:339
+#: lib/Slic3r/GUI/MainFrame.pm:358
 msgid "Show user configuration folder (datadir)"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:342
+#: lib/Slic3r/GUI/MainFrame.pm:361
 msgid "Report an Issue"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:342
+#: lib/Slic3r/GUI/MainFrame.pm:361
 msgid "Report an issue on the Slic3r Prusa Edition"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:345
+#: lib/Slic3r/GUI/MainFrame.pm:364
 msgid "&About Slic3r"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:345
+#: lib/Slic3r/GUI/MainFrame.pm:364
 msgid "Show about dialog"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:355
+#: lib/Slic3r/GUI/MainFrame.pm:374
 msgid "&File"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:356
+#: lib/Slic3r/GUI/MainFrame.pm:375
 msgid "&Plater"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:357
+#: lib/Slic3r/GUI/MainFrame.pm:376
 msgid "&Object"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:358
+#: lib/Slic3r/GUI/MainFrame.pm:377
 msgid "&Window"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:359
+#: lib/Slic3r/GUI/MainFrame.pm:378
 msgid "&View"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:362
+#: lib/Slic3r/GUI/MainFrame.pm:381
 msgid "&Help"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:393
+#: lib/Slic3r/GUI/MainFrame.pm:412
 msgid "Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:405
+#: lib/Slic3r/GUI/MainFrame.pm:424
 msgid "No previously sliced file."
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:406 lib/Slic3r/GUI/Plater.pm:1406
+#: lib/Slic3r/GUI/MainFrame.pm:425 lib/Slic3r/GUI/Plater.pm:1405
 msgid "Error"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:410
+#: lib/Slic3r/GUI/MainFrame.pm:429
 msgid "Previously sliced file ("
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:410
+#: lib/Slic3r/GUI/MainFrame.pm:429
 msgid ") not found."
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:411
+#: lib/Slic3r/GUI/MainFrame.pm:430
 msgid "File Not Found"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:450
+#: lib/Slic3r/GUI/MainFrame.pm:469
 msgid "SVG"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:450
+#: lib/Slic3r/GUI/MainFrame.pm:469
 msgid "G-code"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:450 lib/Slic3r/GUI/Plater.pm:1756
+#: lib/Slic3r/GUI/MainFrame.pm:469 lib/Slic3r/GUI/Plater.pm:1795
 msgid " file as:"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:464
+#: lib/Slic3r/GUI/MainFrame.pm:483
 msgid "Slicing…"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:464
+#: lib/Slic3r/GUI/MainFrame.pm:483
 msgid "Processing "
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:484
+#: lib/Slic3r/GUI/MainFrame.pm:503
 msgid " was successfully sliced."
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:486
+#: lib/Slic3r/GUI/MainFrame.pm:505
 msgid "Slicing Done!"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:502
+#: lib/Slic3r/GUI/MainFrame.pm:521
 msgid "Select the STL file to repair:"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:516
+#: lib/Slic3r/GUI/MainFrame.pm:535
 msgid "Save OBJ file (less prone to coordinate errors than STL) as:"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:530
+#: lib/Slic3r/GUI/MainFrame.pm:549
 msgid "Your file was repaired."
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:530
+#: lib/Slic3r/GUI/MainFrame.pm:549
 msgid "Repair"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:541
+#: lib/Slic3r/GUI/MainFrame.pm:560
 msgid "Save configuration as:"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:559 lib/Slic3r/GUI/MainFrame.pm:603
+#: lib/Slic3r/GUI/MainFrame.pm:578 lib/Slic3r/GUI/MainFrame.pm:622
 msgid "Select configuration to load:"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:582
+#: lib/Slic3r/GUI/MainFrame.pm:601
 msgid "Save presets bundle as:"
 msgstr ""
 
-#: lib/Slic3r/GUI/MainFrame.pm:623
+#: lib/Slic3r/GUI/MainFrame.pm:642
 #, possible-perl-format
 msgid "%d presets successfully imported."
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:140 lib/Slic3r/GUI/Plater.pm:2282
+#: lib/Slic3r/GUI/Plater.pm:164 lib/Slic3r/GUI/Plater.pm:2323
 msgid "3D"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:180
+#: lib/Slic3r/GUI/Plater.pm:206
 msgid "2D"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:199
+#: lib/Slic3r/GUI/Plater.pm:224
 msgid "Layers"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:232 lib/Slic3r/GUI/Plater.pm:250
+#: lib/Slic3r/GUI/Plater.pm:250 lib/Slic3r/GUI/Plater.pm:268
 msgid "Add…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:234 lib/Slic3r/GUI/Plater.pm:252
+#: lib/Slic3r/GUI/Plater.pm:252 lib/Slic3r/GUI/Plater.pm:270
 msgid "Delete All"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:235 lib/Slic3r/GUI/Plater.pm:253
+#: lib/Slic3r/GUI/Plater.pm:253 lib/Slic3r/GUI/Plater.pm:271
 msgid "Arrange"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:237
+#: lib/Slic3r/GUI/Plater.pm:255
 msgid "More"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:238
+#: lib/Slic3r/GUI/Plater.pm:256
 msgid "Fewer"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:240
+#: lib/Slic3r/GUI/Plater.pm:258
 msgid "45° ccw"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:241
+#: lib/Slic3r/GUI/Plater.pm:259
 msgid "45° cw"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:242 lib/Slic3r/GUI/Plater.pm:258
+#: lib/Slic3r/GUI/Plater.pm:260 lib/Slic3r/GUI/Plater.pm:276
 msgid "Scale…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:243 lib/Slic3r/GUI/Plater.pm:259
-#: lib/Slic3r/GUI/Plater.pm:2252
+#: lib/Slic3r/GUI/Plater.pm:261 lib/Slic3r/GUI/Plater.pm:277
+#: lib/Slic3r/GUI/Plater.pm:2293
 msgid "Split"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:244 lib/Slic3r/GUI/Plater.pm:260
-#: lib/Slic3r/GUI/Plater.pm:2255
+#: lib/Slic3r/GUI/Plater.pm:262 lib/Slic3r/GUI/Plater.pm:278
+#: lib/Slic3r/GUI/Plater.pm:2296
 msgid "Cut…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:246 lib/Slic3r/GUI/Plater.pm:261
-#: lib/Slic3r/GUI/Plater.pm:2259
+#: lib/Slic3r/GUI/Plater.pm:264 lib/Slic3r/GUI/Plater.pm:279
+#: lib/Slic3r/GUI/Plater.pm:2300
 msgid "Settings…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:247
+#: lib/Slic3r/GUI/Plater.pm:265
 msgid "Layer Editing"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:262
+#: lib/Slic3r/GUI/Plater.pm:280
 msgid "Layer editing"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:285
+#: lib/Slic3r/GUI/Plater.pm:303
 msgid "Name"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:286 lib/Slic3r/GUI/Plater.pm:1007
+#: lib/Slic3r/GUI/Plater.pm:304 lib/Slic3r/GUI/Plater.pm:992
 msgid "Copies"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:287 lib/Slic3r/GUI/Plater.pm:1163
-#: lib/Slic3r/GUI/Plater.pm:1168 lib/Slic3r/GUI/Plater.pm:2221
+#: lib/Slic3r/GUI/Plater.pm:305 lib/Slic3r/GUI/Plater.pm:1158
+#: lib/Slic3r/GUI/Plater.pm:1163 lib/Slic3r/GUI/Plater.pm:2262
 msgid "Scale"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:301
+#: lib/Slic3r/GUI/Plater.pm:322
 msgid "Export G-code…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:302
+#: lib/Slic3r/GUI/Plater.pm:323
 msgid "Slice now"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:303
+#: lib/Slic3r/GUI/Plater.pm:324
 msgid "Print…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:304
+#: lib/Slic3r/GUI/Plater.pm:325
 msgid "Send to printer"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:305
+#: lib/Slic3r/GUI/Plater.pm:326
 msgid "Export STL…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:432
+#: lib/Slic3r/GUI/Plater.pm:453
 msgid "Print settings"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:434
+#: lib/Slic3r/GUI/Plater.pm:455
 msgid "Printer"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:467
+#: lib/Slic3r/GUI/Plater.pm:488
 msgid "Info"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:478
+#: lib/Slic3r/GUI/Plater.pm:499
 msgid "Volume"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:479
+#: lib/Slic3r/GUI/Plater.pm:500
 msgid "Facets"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:480
+#: lib/Slic3r/GUI/Plater.pm:501
 msgid "Materials"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:481
+#: lib/Slic3r/GUI/Plater.pm:502
 msgid "Manifold"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:507
+#: lib/Slic3r/GUI/Plater.pm:527
 msgid "Sliced Info"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:516
-msgid "Used Filament (m)"
-msgstr ""
-
-#: lib/Slic3r/GUI/Plater.pm:517
-msgid "Used Filament (mm³)"
-msgstr ""
-
-#: lib/Slic3r/GUI/Plater.pm:518
-msgid "Used Filament (g)"
-msgstr ""
-
-#: lib/Slic3r/GUI/Plater.pm:520
-msgid "Estimated printing time"
-msgstr ""
-
-#: lib/Slic3r/GUI/Plater.pm:728
+#: lib/Slic3r/GUI/Plater.pm:713
 msgid "Loading…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:728 lib/Slic3r/GUI/Plater.pm:742
+#: lib/Slic3r/GUI/Plater.pm:713 lib/Slic3r/GUI/Plater.pm:727
 msgid "Processing input file\n"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:765
+#: lib/Slic3r/GUI/Plater.pm:750
 msgid ""
 "This file contains several objects positioned at multiple heights. Instead "
 "of considering them as multiple objects, should I consider\n"
 "this file as a single object having multiple parts?\n"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:768 lib/Slic3r/GUI/Plater.pm:785
+#: lib/Slic3r/GUI/Plater.pm:753 lib/Slic3r/GUI/Plater.pm:770
 msgid "Multi-part object detected"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:782
+#: lib/Slic3r/GUI/Plater.pm:767
 msgid ""
 "Multiple objects were loaded for a multi-material printer.\n"
 "Instead of considering them as multiple objects, should I consider\n"
 "these files to represent a single object having multiple parts?\n"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:794
+#: lib/Slic3r/GUI/Plater.pm:779
 msgid "Loaded "
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:852
+#: lib/Slic3r/GUI/Plater.pm:837
 msgid ""
 "Your object appears to be too large, so it was automatically scaled down to "
 "fit your print bed."
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:853
+#: lib/Slic3r/GUI/Plater.pm:838
 msgid "Object too large?"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1007
+#: lib/Slic3r/GUI/Plater.pm:992
 msgid "Enter the number of copies of the selected object:"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1034
+#: lib/Slic3r/GUI/Plater.pm:1019
 msgid ""
 "\n"
 "Non-positive value."
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1035
+#: lib/Slic3r/GUI/Plater.pm:1020
 msgid ""
 "\n"
 "Not a numeric value."
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1036
+#: lib/Slic3r/GUI/Plater.pm:1021
 msgid "Slic3r Error"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1057
+#: lib/Slic3r/GUI/Plater.pm:1042
 msgid "Enter the rotation angle:"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1057
+#: lib/Slic3r/GUI/Plater.pm:1042
 msgid "Rotate around "
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1057
+#: lib/Slic3r/GUI/Plater.pm:1042
 msgid "Invalid rotation angle entered"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1137
+#: lib/Slic3r/GUI/Plater.pm:1132
 #, possible-perl-format
 msgid "Enter the new size for the selected object (print bed: %smm):"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1138 lib/Slic3r/GUI/Plater.pm:1142
+#: lib/Slic3r/GUI/Plater.pm:1133 lib/Slic3r/GUI/Plater.pm:1137
 msgid "Scale along "
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1138 lib/Slic3r/GUI/Plater.pm:1142
-#: lib/Slic3r/GUI/Plater.pm:1163 lib/Slic3r/GUI/Plater.pm:1168
+#: lib/Slic3r/GUI/Plater.pm:1133 lib/Slic3r/GUI/Plater.pm:1137
+#: lib/Slic3r/GUI/Plater.pm:1158 lib/Slic3r/GUI/Plater.pm:1163
 msgid "Invalid scaling value entered"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1142 lib/Slic3r/GUI/Plater.pm:1168
+#: lib/Slic3r/GUI/Plater.pm:1137 lib/Slic3r/GUI/Plater.pm:1163
 #, no-perl-format
 msgid "Enter the scale % for the selected object:"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1163
+#: lib/Slic3r/GUI/Plater.pm:1158
 msgid "Enter the new max size for the selected object:"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1219
+#: lib/Slic3r/GUI/Plater.pm:1218
 msgid ""
 "The selected object can't be split because it contains more than one volume/"
 "material."
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1228
+#: lib/Slic3r/GUI/Plater.pm:1227
 msgid ""
 "The selected object couldn't be split because it contains only one part."
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1392
+#: lib/Slic3r/GUI/Plater.pm:1391
 msgid "Slicing cancelled"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1406
+#: lib/Slic3r/GUI/Plater.pm:1405
 msgid "Another export job is currently running."
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1556
+#: lib/Slic3r/GUI/Plater.pm:1555
 msgid "File added to print queue"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1562
+#: lib/Slic3r/GUI/Plater.pm:1561
 msgid "G-code file exported to "
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1565
+#: lib/Slic3r/GUI/Plater.pm:1564
 msgid "Export failed"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1577
+#: lib/Slic3r/GUI/Plater.pm:1576
 msgid "OctoPrint upload finished."
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1620 lib/Slic3r/GUI/Plater.pm:1662
+#: lib/Slic3r/GUI/Plater.pm:1610
+msgid "Used Filament (m)"
+msgstr ""
+
+#: lib/Slic3r/GUI/Plater.pm:1612
+msgid "Used Filament (mm³)"
+msgstr ""
+
+#: lib/Slic3r/GUI/Plater.pm:1614
+msgid "Used Filament (g)"
+msgstr ""
+
+#: lib/Slic3r/GUI/Plater.pm:1618
+msgid "Estimated printing time (normal mode)"
+msgstr ""
+
+#: lib/Slic3r/GUI/Plater.pm:1620
+msgid "Estimated printing time (silent mode)"
+msgstr ""
+
+#: lib/Slic3r/GUI/Plater.pm:1659 lib/Slic3r/GUI/Plater.pm:1701
 msgid "STL file exported to "
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1701
+#: lib/Slic3r/GUI/Plater.pm:1740
 msgid "AMF file exported to "
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1705
+#: lib/Slic3r/GUI/Plater.pm:1744
 msgid "Error exporting AMF file "
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1717
+#: lib/Slic3r/GUI/Plater.pm:1756
 msgid "3MF file exported to "
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:1721
+#: lib/Slic3r/GUI/Plater.pm:1760
 msgid "Error exporting 3MF file "
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2099
+#: lib/Slic3r/GUI/Plater.pm:2140
 #, possible-perl-format
 msgid "%d (%d shells)"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2101
+#: lib/Slic3r/GUI/Plater.pm:2142
 #, possible-perl-format
 msgid "Auto-repaired (%d errors)"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2106
+#: lib/Slic3r/GUI/Plater.pm:2147
 #, possible-perl-format
 msgid ""
 "%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d "
 "facets reversed, %d backwards edges"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2111
+#: lib/Slic3r/GUI/Plater.pm:2152
 msgid "Yes"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2174
+#: lib/Slic3r/GUI/Plater.pm:2215
 msgid "Remove the selected object"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2177
+#: lib/Slic3r/GUI/Plater.pm:2218
 msgid "Increase copies"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2177
+#: lib/Slic3r/GUI/Plater.pm:2218
 msgid "Place one more copy of the selected object"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2180
+#: lib/Slic3r/GUI/Plater.pm:2221
 msgid "Decrease copies"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2180
+#: lib/Slic3r/GUI/Plater.pm:2221
 msgid "Remove one copy of the selected object"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2183
+#: lib/Slic3r/GUI/Plater.pm:2224
 msgid "Set number of copies…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2183
+#: lib/Slic3r/GUI/Plater.pm:2224
 msgid "Change the number of copies of the selected object"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2187
+#: lib/Slic3r/GUI/Plater.pm:2228
 msgid "Rotate 45° clockwise"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2187
+#: lib/Slic3r/GUI/Plater.pm:2228
 msgid "Rotate the selected object by 45° clockwise"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2190
+#: lib/Slic3r/GUI/Plater.pm:2231
 msgid "Rotate 45° counter-clockwise"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2190
+#: lib/Slic3r/GUI/Plater.pm:2231
 msgid "Rotate the selected object by 45° counter-clockwise"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2195
+#: lib/Slic3r/GUI/Plater.pm:2236
 msgid "Rotate"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2195
+#: lib/Slic3r/GUI/Plater.pm:2236
 msgid "Rotate the selected object by an arbitrary angle"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2197
+#: lib/Slic3r/GUI/Plater.pm:2238
 msgid "Around X axis…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2197
+#: lib/Slic3r/GUI/Plater.pm:2238
 msgid "Rotate the selected object by an arbitrary angle around X axis"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2200
+#: lib/Slic3r/GUI/Plater.pm:2241
 msgid "Around Y axis…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2200
+#: lib/Slic3r/GUI/Plater.pm:2241
 msgid "Rotate the selected object by an arbitrary angle around Y axis"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2203
+#: lib/Slic3r/GUI/Plater.pm:2244
 msgid "Around Z axis…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2203
+#: lib/Slic3r/GUI/Plater.pm:2244
 msgid "Rotate the selected object by an arbitrary angle around Z axis"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2208
+#: lib/Slic3r/GUI/Plater.pm:2249
 msgid "Mirror"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2208
+#: lib/Slic3r/GUI/Plater.pm:2249
 msgid "Mirror the selected object"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2210 lib/Slic3r/GUI/Plater.pm:2226
-#: lib/Slic3r/GUI/Plater.pm:2242
+#: lib/Slic3r/GUI/Plater.pm:2251 lib/Slic3r/GUI/Plater.pm:2267
+#: lib/Slic3r/GUI/Plater.pm:2283
 msgid "Along X axis…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2210
+#: lib/Slic3r/GUI/Plater.pm:2251
 msgid "Mirror the selected object along the X axis"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2213 lib/Slic3r/GUI/Plater.pm:2229
-#: lib/Slic3r/GUI/Plater.pm:2245
+#: lib/Slic3r/GUI/Plater.pm:2254 lib/Slic3r/GUI/Plater.pm:2270
+#: lib/Slic3r/GUI/Plater.pm:2286
 msgid "Along Y axis…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2213
+#: lib/Slic3r/GUI/Plater.pm:2254
 msgid "Mirror the selected object along the Y axis"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2216 lib/Slic3r/GUI/Plater.pm:2232
-#: lib/Slic3r/GUI/Plater.pm:2248
+#: lib/Slic3r/GUI/Plater.pm:2257 lib/Slic3r/GUI/Plater.pm:2273
+#: lib/Slic3r/GUI/Plater.pm:2289
 msgid "Along Z axis…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2216
+#: lib/Slic3r/GUI/Plater.pm:2257
 msgid "Mirror the selected object along the Z axis"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2221 lib/Slic3r/GUI/Plater.pm:2237
+#: lib/Slic3r/GUI/Plater.pm:2262 lib/Slic3r/GUI/Plater.pm:2278
 msgid "Scale the selected object along a single axis"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2223 lib/Slic3r/GUI/Plater.pm:2239
+#: lib/Slic3r/GUI/Plater.pm:2264 lib/Slic3r/GUI/Plater.pm:2280
 msgid "Uniformly…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2223 lib/Slic3r/GUI/Plater.pm:2239
+#: lib/Slic3r/GUI/Plater.pm:2264 lib/Slic3r/GUI/Plater.pm:2280
 msgid "Scale the selected object along the XYZ axes"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2226 lib/Slic3r/GUI/Plater.pm:2242
+#: lib/Slic3r/GUI/Plater.pm:2267 lib/Slic3r/GUI/Plater.pm:2283
 msgid "Scale the selected object along the X axis"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2229 lib/Slic3r/GUI/Plater.pm:2245
+#: lib/Slic3r/GUI/Plater.pm:2270 lib/Slic3r/GUI/Plater.pm:2286
 msgid "Scale the selected object along the Y axis"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2232 lib/Slic3r/GUI/Plater.pm:2248
+#: lib/Slic3r/GUI/Plater.pm:2273 lib/Slic3r/GUI/Plater.pm:2289
 msgid "Scale the selected object along the Z axis"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2237
+#: lib/Slic3r/GUI/Plater.pm:2278
 msgid "Scale to size"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2252
+#: lib/Slic3r/GUI/Plater.pm:2293
 msgid "Split the selected object into individual parts"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2255
+#: lib/Slic3r/GUI/Plater.pm:2296
 msgid "Open the 3D cutting tool"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2259
+#: lib/Slic3r/GUI/Plater.pm:2300
 msgid "Open the object editor dialog"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2263
+#: lib/Slic3r/GUI/Plater.pm:2304
 msgid "Reload from Disk"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2263
+#: lib/Slic3r/GUI/Plater.pm:2304
 msgid "Reload the selected file from Disk"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2266
+#: lib/Slic3r/GUI/Plater.pm:2307
 msgid "Export object as STL…"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2266
+#: lib/Slic3r/GUI/Plater.pm:2307
 msgid "Export this single object as STL file"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2270
+#: lib/Slic3r/GUI/Plater.pm:2311
 msgid "Fix STL through Netfabb"
 msgstr ""
 
-#: lib/Slic3r/GUI/Plater.pm:2270
+#: lib/Slic3r/GUI/Plater.pm:2311
 msgid ""
 "Fix the model by sending it to a Netfabb cloud service through Windows 10 API"
 msgstr ""
diff --git a/resources/localization/uk/Slic3rPE.mo b/resources/localization/uk/Slic3rPE.mo
index 7ced15dc8..db63e8c8f 100644
Binary files a/resources/localization/uk/Slic3rPE.mo and b/resources/localization/uk/Slic3rPE.mo differ
diff --git a/resources/localization/uk/Slic3rPE_uk.po b/resources/localization/uk/Slic3rPE_uk.po
index 24b12095d..7ec3678ba 100644
--- a/resources/localization/uk/Slic3rPE_uk.po
+++ b/resources/localization/uk/Slic3rPE_uk.po
@@ -2,89 +2,86 @@ msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2018-02-28 13:53+0100\n"
-"PO-Revision-Date: 2018-03-21 16:01+0100\n"
+"POT-Creation-Date: 2018-07-23 12:06+0200\n"
+"PO-Revision-Date: 2018-07-23 12:46+0200\n"
 "Last-Translator: Oleksandra Iushchenko <yusanka@gmail.com>\n"
 "Language-Team: \n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.0.6\n"
+"X-Generator: Poedit 2.0.8\n"
 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
 "Language: uk\n"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:39
+#: xs/src/slic3r/GUI/AboutDialog.cpp:32
+msgid "About Slic3r"
+msgstr ""
+
+#: xs/src/slic3r/GUI/AboutDialog.cpp:67
+msgid "Version"
+msgstr ""
+
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:39
 msgid "Shape"
 msgstr "Вигляд (Форма)"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:46
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:46
 msgid "Rectangular"
 msgstr "Прямокутний"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:50
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1191
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:408
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:50 xs/src/slic3r/GUI/Tab.cpp:1826
+#: lib/Slic3r/GUI/Plater.pm:498
 msgid "Size"
 msgstr "Розмір"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:51
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:51
 msgid "Size in X and Y of the rectangular plate."
 msgstr "Розмір прямокутної подложки за X та Y."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:57
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:57
 msgid "Origin"
 msgstr "Початок координат"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:58
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:58
 msgid ""
 "Distance of the 0,0 G-code coordinate from the front left corner of the "
 "rectangle."
 msgstr "Відстань координат 0,0 G-коду від нижнього лівого кута прямокутника."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:62
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:62
 msgid "Circular"
 msgstr "Круговий"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:65
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:129
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:200
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:211
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:325
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:336
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:355
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:434
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:781
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:801
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:860
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:878
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:896
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1044
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1052
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1094
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1103
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1113
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1121
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1129
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1215
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1421
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1491
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1527
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1704
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1711
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1718
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1727
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1737
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1747
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:65
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:88 xs/src/slic3r/GUI/ConfigWizard.cpp:446
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:460 xs/src/slic3r/GUI/RammingChart.cpp:81
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:79
+#: xs/src/libslic3r/PrintConfig.cpp:133 xs/src/libslic3r/PrintConfig.cpp:181
+#: xs/src/libslic3r/PrintConfig.cpp:189 xs/src/libslic3r/PrintConfig.cpp:237
+#: xs/src/libslic3r/PrintConfig.cpp:248 xs/src/libslic3r/PrintConfig.cpp:363
+#: xs/src/libslic3r/PrintConfig.cpp:374 xs/src/libslic3r/PrintConfig.cpp:393
+#: xs/src/libslic3r/PrintConfig.cpp:531 xs/src/libslic3r/PrintConfig.cpp:890
+#: xs/src/libslic3r/PrintConfig.cpp:1002 xs/src/libslic3r/PrintConfig.cpp:1010
+#: xs/src/libslic3r/PrintConfig.cpp:1068 xs/src/libslic3r/PrintConfig.cpp:1086
+#: xs/src/libslic3r/PrintConfig.cpp:1104 xs/src/libslic3r/PrintConfig.cpp:1166
+#: xs/src/libslic3r/PrintConfig.cpp:1176 xs/src/libslic3r/PrintConfig.cpp:1292
+#: xs/src/libslic3r/PrintConfig.cpp:1300 xs/src/libslic3r/PrintConfig.cpp:1342
+#: xs/src/libslic3r/PrintConfig.cpp:1351 xs/src/libslic3r/PrintConfig.cpp:1361
+#: xs/src/libslic3r/PrintConfig.cpp:1369 xs/src/libslic3r/PrintConfig.cpp:1377
+#: xs/src/libslic3r/PrintConfig.cpp:1463 xs/src/libslic3r/PrintConfig.cpp:1669
+#: xs/src/libslic3r/PrintConfig.cpp:1739 xs/src/libslic3r/PrintConfig.cpp:1773
+#: xs/src/libslic3r/PrintConfig.cpp:1969 xs/src/libslic3r/PrintConfig.cpp:1976
+#: xs/src/libslic3r/PrintConfig.cpp:1983 xs/src/libslic3r/PrintConfig.cpp:2015
+#: xs/src/libslic3r/PrintConfig.cpp:2025 xs/src/libslic3r/PrintConfig.cpp:2035
 msgid "mm"
 msgstr "мм"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:66
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:431
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:66 xs/src/libslic3r/PrintConfig.cpp:528
 msgid "Diameter"
 msgstr "Діаметр"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:67
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:67
 msgid ""
 "Diameter of the print bed. It is assumed that origin (0,0) is located in the "
 "center."
@@ -92,333 +89,830 @@ msgstr ""
 "Діаметр подложки. Передбачається, що початок координат (0,0) знаходиться в "
 "центрі."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:71
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:150
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:92
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:71
+#: xs/src/libslic3r/GCode/PreviewData.cpp:175
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:102
 msgid "Custom"
 msgstr "Користувацький"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:75
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:75
 msgid "Load shape from STL..."
 msgstr "Завантажте форму з STL ..."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:120
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:120
 msgid "Settings"
 msgstr "Налаштування"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:298
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:299
 msgid "Choose a file to import bed shape from (STL/OBJ/AMF/3MF/PRUSA):"
 msgstr "Виберіть файл, щоб імпортувати форму полотна з (STL/OBJ/AMF/PRUSA):"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:315
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:316
 msgid "Error! "
 msgstr "Помилка! "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:324
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:325
 msgid "The selected file contains no geometry."
 msgstr "Обраний файл не містить геометрії."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.cpp:328
+#: xs/src/slic3r/GUI/BedShapeDialog.cpp:329
 msgid ""
 "The selected file contains several disjoint areas. This is not supported."
 msgstr "Обраний файл містить декілька непересічних областей. Не підтримується."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\BedShapeDialog.hpp:42
+#: xs/src/slic3r/GUI/BedShapeDialog.hpp:44
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:409
 msgid "Bed Shape"
 msgstr "Форма полотна"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:224
+#: xs/src/slic3r/GUI/BonjourDialog.cpp:53
+msgid "Network lookup"
+msgstr ""
+
+#: xs/src/slic3r/GUI/BonjourDialog.cpp:66
+msgid "Address"
+msgstr ""
+
+#: xs/src/slic3r/GUI/BonjourDialog.cpp:67
+msgid "Hostname"
+msgstr ""
+
+#: xs/src/slic3r/GUI/BonjourDialog.cpp:68
+msgid "Service name"
+msgstr ""
+
+#: xs/src/slic3r/GUI/BonjourDialog.cpp:69
+msgid "OctoPrint version"
+msgstr ""
+
+#: xs/src/slic3r/GUI/BonjourDialog.cpp:187
+msgid "Searching for devices"
+msgstr ""
+
+#: xs/src/slic3r/GUI/BonjourDialog.cpp:194
+msgid "Finished"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ButtonsDescription.cpp:13
+msgid "Buttons And Text Colors Description"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ButtonsDescription.cpp:38
+msgid "Value is the same as the system value"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ButtonsDescription.cpp:55
+msgid ""
+"Value was changed and is not equal to the system value or the last saved "
+"preset"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:15
+msgid "Upgrade"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:17
+msgid "Downgrade"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:19
+msgid "Before roll back"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:21
+msgid "User"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:24
+msgid "Unknown"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:36
+msgid "Active: "
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:42
+msgid "slic3r version"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:43
+msgid "print"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:44
+msgid "filaments"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:45
+msgid "printer"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:49 xs/src/slic3r/GUI/Tab.cpp:730
+msgid "vendor"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:49
+msgid "version"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:50
+msgid "min slic3r version"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:52
+msgid "max slic3r version"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:55
+msgid "model"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:55
+msgid "variants"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:67
+msgid "Incompatible with this Slic3r"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:70
+msgid "Activate"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigSnapshotDialog.cpp:96 xs/src/slic3r/GUI/GUI.cpp:349
+msgid "Configuration Snapshots"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:88
+msgid "nozzle"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:89
+msgid "(default)"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:108
+msgid "Select all"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:109
+msgid "Select none"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:218
+#, c-format
+msgid "Welcome to the Slic3r %s"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:218
+msgid "Welcome"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:224 xs/src/slic3r/GUI/GUI.cpp:346
+#, c-format
+msgid "Run %s"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:226
+#, c-format
+msgid ""
+"Hello, welcome to Slic3r Prusa Edition! This %s helps you with the initial "
+"configuration; just a few settings and you will be ready to print."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:230
+msgid ""
+"Remove user profiles - install from scratch (a snapshot will be taken "
+"beforehand)"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:252
+msgid "Other vendors"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:254
+msgid "Custom setup"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:278
+msgid "Automatic updates"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:278
+msgid "Updates"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:286 xs/src/slic3r/GUI/Preferences.cpp:59
+msgid "Check for application updates"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:289 xs/src/slic3r/GUI/Preferences.cpp:61
+msgid ""
+"If enabled, Slic3r checks for new versions of Slic3r PE online. When a new "
+"version becomes available a notification is displayed at the next "
+"application startup (never during program usage). This is only a "
+"notification mechanisms, no automatic installation is done."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:293 xs/src/slic3r/GUI/Preferences.cpp:67
+msgid "Update built-in Presets automatically"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:296 xs/src/slic3r/GUI/Preferences.cpp:69
+msgid ""
+"If enabled, Slic3r downloads updates of built-in system presets in the "
+"background. These updates are downloaded into a separate temporary location. "
+"When a new preset version becomes available it is offered at application "
+"startup."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:297
+msgid ""
+"Updates are never applied without user's consent and never overwrite user's "
+"customized settings."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:302
+msgid ""
+"Additionally a backup snapshot of the whole configuration is created before "
+"an update is applied."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:309
+msgid "Other Vendors"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:311
+msgid "Pick another vendor supported by Slic3r PE:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:370
+msgid "Firmware Type"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:370 xs/src/slic3r/GUI/Tab.cpp:1606
+msgid "Firmware"
+msgstr "Прошивка"
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:374
+msgid "Choose the type of firmware used by your printer."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:409
+msgid "Bed Shape and Size"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:412
+msgid "Set the shape of your printer's bed."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:426
+msgid "Filament and Nozzle Diameters"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:426
+msgid "Print Diameters"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:442
+msgid "Enter the diameter of your printer's hot end nozzle."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:445
+msgid "Nozzle Diameter:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:455
+msgid "Enter the diameter of your filament."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:456
+msgid ""
+"Good precision is required, so use a caliper and do multiple measurements "
+"along the filament, then compute the average."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:459
+msgid "Filament Diameter:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:477
+msgid "Extruder and Bed Temperatures"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:477
+msgid "Temperatures"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:493
+msgid "Enter the temperature needed for extruding your filament."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:494
+msgid "A rule of thumb is 160 to 230 °C for PLA, and 215 to 250 °C for ABS."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:497
+msgid "Extrusion Temperature:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:498
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:512
+msgid "°C"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:507
+msgid ""
+"Enter the bed temperature needed for getting your filament to stick to your "
+"heated bed."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:508
+msgid ""
+"A rule of thumb is 60 °C for PLA and 110 °C for ABS. Leave zero if you have "
+"no heated bed."
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:511
+msgid "Bed Temperature:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:824
+msgid "< &Back"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:825
+msgid "&Next >"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:826
+msgid "&Finish"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:896
+msgid "Configuration Wizard"
+msgstr ""
+
+#: xs/src/slic3r/GUI/ConfigWizard.cpp:898
+msgid "Configuration Assistant"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:87
+msgid "Flash!"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:88
+msgid "Cancel"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:128
+msgid "Flashing in progress. Please do not disconnect the printer!"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:155
+msgid "Flashing succeeded!"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:156
+msgid "Flashing failed. Please see the avrdude log below."
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:157
+msgid "Flashing cancelled."
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:294
+msgid "Cancelling..."
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:347
+msgid "Firmware flasher"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:367
+msgid "Serial port:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:369
+msgid "Rescan"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:374
+msgid "Firmware image:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:377
+msgid "Status:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:378
+msgid "Ready"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:381
+msgid "Progress:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:400
+msgid "Advanced: avrdude output log"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:446
+msgid ""
+"Are you sure you want to cancel firmware flashing?\n"
+"This could leave your printer in an unusable state!"
+msgstr ""
+
+#: xs/src/slic3r/GUI/FirmwareDialog.cpp:447
+msgid "Confirmation"
+msgstr ""
+
+#: xs/src/slic3r/GUI/GLCanvas3D.cpp:2308
+msgid "Detected object outside print volume"
+msgstr ""
+
+#: xs/src/slic3r/GUI/GUI.cpp:233
 msgid "Array of language names and identifiers should have the same size."
 msgstr "Масив імен мов та їх ідентифікаторів має бути однакового розміру."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:235
+#: xs/src/slic3r/GUI/GUI.cpp:244
 msgid "Select the language"
 msgstr "Оберіть мову"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:235
+#: xs/src/slic3r/GUI/GUI.cpp:244
 msgid "Language"
 msgstr "Мова"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:300
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:170
+#: xs/src/slic3r/GUI/GUI.cpp:306 xs/src/libslic3r/PrintConfig.cpp:195
 msgid "Default"
 msgstr "За замовчуванням"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:325
+#: xs/src/slic3r/GUI/GUI.cpp:349
+msgid "Inspect / activate configuration snapshots"
+msgstr ""
+
+#: xs/src/slic3r/GUI/GUI.cpp:350
+msgid "Take Configuration Snapshot"
+msgstr ""
+
+#: xs/src/slic3r/GUI/GUI.cpp:350
+msgid "Capture a configuration snapshot"
+msgstr ""
+
+#: xs/src/slic3r/GUI/GUI.cpp:353 xs/src/slic3r/GUI/Preferences.cpp:9
+msgid "Preferences"
+msgstr "Налаштування"
+
+#: xs/src/slic3r/GUI/GUI.cpp:353
+msgid "Application preferences"
+msgstr "Преференції застосування"
+
+#: xs/src/slic3r/GUI/GUI.cpp:354
 msgid "Change Application Language"
 msgstr "Змінити мову застосування"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:332
+#: xs/src/slic3r/GUI/GUI.cpp:356
+msgid "Flash printer firmware"
+msgstr ""
+
+#: xs/src/slic3r/GUI/GUI.cpp:356
+msgid "Upload a firmware image into an Arduino based printer"
+msgstr ""
+
+#: xs/src/slic3r/GUI/GUI.cpp:368
+msgid "Taking configuration snapshot"
+msgstr ""
+
+#: xs/src/slic3r/GUI/GUI.cpp:368
+msgid "Snapshot name"
+msgstr ""
+
+#: xs/src/slic3r/GUI/GUI.cpp:406
 msgid "Application will be restarted"
 msgstr "Застосування буде перезапущене"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:332
+#: xs/src/slic3r/GUI/GUI.cpp:406
 msgid "Attention!"
 msgstr "Увага!"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:339
-msgid "&Localization"
-msgstr "Локалізація"
+#: xs/src/slic3r/GUI/GUI.cpp:422
+msgid "&Configuration"
+msgstr ""
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:488
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:470
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1300
-msgid "Error"
-msgstr "Помилка"
+#: xs/src/slic3r/GUI/GUI.cpp:446
+msgid "You have unsaved changes "
+msgstr "У вас є незбережені зміни "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:493
+#: xs/src/slic3r/GUI/GUI.cpp:446
+msgid ". Discard changes and continue anyway?"
+msgstr ". Відхилити зміни і продовжити в будь-якому випадку?"
+
+#: xs/src/slic3r/GUI/GUI.cpp:447
+msgid "Unsaved Presets"
+msgstr "Незбереженні налаштування"
+
+#: xs/src/slic3r/GUI/GUI.cpp:655
 msgid "Notice"
 msgstr "Зауваження"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:498
-msgid "GLUquadricObjPtr | Attempt to free unreferenced scalar"
+#: xs/src/slic3r/GUI/GUI.cpp:660
+msgid "Attempt to free unreferenced scalar"
 msgstr ""
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\GUI.cpp:500
+#: xs/src/slic3r/GUI/GUI.cpp:662 xs/src/slic3r/GUI/WipeTowerDialog.cpp:39
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:321
 msgid "Warning"
 msgstr "Застереження"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:50
-msgid "Save current "
-msgstr "Зберегти поточний "
+#: xs/src/slic3r/GUI/GUI.cpp:859
+msgid "Support"
+msgstr ""
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:51
-msgid "Delete this preset"
-msgstr "Видалити це налаштування"
+#: xs/src/slic3r/GUI/GUI.cpp:862
+msgid "Select what kind of support do you need"
+msgstr ""
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:313
-msgid "Layers and perimeters"
-msgstr "Шари та периметри"
+#: xs/src/slic3r/GUI/GUI.cpp:863 xs/src/libslic3r/GCode/PreviewData.cpp:162
+msgid "None"
+msgstr "Жодне"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:314
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:777
-msgid "Layer height"
-msgstr "Висота шару"
+#: xs/src/slic3r/GUI/GUI.cpp:864 xs/src/libslic3r/PrintConfig.cpp:1656
+msgid "Support on build plate only"
+msgstr "Підтримка тільки на збірній пластині"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:318
-msgid "Vertical shells"
-msgstr "Вертикальні оболонки"
+#: xs/src/slic3r/GUI/GUI.cpp:865
+msgid "Everywhere"
+msgstr ""
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:329
-msgid "Horizontal shells"
-msgstr "Горизонтальні оболонки"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:330
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1314
-msgid "Solid layers"
-msgstr "Суцільні шари"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:335
-msgid "Quality (slower slicing)"
-msgstr "Якість (повільне нарізання)"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:342
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:356
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:449
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:452
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:831
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1113
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:107
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:208
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:736
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1733
-msgid "Advanced"
-msgstr "Розширений"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:346
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:347
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:664
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:87
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:247
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:488
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:502
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:540
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:681
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:691
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:709
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:727
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:746
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1263
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1280
-msgid "Infill"
-msgstr "Заповнення"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:352
-msgid "Reducing printing time"
-msgstr "Зниження часу друку"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:364
-msgid "Skirt and brim"
-msgstr "Плінтус та край"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:365
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:146
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:88
-msgid "Skirt"
-msgstr "Плінтус"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:371
+#: xs/src/slic3r/GUI/GUI.cpp:877 xs/src/slic3r/GUI/Tab.cpp:844
 msgid "Brim"
 msgstr "Край"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:374
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:375
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:191
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1030
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1380
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1387
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1399
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1409
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1417
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1432
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1453
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1464
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1480
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1489
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1498
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1509
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1525
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1533
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1534
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1543
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1551
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1565
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:147
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:89
+#: xs/src/slic3r/GUI/GUI.cpp:879
+msgid ""
+"This flag enables the brim that will be printed around each object on the "
+"first layer."
+msgstr ""
+
+#: xs/src/slic3r/GUI/GUI.cpp:888
+msgid "Purging volumes"
+msgstr ""
+
+#: xs/src/slic3r/GUI/GUI.cpp:930
+msgid "Export print config"
+msgstr ""
+
+#: xs/src/slic3r/GUI/MsgDialog.cpp:64
+msgid "Slic3r error"
+msgstr ""
+
+#: xs/src/slic3r/GUI/MsgDialog.cpp:64
+msgid "Slic3r has encountered an error"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:84
+msgid "Save current "
+msgstr "Зберегти поточний "
+
+#: xs/src/slic3r/GUI/Tab.cpp:85
+msgid "Delete this preset"
+msgstr "Видалити це налаштування"
+
+#: xs/src/slic3r/GUI/Tab.cpp:97
+msgid ""
+"Hover the cursor over buttons to find more information \n"
+"or click this button."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:716
+msgid "It's a default preset."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:717
+msgid "It's a system preset."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:718
+msgid "Current preset is inherited from "
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:723
+msgid "It can't be deleted or modified. "
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:724
+msgid ""
+"Any modifications should be saved as a new preset inherited from this one. "
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:725
+msgid "To do that please specify a new name for the preset."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:729
+msgid "Additional information:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:737
+msgid "printer model"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:739
+msgid "default print profile"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:742
+msgid "default filament profile"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:786
+msgid "Layers and perimeters"
+msgstr "Шари та периметри"
+
+#: xs/src/slic3r/GUI/Tab.cpp:787 xs/src/libslic3r/PrintConfig.cpp:886
+msgid "Layer height"
+msgstr "Висота шару"
+
+#: xs/src/slic3r/GUI/Tab.cpp:791
+msgid "Vertical shells"
+msgstr "Вертикальні оболонки"
+
+#: xs/src/slic3r/GUI/Tab.cpp:802
+msgid "Horizontal shells"
+msgstr "Горизонтальні оболонки"
+
+#: xs/src/slic3r/GUI/Tab.cpp:803 xs/src/libslic3r/PrintConfig.cpp:1562
+msgid "Solid layers"
+msgstr "Суцільні шари"
+
+#: xs/src/slic3r/GUI/Tab.cpp:808
+msgid "Quality (slower slicing)"
+msgstr "Якість (повільне нарізання)"
+
+#: xs/src/slic3r/GUI/Tab.cpp:815 xs/src/slic3r/GUI/Tab.cpp:829
+#: xs/src/slic3r/GUI/Tab.cpp:923 xs/src/slic3r/GUI/Tab.cpp:926
+#: xs/src/slic3r/GUI/Tab.cpp:1276 xs/src/slic3r/GUI/Tab.cpp:1625
+#: xs/src/libslic3r/PrintConfig.cpp:110 xs/src/libslic3r/PrintConfig.cpp:245
+#: xs/src/libslic3r/PrintConfig.cpp:833 xs/src/libslic3r/PrintConfig.cpp:2021
+msgid "Advanced"
+msgstr "Розширений"
+
+#: xs/src/slic3r/GUI/Tab.cpp:819 xs/src/slic3r/GUI/Tab.cpp:820
+#: xs/src/slic3r/GUI/Tab.cpp:1127 xs/src/libslic3r/PrintConfig.cpp:90
+#: xs/src/libslic3r/PrintConfig.cpp:284 xs/src/libslic3r/PrintConfig.cpp:585
+#: xs/src/libslic3r/PrintConfig.cpp:599 xs/src/libslic3r/PrintConfig.cpp:637
+#: xs/src/libslic3r/PrintConfig.cpp:778 xs/src/libslic3r/PrintConfig.cpp:788
+#: xs/src/libslic3r/PrintConfig.cpp:806 xs/src/libslic3r/PrintConfig.cpp:824
+#: xs/src/libslic3r/PrintConfig.cpp:843 xs/src/libslic3r/PrintConfig.cpp:1511
+#: xs/src/libslic3r/PrintConfig.cpp:1528
+msgid "Infill"
+msgstr "Заповнення"
+
+#: xs/src/slic3r/GUI/Tab.cpp:825
+msgid "Reducing printing time"
+msgstr "Зниження часу друку"
+
+#: xs/src/slic3r/GUI/Tab.cpp:837
+msgid "Skirt and brim"
+msgstr "Плінтус та край"
+
+#: xs/src/slic3r/GUI/Tab.cpp:838 xs/src/libslic3r/GCode/PreviewData.cpp:171
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:98
+msgid "Skirt"
+msgstr "Плінтус"
+
+#: xs/src/slic3r/GUI/Tab.cpp:847 xs/src/slic3r/GUI/Tab.cpp:848
+#: xs/src/libslic3r/PrintConfig.cpp:228 xs/src/libslic3r/PrintConfig.cpp:1278
+#: xs/src/libslic3r/PrintConfig.cpp:1628 xs/src/libslic3r/PrintConfig.cpp:1635
+#: xs/src/libslic3r/PrintConfig.cpp:1647 xs/src/libslic3r/PrintConfig.cpp:1657
+#: xs/src/libslic3r/PrintConfig.cpp:1665 xs/src/libslic3r/PrintConfig.cpp:1680
+#: xs/src/libslic3r/PrintConfig.cpp:1701 xs/src/libslic3r/PrintConfig.cpp:1712
+#: xs/src/libslic3r/PrintConfig.cpp:1728 xs/src/libslic3r/PrintConfig.cpp:1737
+#: xs/src/libslic3r/PrintConfig.cpp:1746 xs/src/libslic3r/PrintConfig.cpp:1757
+#: xs/src/libslic3r/PrintConfig.cpp:1771 xs/src/libslic3r/PrintConfig.cpp:1779
+#: xs/src/libslic3r/PrintConfig.cpp:1780 xs/src/libslic3r/PrintConfig.cpp:1789
+#: xs/src/libslic3r/PrintConfig.cpp:1797 xs/src/libslic3r/PrintConfig.cpp:1811
+#: xs/src/libslic3r/GCode/PreviewData.cpp:172
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:99
 msgid "Support material"
 msgstr "Підтримка"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:380
+#: xs/src/slic3r/GUI/Tab.cpp:853
 msgid "Raft"
 msgstr "Пліт"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:384
+#: xs/src/slic3r/GUI/Tab.cpp:857
 msgid "Options for support material and raft"
 msgstr "Варіанти для опорного матеріалу та плоту"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:398
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:118
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:278
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:635
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:747
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:979
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1201
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1251
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1302
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1625
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:71
+#: xs/src/slic3r/GUI/Tab.cpp:871 xs/src/libslic3r/PrintConfig.cpp:122
+#: xs/src/libslic3r/PrintConfig.cpp:315 xs/src/libslic3r/PrintConfig.cpp:732
+#: xs/src/libslic3r/PrintConfig.cpp:844 xs/src/libslic3r/PrintConfig.cpp:1212
+#: xs/src/libslic3r/PrintConfig.cpp:1449 xs/src/libslic3r/PrintConfig.cpp:1499
+#: xs/src/libslic3r/PrintConfig.cpp:1550 xs/src/libslic3r/PrintConfig.cpp:1871
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:77
 msgid "Speed"
 msgstr "Швидкість"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:399
+#: xs/src/slic3r/GUI/Tab.cpp:872
 msgid "Speed for print moves"
 msgstr "Швидкість друкарських рухів"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:411
+#: xs/src/slic3r/GUI/Tab.cpp:884
 msgid "Speed for non-print moves"
 msgstr "Швидкість недрукарських рухів"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:414
+#: xs/src/slic3r/GUI/Tab.cpp:887
 msgid "Modifiers"
 msgstr "Модифікатори"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:417
+#: xs/src/slic3r/GUI/Tab.cpp:890
 msgid "Acceleration control (advanced)"
 msgstr "Контроль прискорення (розширений)"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:424
+#: xs/src/slic3r/GUI/Tab.cpp:897
 msgid "Autospeed (advanced)"
 msgstr "Автоматична швидкість (розширена)"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:430
+#: xs/src/slic3r/GUI/Tab.cpp:903
 msgid "Multiple Extruders"
 msgstr "Кілька екструдерів"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:431
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:966
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:308
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:702
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:958
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1272
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1445
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1471
+#: xs/src/slic3r/GUI/Tab.cpp:904 xs/src/slic3r/GUI/Tab.cpp:1451
+#: xs/src/libslic3r/PrintConfig.cpp:345 xs/src/libslic3r/PrintConfig.cpp:799
+#: xs/src/libslic3r/PrintConfig.cpp:1191 xs/src/libslic3r/PrintConfig.cpp:1520
+#: xs/src/libslic3r/PrintConfig.cpp:1693 xs/src/libslic3r/PrintConfig.cpp:1719
+#: xs/src/libslic3r/PrintConfig.cpp:1995 xs/src/libslic3r/PrintConfig.cpp:2004
 msgid "Extruders"
 msgstr "Екструдери"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:438
+#: xs/src/slic3r/GUI/Tab.cpp:911
 msgid "Ooze prevention"
 msgstr "Профілактика просочування"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:442
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:149
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:91
+#: xs/src/slic3r/GUI/Tab.cpp:915 xs/src/libslic3r/GCode/PreviewData.cpp:174
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:101
 msgid "Wipe tower"
 msgstr "Вежа вичищування"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:453
+#: xs/src/slic3r/GUI/Tab.cpp:927
 msgid "Extrusion width"
 msgstr "Ширина екструзії"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:463
+#: xs/src/slic3r/GUI/Tab.cpp:937
 msgid "Overlap"
 msgstr "Перекриття"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:466
+#: xs/src/slic3r/GUI/Tab.cpp:940
 msgid "Flow"
 msgstr "Потік"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:469
+#: xs/src/slic3r/GUI/Tab.cpp:943
 msgid "Other"
 msgstr "Інше"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:476
+#: xs/src/slic3r/GUI/Tab.cpp:950
 msgid "Output options"
 msgstr "Параметри виводу"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:477
+#: xs/src/slic3r/GUI/Tab.cpp:951
 msgid "Sequential printing"
 msgstr "Послідовне друкування"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:479
+#: xs/src/slic3r/GUI/Tab.cpp:953
 msgid "Extruder clearance (mm)"
 msgstr "Розмір екструдера (мм)"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:488
+#: xs/src/slic3r/GUI/Tab.cpp:962
 msgid "Output file"
 msgstr "Вихідний файл"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:494
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1001
+#: xs/src/slic3r/GUI/Tab.cpp:968 xs/src/libslic3r/PrintConfig.cpp:1234
 msgid "Post-processing scripts"
 msgstr "Скрипти пост-обробки"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:500
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:501
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:859
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:860
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1156
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1157
+#: xs/src/slic3r/GUI/Tab.cpp:974 xs/src/slic3r/GUI/Tab.cpp:975
+#: xs/src/slic3r/GUI/Tab.cpp:1329 xs/src/slic3r/GUI/Tab.cpp:1330
+#: xs/src/slic3r/GUI/Tab.cpp:1668 xs/src/slic3r/GUI/Tab.cpp:1669
 msgid "Notes"
 msgstr "Примітки"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:507
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:867
+#: xs/src/slic3r/GUI/Tab.cpp:981 xs/src/slic3r/GUI/Tab.cpp:1337
+#: xs/src/slic3r/GUI/Tab.cpp:1675
 msgid "Dependencies"
 msgstr "Залежності"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:508
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:868
+#: xs/src/slic3r/GUI/Tab.cpp:982 xs/src/slic3r/GUI/Tab.cpp:1338
+#: xs/src/slic3r/GUI/Tab.cpp:1676
 msgid "Profile dependencies"
 msgstr "Залежності профілю"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:509
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:869
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1668
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:143
+#: xs/src/slic3r/GUI/Tab.cpp:983 xs/src/slic3r/GUI/Tab.cpp:1339
+#: xs/src/slic3r/GUI/Tab.cpp:2364 xs/src/libslic3r/PrintConfig.cpp:147
 msgid "Compatible printers"
 msgstr "Сумісні принтери"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:533
+#: xs/src/slic3r/GUI/Tab.cpp:1016
 #, no-c-format
 msgid ""
 "The Spiral Vase mode requires:\n"
@@ -439,31 +933,11 @@ msgstr ""
 "\n"
 "Чи потрібно змінити ці налаштування, щоб увімкнути режим Спіральної вази?"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:540
+#: xs/src/slic3r/GUI/Tab.cpp:1023
 msgid "Spiral Vase"
 msgstr "Спіральна ваза"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:560
-msgid ""
-"The Wipe Tower currently supports only:\n"
-"- first layer height 0.2mm\n"
-"- layer height from 0.15mm to 0.35mm\n"
-"\n"
-"Shall I adjust those settings in order to enable the Wipe Tower?"
-msgstr ""
-"Вичіщуюча веж в даний час підтримує тільки:\n"
-"- висота першого шару 0,2 мм\n"
-"- висота шару від 0,15 мм до 0,35 мм\n"
-"\n"
-"Чи потрібно коригувати ці налаштування, щоб увімкнути вичіщуючу веж?"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:564
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:585
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:602
-msgid "Wipe Tower"
-msgstr "Вичіщуюча веж"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:581
+#: xs/src/slic3r/GUI/Tab.cpp:1044
 msgid ""
 "The Wipe Tower currently supports the non-soluble supports only\n"
 "if they are printed with the current extruder without triggering a tool "
@@ -481,7 +955,11 @@ msgstr ""
 "\n"
 "Чи потрібно коригувати ці налаштування, щоб увімкнути вичіщуючу веж?"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:599
+#: xs/src/slic3r/GUI/Tab.cpp:1048 xs/src/slic3r/GUI/Tab.cpp:1065
+msgid "Wipe Tower"
+msgstr "Вичіщуюча веж"
+
+#: xs/src/slic3r/GUI/Tab.cpp:1062
 msgid ""
 "For the Wipe Tower to work with the soluble supports, the support layers\n"
 "need to be synchronized with the object layers.\n"
@@ -494,7 +972,7 @@ msgstr ""
 "\n"
 "Чи потрібно синхронізувати шари підтримки, щоб увімкнути вичіщуючу веж?"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:617
+#: xs/src/slic3r/GUI/Tab.cpp:1080
 msgid ""
 "Supports work better, if the following feature is enabled:\n"
 "- Detect bridging perimeters\n"
@@ -506,15 +984,15 @@ msgstr ""
 "\n"
 "Чи потрібно змінити ці налаштування для підтримки?"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:620
+#: xs/src/slic3r/GUI/Tab.cpp:1083
 msgid "Support Generator"
 msgstr "Створення підтримки"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:662
+#: xs/src/slic3r/GUI/Tab.cpp:1125
 msgid "The "
 msgstr "Шаблон наповнення "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:662
+#: xs/src/slic3r/GUI/Tab.cpp:1125
 #, no-c-format
 msgid ""
 " infill pattern is not supposed to work at 100% density.\n"
@@ -525,186 +1003,251 @@ msgstr ""
 "\n"
 "Чи потрібно змінити його на Rectilinear шаблон заповнення?"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:786
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:787
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:368
+#: xs/src/slic3r/GUI/Tab.cpp:1231 xs/src/slic3r/GUI/Tab.cpp:1232
+#: lib/Slic3r/GUI/Plater.pm:454
 msgid "Filament"
 msgstr "Філамент"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:794
+#: xs/src/slic3r/GUI/Tab.cpp:1239
 msgid "Temperature "
 msgstr "Температура "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:795
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1234
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:307
+#: xs/src/slic3r/GUI/Tab.cpp:1240 xs/src/libslic3r/PrintConfig.cpp:344
 msgid "Extruder"
 msgstr "Екструдер"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:800
+#: xs/src/slic3r/GUI/Tab.cpp:1245
 msgid "Bed"
 msgstr "Полотно"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:805
+#: xs/src/slic3r/GUI/Tab.cpp:1250
 msgid "Cooling"
 msgstr "Охолодження"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:806
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:922
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1695
+#: xs/src/slic3r/GUI/Tab.cpp:1251 xs/src/libslic3r/PrintConfig.cpp:1137
+#: xs/src/libslic3r/PrintConfig.cpp:1941
 msgid "Enable"
 msgstr "Увімкнути"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:817
+#: xs/src/slic3r/GUI/Tab.cpp:1262
 msgid "Fan settings"
 msgstr "Налаштування вентилятора"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:818
+#: xs/src/slic3r/GUI/Tab.cpp:1263
 msgid "Fan speed"
 msgstr "Швидкість вентилятора"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:826
+#: xs/src/slic3r/GUI/Tab.cpp:1271
 msgid "Cooling thresholds"
 msgstr "Пороги охолодження"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:832
+#: xs/src/slic3r/GUI/Tab.cpp:1277
 msgid "Filament properties"
 msgstr "Властивості філаменту"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:836
+#: xs/src/slic3r/GUI/Tab.cpp:1281
 msgid "Print speed override"
 msgstr "Перевизначення швидкості друку"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:846
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1119
+#: xs/src/slic3r/GUI/Tab.cpp:1291
+msgid "Toolchange parameters with single extruder MM printers"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1299
+msgid "Ramming"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1301
+msgid "Ramming settings"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1316 xs/src/slic3r/GUI/Tab.cpp:1631
 msgid "Custom G-code"
 msgstr "Користувацький G-код"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:847
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1120
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1342
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1357
+#: xs/src/slic3r/GUI/Tab.cpp:1317 xs/src/slic3r/GUI/Tab.cpp:1632
+#: xs/src/libslic3r/PrintConfig.cpp:1590 xs/src/libslic3r/PrintConfig.cpp:1605
 msgid "Start G-code"
 msgstr "Початок G-коду"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:853
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1126
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:217
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:227
+#: xs/src/slic3r/GUI/Tab.cpp:1323 xs/src/slic3r/GUI/Tab.cpp:1638
+#: xs/src/libslic3r/PrintConfig.cpp:254 xs/src/libslic3r/PrintConfig.cpp:264
 msgid "End G-code"
 msgstr "Закінчення G-коду"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:937
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:11
+#: xs/src/slic3r/GUI/Tab.cpp:1419 xs/src/slic3r/GUI/Preferences.cpp:17
 msgid "General"
 msgstr "Загальне"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:938
+#: xs/src/slic3r/GUI/Tab.cpp:1420
 msgid "Size and coordinates"
 msgstr "Розмір і координати"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:940
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:34
+#: xs/src/slic3r/GUI/Tab.cpp:1422 xs/src/libslic3r/PrintConfig.cpp:37
 msgid "Bed shape"
 msgstr "Форма полотна"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:942
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1637
+#: xs/src/slic3r/GUI/Tab.cpp:1424 xs/src/slic3r/GUI/Tab.cpp:2332
 msgid " Set "
 msgstr " Встановити "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:962
+#: xs/src/slic3r/GUI/Tab.cpp:1447
 msgid "Capabilities"
 msgstr "Можливості"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:967
+#: xs/src/slic3r/GUI/Tab.cpp:1452
 msgid "Number of extruders of the printer."
 msgstr "Кількість екструдерів у принтері."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:989
+#: xs/src/slic3r/GUI/Tab.cpp:1477
 msgid "USB/Serial connection"
 msgstr "USB/послідовне з'єднання"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:990
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1193
+#: xs/src/slic3r/GUI/Tab.cpp:1478 xs/src/libslic3r/PrintConfig.cpp:1441
 msgid "Serial port"
 msgstr "Послідовний порт"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:995
+#: xs/src/slic3r/GUI/Tab.cpp:1483
 msgid "Rescan serial ports"
 msgstr "Сканувати ще раз послідовні порти"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1004
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1072
+#: xs/src/slic3r/GUI/Tab.cpp:1492 xs/src/slic3r/GUI/Tab.cpp:1539
 msgid "Test"
 msgstr "Перевірити"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1017
+#: xs/src/slic3r/GUI/Tab.cpp:1505
 msgid "Connection to printer works correctly."
 msgstr "Підключення до принтера працює коректно."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1017
+#: xs/src/slic3r/GUI/Tab.cpp:1505 xs/src/slic3r/GUI/Tab.cpp:1549
 msgid "Success!"
 msgstr "Успіх!"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1020
+#: xs/src/slic3r/GUI/Tab.cpp:1508
 msgid "Connection failed."
 msgstr "Підключення не вдалося."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1032
+#: xs/src/slic3r/GUI/Tab.cpp:1520 xs/src/slic3r/Utils/OctoPrint.cpp:110
 msgid "OctoPrint upload"
 msgstr "Завантаження OctoPrint"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1035
+#: xs/src/slic3r/GUI/Tab.cpp:1523 xs/src/slic3r/GUI/Tab.cpp:1572
 msgid " Browse "
 msgstr " Переглянути "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1110
-msgid "Firmware"
-msgstr "Прошивка"
+#: xs/src/slic3r/GUI/Tab.cpp:1549
+msgid "Connection to OctoPrint works correctly."
+msgstr "Підключення до OctoPrint працює правильно."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1132
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:48
+#: xs/src/slic3r/GUI/Tab.cpp:1552
+msgid "Could not connect to OctoPrint"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1552
+msgid "Note: OctoPrint version at least 1.1.0 is required."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1578
+msgid "Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1579
+msgid "Open CA certificate file"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1593
+msgid ""
+"HTTPS CA file is optional. It is only needed if you use HTTPS with a self-"
+"signed certificate."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1644 xs/src/libslic3r/PrintConfig.cpp:51
 msgid "Before layer change G-code"
 msgstr "G-код перед зміною шару"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1138
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:766
+#: xs/src/slic3r/GUI/Tab.cpp:1650 xs/src/libslic3r/PrintConfig.cpp:875
 msgid "After layer change G-code"
 msgstr "G-код після зміни шару"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1144
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1602
+#: xs/src/slic3r/GUI/Tab.cpp:1656 xs/src/libslic3r/PrintConfig.cpp:1848
 msgid "Tool change G-code"
 msgstr "G-код зміни інструменту"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1150
+#: xs/src/slic3r/GUI/Tab.cpp:1662
 msgid "Between objects G-code (for sequential printing)"
 msgstr "G-код між об'єктами (для послідовного друку)"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1187
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:400
+#: xs/src/slic3r/GUI/Tab.cpp:1717 xs/src/slic3r/GUI/Tab.cpp:1778
+#: xs/src/slic3r/GUI/Tab.cpp:2037 xs/src/libslic3r/PrintConfig.cpp:920
+#: xs/src/libslic3r/PrintConfig.cpp:929 xs/src/libslic3r/PrintConfig.cpp:938
+#: xs/src/libslic3r/PrintConfig.cpp:950 xs/src/libslic3r/PrintConfig.cpp:960
+#: xs/src/libslic3r/PrintConfig.cpp:970 xs/src/libslic3r/PrintConfig.cpp:980
+msgid "Machine limits"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1730
+msgid "Values in this column are for Full Power mode"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1731
+msgid "Full Power"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1736
+msgid "Values in this column are for Silent mode"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1737
+msgid "Silent"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1745
+msgid "Maximum feedrates"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1750
+msgid "Maximum accelerations"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1757
+msgid "Jerk limits"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1762
+msgid "Minimum feedrates"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1800 xs/src/slic3r/GUI/Tab.cpp:1808
+#: xs/src/slic3r/GUI/Tab.cpp:2037
+msgid "Single extruder MM setup"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1809
+msgid "Single extruder multimaterial parameters"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:1822 xs/src/libslic3r/GCode/PreviewData.cpp:446
 #, c-format
 msgid "Extruder %d"
 msgstr "Екструдер %d"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1194
+#: xs/src/slic3r/GUI/Tab.cpp:1829
 msgid "Layer height limits"
 msgstr "Межі висоти шару"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1199
+#: xs/src/slic3r/GUI/Tab.cpp:1834
 msgid "Position (for multi-extruder printers)"
 msgstr "Позиція (для мульти-екструдерних принтерів)"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1202
+#: xs/src/slic3r/GUI/Tab.cpp:1837
 msgid "Retraction"
 msgstr "Переривання"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1205
+#: xs/src/slic3r/GUI/Tab.cpp:1840
 msgid "Only lift Z"
 msgstr "Межі підняття Z"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1218
+#: xs/src/slic3r/GUI/Tab.cpp:1853
 msgid ""
 "Retraction when tool is disabled (advanced settings for multi-extruder "
 "setups)"
@@ -712,13 +1255,12 @@ msgstr ""
 "Переривання при відключенні інструмента (додаткові налаштування для "
 "налагодження мульти-екструдерів)"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1222
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:150
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2125
+#: xs/src/slic3r/GUI/Tab.cpp:1857 lib/Slic3r/GUI/Plater.pm:217
+#: lib/Slic3r/GUI/Plater.pm:2324
 msgid "Preview"
 msgstr "Попередній перегляд"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1312
+#: xs/src/slic3r/GUI/Tab.cpp:1953
 msgid ""
 "The Wipe option is not available when using the Firmware Retraction mode.\n"
 "\n"
@@ -729,23 +1271,23 @@ msgstr ""
 "\n"
 "Відключити його для увімкнення програмного переривання?"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1314
+#: xs/src/slic3r/GUI/Tab.cpp:1955
 msgid "Firmware Retraction"
 msgstr "Програмне переривання"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1469
+#: xs/src/slic3r/GUI/Tab.cpp:2130
 msgid "Default "
 msgstr "За замовчуванням "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1469
+#: xs/src/slic3r/GUI/Tab.cpp:2130
 msgid " preset"
 msgstr " налаштування"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1470
+#: xs/src/slic3r/GUI/Tab.cpp:2131
 msgid " preset\n"
 msgstr " налаштування\n"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1488
+#: xs/src/slic3r/GUI/Tab.cpp:2149
 msgid ""
 "\n"
 "\n"
@@ -755,7 +1297,7 @@ msgstr ""
 "\n"
 "є не сумісним з принтером\n"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1488
+#: xs/src/slic3r/GUI/Tab.cpp:2149
 msgid ""
 "\n"
 "\n"
@@ -765,7 +1307,7 @@ msgstr ""
 "\n"
 "і має такі незбережені зміни:"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1489
+#: xs/src/slic3r/GUI/Tab.cpp:2150
 msgid ""
 "\n"
 "\n"
@@ -775,7 +1317,7 @@ msgstr ""
 "\n"
 "має такі незбережені зміни:"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1491
+#: xs/src/slic3r/GUI/Tab.cpp:2152
 msgid ""
 "\n"
 "\n"
@@ -785,93 +1327,219 @@ msgstr ""
 "\n"
 "Відхилити зміни і продовжувати в будь-якому випадку?"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1492
+#: xs/src/slic3r/GUI/Tab.cpp:2153
 msgid "Unsaved Changes"
 msgstr "Незбережені зміни"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1560
+#: xs/src/slic3r/GUI/Tab.cpp:2240
 msgid "The supplied name is empty. It can't be saved."
 msgstr "Надане ім'я порожнє. Не вдається зберегти."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1580
+#: xs/src/slic3r/GUI/Tab.cpp:2245
+msgid "Cannot overwrite a system profile."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2249
+msgid "Cannot overwrite an external profile."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2275
 msgid "remove"
 msgstr "перемістити"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1580
+#: xs/src/slic3r/GUI/Tab.cpp:2275
 msgid "delete"
 msgstr "видалити"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1581
+#: xs/src/slic3r/GUI/Tab.cpp:2276
 msgid "Are you sure you want to "
 msgstr "Ви впевнені, що хочете "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1581
+#: xs/src/slic3r/GUI/Tab.cpp:2276
 msgid " the selected preset?"
 msgstr " вибране налаштування?"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1582
+#: xs/src/slic3r/GUI/Tab.cpp:2277
 msgid "Remove"
 msgstr "Перемістити"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1582
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:178
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:196
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2021
+#: xs/src/slic3r/GUI/Tab.cpp:2277 lib/Slic3r/GUI/Plater.pm:251
+#: lib/Slic3r/GUI/Plater.pm:269 lib/Slic3r/GUI/Plater.pm:2215
 msgid "Delete"
 msgstr "Видалити"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1583
+#: xs/src/slic3r/GUI/Tab.cpp:2278
 msgid " Preset"
 msgstr " Налаштування"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1636
+#: xs/src/slic3r/GUI/Tab.cpp:2331
 msgid "All"
 msgstr "Всі"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1667
+#: xs/src/slic3r/GUI/Tab.cpp:2363
 msgid "Select the printers this profile is compatible with."
 msgstr "Оберіть принтери, сумісні з цим профілем."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1751
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:514
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1645
+#: xs/src/slic3r/GUI/Tab.cpp:2409 xs/src/slic3r/GUI/Tab.cpp:2495
+#: xs/src/slic3r/GUI/Preset.cpp:702 xs/src/slic3r/GUI/Preset.cpp:742
+#: xs/src/slic3r/GUI/Preset.cpp:770 xs/src/slic3r/GUI/Preset.cpp:802
+#: xs/src/slic3r/GUI/PresetBundle.cpp:1193
+#: xs/src/slic3r/GUI/PresetBundle.cpp:1246 lib/Slic3r/GUI/Plater.pm:603
+msgid "System presets"
+msgstr "Системні налаштування"
+
+#: xs/src/slic3r/GUI/Tab.cpp:2410 xs/src/slic3r/GUI/Tab.cpp:2496
+msgid "Default presets"
+msgstr "Налаштування за замовчанням"
+
+#: xs/src/slic3r/GUI/Tab.cpp:2565
+msgid ""
+"LOCKED LOCK;indicates that the settings are the same as the system values "
+"for the current option group"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2568
+msgid ""
+"UNLOCKED LOCK;indicates that some settings were changed and are not equal to "
+"the system values for the current option group.\n"
+"Click the UNLOCKED LOCK icon to reset all settings for current option group "
+"to the system values."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2574
+msgid ""
+"WHITE BULLET;for the left button: \tindicates a non-system preset,\n"
+"for the right button: \tindicates that the settings hasn't been modified."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2578
+msgid ""
+"BACK ARROW;indicates that the settings were changed and are not equal to the "
+"last saved preset for the current option group.\n"
+"Click the BACK ARROW icon to reset all settings for the current option group "
+"to the last saved preset."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2604
+msgid ""
+"LOCKED LOCK icon indicates that the settings are the same as the system "
+"values for the current option group"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2606
+msgid ""
+"UNLOCKED LOCK icon indicates that some settings were changed and are not "
+"equal to the system values for the current option group.\n"
+"Click to reset all settings for current option group to the system values."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2609
+msgid "WHITE BULLET icon indicates a non system preset."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2612
+msgid ""
+"WHITE BULLET icon indicates that the settings are the same as in the last "
+"saved preset for the current option group."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2614
+msgid ""
+"BACK ARROW icon indicates that the settings were changed and are not equal "
+"to the last saved preset for the current option group.\n"
+"Click to reset all settings for the current option group to the last saved "
+"preset."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2620
+msgid ""
+"LOCKED LOCK icon indicates that the value is the same as the system value."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2621
+msgid ""
+"UNLOCKED LOCK icon indicates that the value was changed and is not equal to "
+"the system value.\n"
+"Click to reset current value to the system value."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2627
+msgid ""
+"WHITE BULLET icon indicates that the value is the same as in the last saved "
+"preset."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2628
+msgid ""
+"BACK ARROW icon indicates that the value was changed and is not equal to the "
+"last saved preset.\n"
+"Click to reset current value to the last saved preset."
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2703 lib/Slic3r/GUI/MainFrame.pm:469
+#: lib/Slic3r/GUI/Plater.pm:1795
 msgid "Save "
 msgstr "Зберегти "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1751
+#: xs/src/slic3r/GUI/Tab.cpp:2703
 msgid " as:"
 msgstr " як:"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1785
-msgid ""
-"The supplied name is not valid; the following characters are not allowed:"
-msgstr "Надане ім'я недійсне; такі символи не допускаються:"
+#: xs/src/slic3r/GUI/Tab.cpp:2742 xs/src/slic3r/GUI/Tab.cpp:2746
+msgid "The supplied name is not valid;"
+msgstr ""
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.cpp:1788
+#: xs/src/slic3r/GUI/Tab.cpp:2743
+msgid "the following characters are not allowed:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2747
+msgid "the following postfix are not allowed:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Tab.cpp:2750
 msgid "The supplied name is not available."
 msgstr "Надане ім'я недійсне."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.hpp:182
+#: xs/src/slic3r/GUI/Tab.hpp:286
 msgid "Print Settings"
 msgstr "Параметри друку"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.hpp:202
+#: xs/src/slic3r/GUI/Tab.hpp:306
 msgid "Filament Settings"
 msgstr "Параметри філаменту"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.hpp:228
+#: xs/src/slic3r/GUI/Tab.hpp:332
 msgid "Printer Settings"
 msgstr "Параметри принтеру"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Tab.hpp:248
+#: xs/src/slic3r/GUI/Tab.hpp:348
 msgid "Save preset"
 msgstr "Зберегти налаштування"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Field.cpp:42
+#: xs/src/slic3r/GUI/Field.cpp:98
 msgid "default"
 msgstr "за замовчуванням"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:26
+#: xs/src/slic3r/GUI/Field.cpp:128
+#, c-format
+msgid "%s doesn't support percentage"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Field.cpp:137
+msgid "Input value is out of range"
+msgstr ""
+
+#: xs/src/slic3r/GUI/Preset.cpp:144
+msgid "modified"
+msgstr "модифікований"
+
+#: xs/src/slic3r/GUI/Preset.cpp:746 xs/src/slic3r/GUI/Preset.cpp:806
+#: xs/src/slic3r/GUI/PresetBundle.cpp:1251 lib/Slic3r/GUI/Plater.pm:604
+msgid "User presets"
+msgstr "Налаштування користувача"
+
+#: xs/src/slic3r/GUI/PresetHints.cpp:27
 #, c-format
 msgid ""
 "If estimated layer time is below ~%ds, fan will run at %d%% and print speed "
@@ -882,7 +1550,7 @@ msgstr ""
 "%%, і швидкість друку буде зменшена, так що на цей шар витрачається не менше "
 "%dс (однак швидкість ніколи не зменшиться нижче %d mm/s) ."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:30
+#: xs/src/slic3r/GUI/PresetHints.cpp:31
 #, c-format
 msgid ""
 "\n"
@@ -893,7 +1561,7 @@ msgstr ""
 "Якщо запланований час друку шару більше, але все ще нижче ~%dс, вентилятор "
 "буде працювати з пропорційно зменшуваною швидкістю між %d%% та %d%%."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:34
+#: xs/src/slic3r/GUI/PresetHints.cpp:35
 msgid ""
 "\n"
 "During the other layers, fan "
@@ -901,95 +1569,95 @@ msgstr ""
 "\n"
 "Під час друку інших шарів вентилятор "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:36
+#: xs/src/slic3r/GUI/PresetHints.cpp:37
 msgid "Fan "
 msgstr "Вентилятор "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:41
+#: xs/src/slic3r/GUI/PresetHints.cpp:42
 #, c-format
 msgid "will always run at %d%% "
 msgstr "буде завжди працювати на %d%% "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:44
+#: xs/src/slic3r/GUI/PresetHints.cpp:45
 #, c-format
 msgid "except for the first %d layers"
 msgstr "за винятком перших %d шарів"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:48
+#: xs/src/slic3r/GUI/PresetHints.cpp:49
 msgid "except for the first layer"
 msgstr "за винятком першого шару"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:50
+#: xs/src/slic3r/GUI/PresetHints.cpp:51
 msgid "will be turned off."
 msgstr "буде вимкнено."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:151
+#: xs/src/slic3r/GUI/PresetHints.cpp:152
 msgid "external perimeters"
 msgstr "зовнішні периметри"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:160
+#: xs/src/slic3r/GUI/PresetHints.cpp:161
 msgid "perimeters"
 msgstr "периметри"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:169
+#: xs/src/slic3r/GUI/PresetHints.cpp:170
 msgid "infill"
 msgstr "наповнення"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:179
+#: xs/src/slic3r/GUI/PresetHints.cpp:180
 msgid "solid infill"
 msgstr "суцільне наповнення"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:187
+#: xs/src/slic3r/GUI/PresetHints.cpp:188
 msgid "top solid infill"
 msgstr "верхній суцільне наповнення"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:198
+#: xs/src/slic3r/GUI/PresetHints.cpp:199
 msgid "support"
 msgstr "підтримка"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:208
+#: xs/src/slic3r/GUI/PresetHints.cpp:209
 msgid "support interface"
 msgstr "інтерфейс підтримки"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:214
+#: xs/src/slic3r/GUI/PresetHints.cpp:215
 msgid "First layer volumetric"
 msgstr "Об'єм першого шару"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:214
+#: xs/src/slic3r/GUI/PresetHints.cpp:215
 msgid "Bridging volumetric"
 msgstr "Об'єм мостів"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:214
+#: xs/src/slic3r/GUI/PresetHints.cpp:215
 msgid "Volumetric"
 msgstr "Об'ємний"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:215
+#: xs/src/slic3r/GUI/PresetHints.cpp:216
 msgid " flow rate is maximized "
 msgstr " швидкість потоку максимізується "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:218
+#: xs/src/slic3r/GUI/PresetHints.cpp:219
 msgid "by the print profile maximum"
 msgstr "за профілем друку максимум"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:219
+#: xs/src/slic3r/GUI/PresetHints.cpp:220
 msgid "when printing "
 msgstr "коли друкуємо "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:220
+#: xs/src/slic3r/GUI/PresetHints.cpp:221
 msgid " with a volumetric rate "
 msgstr " з об'ємною швидкістю "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:224
+#: xs/src/slic3r/GUI/PresetHints.cpp:225
 #, c-format
 msgid "%3.2f mm³/s"
 msgstr "%3.2f мм³/с"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:226
+#: xs/src/slic3r/GUI/PresetHints.cpp:227
 #, c-format
 msgid " at filament speed %3.2f mm/s."
 msgstr " при швидкості філаменту %3.2f мм/с."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:245
+#: xs/src/slic3r/GUI/PresetHints.cpp:246
 msgid ""
 "Recommended object thin wall thickness: Not available due to invalid layer "
 "height."
@@ -997,25 +1665,21 @@ msgstr ""
 "Рекомендований об'єкт товщиною тонкої стінки: Недоступний через невірне "
 "значення висоти шару."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:262
+#: xs/src/slic3r/GUI/PresetHints.cpp:263
 #, c-format
 msgid "Recommended object thin wall thickness for layer height %.2f and "
 msgstr "Рекомендована товщина стінки для висоти шару %.2f та "
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\PresetHints.cpp:269
+#: xs/src/slic3r/GUI/PresetHints.cpp:270
 #, c-format
 msgid "%d lines: %.2lf mm"
 msgstr "%d рядків: %.2lf мм"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.hpp:17
-msgid "Preferences"
-msgstr "Налаштування"
-
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:27
+#: xs/src/slic3r/GUI/Preferences.cpp:34
 msgid "Remember output directory"
 msgstr "Пам'ятати вихідний каталог"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:29
+#: xs/src/slic3r/GUI/Preferences.cpp:36
 msgid ""
 "If this is enabled, Slic3r will prompt the last output directory instead of "
 "the one containing the input files."
@@ -1023,22 +1687,22 @@ msgstr ""
 "Якщо вибрано, Slic3r запропонує останню вихідну директорію замість тої, що "
 "вказана у вхідному файлі."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:35
+#: xs/src/slic3r/GUI/Preferences.cpp:42
 msgid "Auto-center parts"
 msgstr "Автоцентрувати частини"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:37
+#: xs/src/slic3r/GUI/Preferences.cpp:44
 msgid ""
 "If this is enabled, Slic3r will auto-center objects around the print bed "
 "center."
 msgstr ""
 "Якщо вибрано, Slic3r автоматично орієнтує об'єкти навколо центру друку."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:43
+#: xs/src/slic3r/GUI/Preferences.cpp:50
 msgid "Background processing"
 msgstr "Фонова обробка"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:45
+#: xs/src/slic3r/GUI/Preferences.cpp:52
 msgid ""
 "If this is enabled, Slic3r will pre-process objects as soon as they're "
 "loaded in order to save time when exporting G-code."
@@ -1046,11 +1710,11 @@ msgstr ""
 "Якщо вибрано, Slic3r буде попередньо обробляти об'єкти, як тільки вони "
 "будуть завантажені, щоб заощадити час при експорті G-коду."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:51
+#: xs/src/slic3r/GUI/Preferences.cpp:74
 msgid "Disable USB/serial connection"
 msgstr "Вимкнути USB / послідовне з'єднання"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:53
+#: xs/src/slic3r/GUI/Preferences.cpp:76
 msgid ""
 "Disable communication with the printer over a serial / USB cable. This "
 "simplifies the user interface in case the printer is never attached to the "
@@ -1060,11 +1724,11 @@ msgstr ""
 "Користувальницький інтерфейс спрощує, якщо принтер ніколи не приєднується до "
 "комп'ютера."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:59
+#: xs/src/slic3r/GUI/Preferences.cpp:82
 msgid "Suppress \" - default - \" presets"
 msgstr "Заборонити налаштування \"- за замовчуванням -\""
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:61
+#: xs/src/slic3r/GUI/Preferences.cpp:84
 msgid ""
 "Suppress \" - default - \" presets in the Print / Filament / Printer "
 "selections once there are any other valid presets available."
@@ -1072,11 +1736,11 @@ msgstr ""
 "Заборонити налаштування \"- за замовчуванням -\" у параметрах Друк / "
 "Філамент / Принтер, якщо доступні інші діючі налаштування."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:67
+#: xs/src/slic3r/GUI/Preferences.cpp:90
 msgid "Show incompatible print and filament presets"
 msgstr "Показувати несумісні налаштування друку та філаменту"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:69
+#: xs/src/slic3r/GUI/Preferences.cpp:92
 msgid ""
 "When checked, the print and filament presets are shown in the preset editor "
 "even if they are marked as incompatible with the active printer"
@@ -1084,11 +1748,11 @@ msgstr ""
 "Якщо вибрано, налаштування друку та філаменту відображаються у списку "
 "налаштувань, навіть якщо вони позначені як несумісні з активним принтером"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:75
+#: xs/src/slic3r/GUI/Preferences.cpp:98
 msgid "Use legacy OpenGL 1.1 rendering"
 msgstr "Використовувати застарілий OpenGL 1.1 рендеринг"
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:77
+#: xs/src/slic3r/GUI/Preferences.cpp:100
 msgid ""
 "If you have rendering issues caused by a buggy OpenGL 2.0 driver, you may "
 "try to check this checkbox. This will disable the layer height editing and "
@@ -1099,15 +1763,355 @@ msgstr ""
 "редагування висоти шару та згладжування, тому краще оновити графічний "
 "драйвер."
 
-#: c:\src\Slic3r\xs\src\slic3r\GUI\Preferences.cpp:101
+#: xs/src/slic3r/GUI/Preferences.cpp:124
 msgid "You need to restart Slic3r to make the changes effective."
 msgstr "З метою ефективності зміни, Вам потрібно буде перезапустити Slic3r."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:26
+#: xs/src/slic3r/GUI/RammingChart.cpp:23
+msgid "NO RAMMING AT ALL"
+msgstr ""
+
+#: xs/src/slic3r/GUI/RammingChart.cpp:76
+msgid "Time"
+msgstr ""
+
+#: xs/src/slic3r/GUI/RammingChart.cpp:76 xs/src/slic3r/GUI/RammingChart.cpp:81
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:77
+#: xs/src/libslic3r/PrintConfig.cpp:490
+msgid "s"
+msgstr ""
+
+#: xs/src/slic3r/GUI/RammingChart.cpp:81
+msgid "Volumetric speed"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:27
+msgid "Update available"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:27
+msgid "New version of Slic3r PE is available"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:34
+msgid "To download, follow the link below."
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:41
+msgid "Current version:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:43
+msgid "New version:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:51
+msgid "Don't notify about new releases any more"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:69
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:161
+msgid "Configuration update"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:69
+msgid "Configuration update is available"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:72
+msgid ""
+"Would you like to install it?\n"
+"\n"
+"Note that a full configuration snapshot will be created first. It can then "
+"be restored at any time should there be a problem with the new version.\n"
+"\n"
+"Updated configuration bundles:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:108
+msgid "Slic3r incompatibility"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:108
+msgid "Slic3r configuration is incompatible"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:111
+msgid ""
+"This version of Slic3r PE is not compatible with currently installed "
+"configuration bundles.\n"
+"This probably happened as a result of running an older Slic3r PE after using "
+"a newer one.\n"
+"\n"
+"You may either exit Slic3r and try again with a newer version, or you may re-"
+"run the initial configuration. Doing so will create a backup snapshot of the "
+"existing configuration before installing files compatible with this Slic3r.\n"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:120
+#, c-format
+msgid "This Slic3r PE version: %s"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:125
+msgid "Incompatible bundles:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:141
+msgid "Exit Slic3r"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:144
+msgid "Re-configure"
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:165
+#, c-format
+msgid ""
+"Slic3r PE now uses an updated configuration structure.\n"
+"\n"
+"So called 'System presets' have been introduced, which hold the built-in "
+"default settings for various printers. These System presets cannot be "
+"modified, instead, users now may create their own presets inheriting "
+"settings from one of the System presets.\n"
+"An inheriting preset may either inherit a particular value from its parent "
+"or override it with a customized value.\n"
+"\n"
+"Please proceed with the %s that follows to set up the new presets and to "
+"choose whether to enable automatic preset updates."
+msgstr ""
+
+#: xs/src/slic3r/GUI/UpdateDialogs.cpp:181
+msgid "For more information please visit our wiki page:"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:9
+msgid "Ramming customization"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:35
+msgid ""
+"Ramming denotes the rapid extrusion just before a tool change in a single-"
+"extruder MM printer. Its purpose is to properly shape the end of the "
+"unloaded filament so it does not prevent insertion of the new filament and "
+"can itself be reinserted later. This phase is important and different "
+"materials can require different extrusion speeds to get the good shape. For "
+"this reason, the extrusion rates during ramming are adjustable.\n"
+"\n"
+"This is an expert-level setting, incorrect adjustment will likely lead to "
+"jams, extruder wheel grinding into filament etc."
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:77
+msgid "Total ramming time"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:79
+msgid "Total rammed volume"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:83
+msgid "Ramming line width"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:85
+msgid "Ramming line spacing"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:137
+msgid "Wipe tower - Purging volume adjustment"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:218
+msgid ""
+"Here you can adjust required purging volume (mm³) for any given pair of "
+"tools."
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:219
+msgid "Extruder changed to"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:227
+msgid "unloaded"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:228
+msgid "loaded"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:233
+msgid "Tool #"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:240
+msgid ""
+"Total purging volume is calculated by summing two values below, depending on "
+"which tools are loaded/unloaded."
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:241
+msgid "Volume to purge (mm³) when the filament is being"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:255
+msgid "From"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:320
+msgid ""
+"Switching to simple settings will discard changes done in the advanced "
+"mode!\n"
+"\n"
+"Do you want to proceed?"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:332
+msgid "Show simplified settings"
+msgstr ""
+
+#: xs/src/slic3r/GUI/WipeTowerDialog.cpp:332
+msgid "Show advanced settings"
+msgstr ""
+
+#: xs/src/slic3r/Utils/OctoPrint.cpp:33
+msgid "Send G-Code to printer"
+msgstr ""
+
+#: xs/src/slic3r/Utils/OctoPrint.cpp:33
+msgid "Upload to OctoPrint with the following filename:"
+msgstr ""
+
+#: xs/src/slic3r/Utils/OctoPrint.cpp:35
+msgid "Start printing after upload"
+msgstr ""
+
+#: xs/src/slic3r/Utils/OctoPrint.cpp:37
+msgid "Use forward slashes ( / ) as a directory separator if needed."
+msgstr ""
+
+#: xs/src/slic3r/Utils/OctoPrint.cpp:98
+msgid "Error while uploading to the OctoPrint server"
+msgstr ""
+
+#: xs/src/slic3r/Utils/OctoPrint.cpp:111 lib/Slic3r/GUI/Plater.pm:1558
+msgid "Sending G-code file to the OctoPrint server..."
+msgstr "Відправка файлу G-коду на сервер OctoPrint..."
+
+#: xs/src/slic3r/Utils/PresetUpdater.cpp:544
+#, c-format
+msgid "requires min. %s and max. %s"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:553
+msgid "All objects are outside of the print volume."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:579
+msgid "Some objects are too close; your extruder will collide with them."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:594
+msgid ""
+"Some objects are too tall and cannot be printed without extruder collisions."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:604
+msgid "The Spiral Vase option can only be used when printing a single object."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:606
+msgid ""
+"The Spiral Vase option can only be used when printing single material "
+"objects."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:612
+msgid ""
+"All extruders must have the same diameter for single extruder multimaterial "
+"printer."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:617
+msgid ""
+"The Wipe Tower is currently only supported for the Marlin and RepRap/"
+"Sprinter G-code flavors."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:619
+msgid ""
+"The Wipe Tower is currently only supported with the relative extruder "
+"addressing (use_relative_e_distances=1)."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:631
+msgid ""
+"The Wipe Tower is only supported for multiple objects if they have equal "
+"layer heigths"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:633
+msgid ""
+"The Wipe Tower is only supported for multiple objects if they are printed "
+"over an equal number of raft layers"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:635
+msgid ""
+"The Wipe Tower is only supported for multiple objects if they are printed "
+"with the same support_material_contact_distance"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:637
+msgid ""
+"The Wipe Tower is only supported for multiple objects if they are sliced "
+"equally."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:661
+msgid ""
+"The Wipe tower is only supported if all objects have the same layer height "
+"profile"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:670
+msgid "The supplied settings will cause an empty print."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:680
+msgid ""
+"One or more object were assigned an extruder that the printer does not have."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:689
+msgid ""
+"Printing with multiple extruders of differing nozzle diameters. If support "
+"is to be printed with the current extruder (support_material_extruder == 0 "
+"or support_material_interface_extruder == 0), all nozzles have to be of the "
+"same diameter."
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:695
+msgid "first_layer_height"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:710
+msgid "First layer height can't be greater than nozzle diameter"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:714
+msgid "Layer height can't be greater than nozzle diameter"
+msgstr ""
+
+#: xs/src/libslic3r/Print.cpp:1196
+msgid "Failed processing of the output_filename_format template."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:29
 msgid "Avoid crossing perimeters"
 msgstr "Уникати перетинання периметрів"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:27
+#: xs/src/libslic3r/PrintConfig.cpp:30
 msgid ""
 "Optimize travel moves in order to minimize the crossing of perimeters. This "
 "is mostly useful with Bowden extruders which suffer from oozing. This "
@@ -1117,12 +2121,11 @@ msgstr ""
 "основному це корисно для екструдерів Bowden, які страждають від протікання. "
 "Ця функція уповільнює як друк, так і генерацію G-коду."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:38
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1572
+#: xs/src/libslic3r/PrintConfig.cpp:41 xs/src/libslic3r/PrintConfig.cpp:1818
 msgid "Other layers"
 msgstr "Інші шари"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:39
+#: xs/src/libslic3r/PrintConfig.cpp:42
 msgid ""
 "Bed temperature for layers after the first one. Set this to zero to disable "
 "bed temperature control commands in the output."
@@ -1130,11 +2133,11 @@ msgstr ""
 "Температура полотна для останніх шарів після першого. Установіть 0, щоб "
 "відключити команди керування температурою полотна на виході."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:42
+#: xs/src/libslic3r/PrintConfig.cpp:45
 msgid "Bed temperature"
 msgstr "Температура полотна"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:49
+#: xs/src/libslic3r/PrintConfig.cpp:52
 msgid ""
 "This custom code is inserted at every layer change, right before the Z move. "
 "Note that you can use placeholder variables for all Slic3r settings as well "
@@ -1144,11 +2147,11 @@ msgstr ""
 "переміщення Z. Зауважте, що ви можете використовувати змінні-заповнювачі для "
 "всіх параметрів Slic3r, а також [layer_num] і [layer_z]."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:59
+#: xs/src/libslic3r/PrintConfig.cpp:62
 msgid "Between objects G-code"
 msgstr "G-код між об'єктами"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:60
+#: xs/src/libslic3r/PrintConfig.cpp:63
 msgid ""
 "This code is inserted between objects when using sequential printing. By "
 "default extruder and bed temperature are reset using non-wait command; "
@@ -1165,39 +2168,32 @@ msgstr ""
 "Slic3r, то ж ви можете вставити команду \"M109 S [first_layer_temperature]\" "
 "де завгодно."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:68
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:370
+#: xs/src/libslic3r/PrintConfig.cpp:71 lib/Slic3r/GUI/MainFrame.pm:328
 msgid "Bottom"
 msgstr "Знизу"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:69
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:239
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:290
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:298
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:604
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:762
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:778
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:941
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:989
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1152
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1583
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1639
+#: xs/src/libslic3r/PrintConfig.cpp:72 xs/src/libslic3r/PrintConfig.cpp:276
+#: xs/src/libslic3r/PrintConfig.cpp:327 xs/src/libslic3r/PrintConfig.cpp:335
+#: xs/src/libslic3r/PrintConfig.cpp:701 xs/src/libslic3r/PrintConfig.cpp:871
+#: xs/src/libslic3r/PrintConfig.cpp:887 xs/src/libslic3r/PrintConfig.cpp:1156
+#: xs/src/libslic3r/PrintConfig.cpp:1222 xs/src/libslic3r/PrintConfig.cpp:1400
+#: xs/src/libslic3r/PrintConfig.cpp:1829 xs/src/libslic3r/PrintConfig.cpp:1885
 msgid "Layers and Perimeters"
 msgstr "Шари та периметри"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:70
+#: xs/src/libslic3r/PrintConfig.cpp:73
 msgid "Number of solid layers to generate on bottom surfaces."
 msgstr "Кількість суцільних шарів, генерованих на нижніх поверхнях."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:72
+#: xs/src/libslic3r/PrintConfig.cpp:75
 msgid "Bottom solid layers"
 msgstr "Нижні суцільні шари"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:77
+#: xs/src/libslic3r/PrintConfig.cpp:80
 msgid "Bridge"
 msgstr "Міст"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:78
+#: xs/src/libslic3r/PrintConfig.cpp:81
 msgid ""
 "This is the acceleration your printer will use for bridges. Set zero to "
 "disable acceleration control for bridges."
@@ -1205,19 +2201,18 @@ msgstr ""
 "Це прискорення, яке ваш принтер використовуватиме для мостів. Встановити 0, "
 "щоб відключити управління прискоренням для мостів."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:80
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:174
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:576
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:684
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:952
+#: xs/src/libslic3r/PrintConfig.cpp:83 xs/src/libslic3r/PrintConfig.cpp:199
+#: xs/src/libslic3r/PrintConfig.cpp:673 xs/src/libslic3r/PrintConfig.cpp:781
+#: xs/src/libslic3r/PrintConfig.cpp:931 xs/src/libslic3r/PrintConfig.cpp:972
+#: xs/src/libslic3r/PrintConfig.cpp:982 xs/src/libslic3r/PrintConfig.cpp:1185
 msgid "mm/s²"
 msgstr "мм/с²"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:86
+#: xs/src/libslic3r/PrintConfig.cpp:89
 msgid "Bridging angle"
 msgstr "Кут моста"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:88
+#: xs/src/libslic3r/PrintConfig.cpp:91
 msgid ""
 "Bridging angle override. If left to zero, the bridging angle will be "
 "calculated automatically. Otherwise the provided angle will be used for all "
@@ -1227,36 +2222,31 @@ msgstr ""
 "автоматично. Інакше передбачений кут буде використаний для всіх мостів. "
 "Використовуйте 180° для нульового кута."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:91
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:492
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1170
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1181
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1401
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1557
+#: xs/src/libslic3r/PrintConfig.cpp:94 xs/src/libslic3r/PrintConfig.cpp:589
+#: xs/src/libslic3r/PrintConfig.cpp:1418 xs/src/libslic3r/PrintConfig.cpp:1429
+#: xs/src/libslic3r/PrintConfig.cpp:1649 xs/src/libslic3r/PrintConfig.cpp:1803
 msgid "°"
 msgstr "°"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:97
+#: xs/src/libslic3r/PrintConfig.cpp:100
 msgid "Bridges fan speed"
 msgstr "Швидкість вентилятора для мостів"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:98
+#: xs/src/libslic3r/PrintConfig.cpp:101
 msgid "This fan speed is enforced during all bridges and overhangs."
 msgstr "Ця швидкість вентилятора виконується для всіх мостів і виступів."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:99
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:504
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:789
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:850
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1060
+#: xs/src/libslic3r/PrintConfig.cpp:102 xs/src/libslic3r/PrintConfig.cpp:601
+#: xs/src/libslic3r/PrintConfig.cpp:990 xs/src/libslic3r/PrintConfig.cpp:1058
+#: xs/src/libslic3r/PrintConfig.cpp:1308
 msgid "%"
 msgstr "%"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:106
+#: xs/src/libslic3r/PrintConfig.cpp:109
 msgid "Bridge flow ratio"
 msgstr "Співвідношення мостового потоку"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:108
+#: xs/src/libslic3r/PrintConfig.cpp:111
 msgid ""
 "This factor affects the amount of plastic for bridging. You can decrease it "
 "slightly to pull the extrudates and prevent sagging, although default "
@@ -1268,32 +2258,31 @@ msgstr ""
 "стандартні налаштування зазвичай добрі, тому ви маете по-експериментувати з "
 "охолодженням (використовуйте вентилятор), перш ніж їх налаштувати."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:117
+#: xs/src/libslic3r/PrintConfig.cpp:121
 msgid "Bridges"
 msgstr "Мости"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:119
+#: xs/src/libslic3r/PrintConfig.cpp:123
 msgid "Speed for printing bridges."
 msgstr "Швидкість друку мостів."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:120
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:638
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:749
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:811
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:868
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:981
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1137
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1146
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1536
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1649
+#: xs/src/libslic3r/PrintConfig.cpp:124 xs/src/libslic3r/PrintConfig.cpp:471
+#: xs/src/libslic3r/PrintConfig.cpp:480 xs/src/libslic3r/PrintConfig.cpp:508
+#: xs/src/libslic3r/PrintConfig.cpp:516 xs/src/libslic3r/PrintConfig.cpp:735
+#: xs/src/libslic3r/PrintConfig.cpp:846 xs/src/libslic3r/PrintConfig.cpp:922
+#: xs/src/libslic3r/PrintConfig.cpp:940 xs/src/libslic3r/PrintConfig.cpp:952
+#: xs/src/libslic3r/PrintConfig.cpp:962 xs/src/libslic3r/PrintConfig.cpp:1019
+#: xs/src/libslic3r/PrintConfig.cpp:1076 xs/src/libslic3r/PrintConfig.cpp:1214
+#: xs/src/libslic3r/PrintConfig.cpp:1385 xs/src/libslic3r/PrintConfig.cpp:1394
+#: xs/src/libslic3r/PrintConfig.cpp:1782 xs/src/libslic3r/PrintConfig.cpp:1895
 msgid "mm/s"
 msgstr "мм/с"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:127
+#: xs/src/libslic3r/PrintConfig.cpp:131
 msgid "Brim width"
 msgstr "Ширина краю"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:128
+#: xs/src/libslic3r/PrintConfig.cpp:132
 msgid ""
 "Horizontal width of the brim that will be printed around each object on the "
 "first layer."
@@ -1301,11 +2290,11 @@ msgstr ""
 "Горизонтальна ширина краю, яка буде надрукована навколо кожного об'єкта на "
 "першому шарі."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:135
+#: xs/src/libslic3r/PrintConfig.cpp:139
 msgid "Clip multi-part objects"
 msgstr "Обрізати об'єкти, що складаються з кількох частин"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:136
+#: xs/src/libslic3r/PrintConfig.cpp:140
 msgid ""
 "When printing multi-material objects, this settings will make slic3r to clip "
 "the overlapping object parts one by the other (2nd part will be clipped by "
@@ -1315,11 +2304,11 @@ msgstr ""
 "обрізати частини, що перекриваються один одною (друга частина буде обрізана "
 "першою, третя - першою та другою, тощо)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:147
+#: xs/src/libslic3r/PrintConfig.cpp:151
 msgid "Compatible printers condition"
 msgstr "Стан сумісних принтерів"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:148
+#: xs/src/libslic3r/PrintConfig.cpp:152
 msgid ""
 "A boolean expression using the configuration values of an active printer "
 "profile. If this expression evaluates to true, this profile is considered "
@@ -1329,11 +2318,11 @@ msgstr ""
 "принтера. Якщо цей вираз оцінюється як Правда, цей профіль вважається "
 "сумісним з активним профілем принтера."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:154
+#: xs/src/libslic3r/PrintConfig.cpp:163
 msgid "Complete individual objects"
 msgstr "Закінчити окремі об'єкти"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:155
+#: xs/src/libslic3r/PrintConfig.cpp:164
 msgid ""
 "When printing multiple objects or copies, this feature will complete each "
 "object before moving onto next one (and starting it from its bottom layer). "
@@ -1345,11 +2334,11 @@ msgstr ""
 "шару). Ця функція корисна для уникнення ризику зіпсованих відбитків. Slic3r "
 "має попередити та запобігти зіткненню екструдера, але будьте обережні."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:163
+#: xs/src/libslic3r/PrintConfig.cpp:172
 msgid "Enable auto cooling"
 msgstr "Увімкнути автоматичне охолодження"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:164
+#: xs/src/libslic3r/PrintConfig.cpp:173
 msgid ""
 "This flag enables the automatic cooling logic that adjusts print speed and "
 "fan speed according to layer printing time."
@@ -1357,7 +2346,23 @@ msgstr ""
 "Цей прапорець дозволяє автоматичну логіку охолодження, яка регулює швидкість "
 "друку та швидкість вентиляції відповідно до часу друку шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:171
+#: xs/src/libslic3r/PrintConfig.cpp:179
+msgid "Cooling tube position"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:180
+msgid "Distance of the center-point of the cooling tube from the extruder tip "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:187
+msgid "Cooling tube length"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:188
+msgid "Length of the cooling tube to limit space for cooling moves inside it "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:196
 msgid ""
 "This is the acceleration your printer will be reset to after the role-"
 "specific acceleration values are used (perimeter/infill). Set zero to "
@@ -1367,11 +2372,33 @@ msgstr ""
 "використані конкретні визначені прискорення (периметру / заповнення). "
 "Встановити 0, щоб запобігти скиданням прискорення взагалі."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:180
+#: xs/src/libslic3r/PrintConfig.cpp:205
+msgid "Default filament profile"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:206
+msgid ""
+"Default filament profile associated with the current printer profile. On "
+"selection of the current printer profile, this filament profile will be "
+"activated."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:211
+msgid "Default print profile"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:212
+msgid ""
+"Default print profile associated with the current printer profile. On "
+"selection of the current printer profile, this print profile will be "
+"activated."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:217
 msgid "Disable fan for the first"
 msgstr "Вимкнути вентилятор для першого(их)"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:181
+#: xs/src/libslic3r/PrintConfig.cpp:218
 msgid ""
 "You can set this to a positive value to disable fan at all during the first "
 "layers, so that it does not make adhesion worse."
@@ -1380,21 +2407,18 @@ msgstr ""
 "протягом друку декількох перших шарів, щоб це не призвело до гіршого "
 "зчеплення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:183
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:694
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1033
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1224
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1285
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1437
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1482
+#: xs/src/libslic3r/PrintConfig.cpp:220 xs/src/libslic3r/PrintConfig.cpp:791
+#: xs/src/libslic3r/PrintConfig.cpp:1281 xs/src/libslic3r/PrintConfig.cpp:1472
+#: xs/src/libslic3r/PrintConfig.cpp:1533 xs/src/libslic3r/PrintConfig.cpp:1685
+#: xs/src/libslic3r/PrintConfig.cpp:1730
 msgid "layers"
 msgstr "шару(ів)"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:190
+#: xs/src/libslic3r/PrintConfig.cpp:227
 msgid "Don't support bridges"
 msgstr "Не підтримувати мости"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:192
+#: xs/src/libslic3r/PrintConfig.cpp:229
 msgid ""
 "Experimental option for preventing support material from being generated "
 "under bridged areas."
@@ -1402,19 +2426,19 @@ msgstr ""
 "Експериментальний варіант для запобігання утворенню допоміжного матеріалу в "
 "областях під мостами."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:198
+#: xs/src/libslic3r/PrintConfig.cpp:235
 msgid "Distance between copies"
 msgstr "Відстань між копіями"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:199
+#: xs/src/libslic3r/PrintConfig.cpp:236
 msgid "Distance used for the auto-arrange feature of the plater."
 msgstr "Відстань використовується для автоматичного розташування платеру."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:207
+#: xs/src/libslic3r/PrintConfig.cpp:244
 msgid "Elephant foot compensation"
 msgstr "Зрівноваження Стопи слона"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:209
+#: xs/src/libslic3r/PrintConfig.cpp:246
 msgid ""
 "The first layer will be shrunk in the XY plane by the configured value to "
 "compensate for the 1st layer squish aka an Elephant Foot effect."
@@ -1422,7 +2446,7 @@ msgstr ""
 "Перший шар буде зменшено в площині XY завдяки налаштованому значенню, щоб "
 "компенсувати ефект Ноги Слона для 1-го шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:218
+#: xs/src/libslic3r/PrintConfig.cpp:255
 msgid ""
 "This end procedure is inserted at the end of the output file. Note that you "
 "can use placeholder variables for all Slic3r settings."
@@ -1430,7 +2454,7 @@ msgstr ""
 "Ця кінцева процедура вставляється в кінці вихідного файлу. Зауважте, що ви "
 "можете використовувати заповнювачі змінних для всіх параметрів Slic3r."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:228
+#: xs/src/libslic3r/PrintConfig.cpp:265
 msgid ""
 "This end procedure is inserted at the end of the output file, before the "
 "printer end gcode. Note that you can use placeholder variables for all "
@@ -1442,11 +2466,11 @@ msgstr ""
 "для всіх параметрів Slic3r. Якщо у вас є кілька екструдерів, G-code "
 "обробляється в порядку екструдерів."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:238
+#: xs/src/libslic3r/PrintConfig.cpp:275
 msgid "Ensure vertical shell thickness"
 msgstr "Перевірте товщину вертикальної оболонки"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:240
+#: xs/src/libslic3r/PrintConfig.cpp:277
 msgid ""
 "Add solid infill near sloping surfaces to guarantee the vertical shell "
 "thickness (top+bottom solid layers)."
@@ -1454,11 +2478,11 @@ msgstr ""
 "Додайте суцільні наповнювачі біля нахилених поверхонь, щоб гарантувати "
 "товщину вертикальної оболонки (верхній і нижній суцільні шари)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:246
+#: xs/src/libslic3r/PrintConfig.cpp:283
 msgid "Top/bottom fill pattern"
 msgstr "Верхній/нижній шаблон наповнення"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:248
+#: xs/src/libslic3r/PrintConfig.cpp:285
 msgid ""
 "Fill pattern for top/bottom infill. This only affects the external visible "
 "layer, and not its adjacent solid shells."
@@ -1466,23 +2490,39 @@ msgstr ""
 "Шаблон для верхнього/нижнього наповнення. Це впливає лише на зовнішній "
 "видимий шар, а не на сусідні суцільні оболонки."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:267
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:277
+#: xs/src/libslic3r/PrintConfig.cpp:294 xs/src/libslic3r/PrintConfig.cpp:654
+#: xs/src/libslic3r/PrintConfig.cpp:1764
+msgid "Rectilinear"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:295 xs/src/libslic3r/PrintConfig.cpp:660
+msgid "Concentric"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:296 xs/src/libslic3r/PrintConfig.cpp:664
+msgid "Hilbert Curve"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:297 xs/src/libslic3r/PrintConfig.cpp:665
+msgid "Archimedean Chords"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:298 xs/src/libslic3r/PrintConfig.cpp:666
+msgid "Octagram Spiral"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:304 xs/src/libslic3r/PrintConfig.cpp:314
 msgid "External perimeters"
 msgstr "Зовнішні периметри"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:268
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:377
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:592
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:710
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:967
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1292
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1454
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1614
+#: xs/src/libslic3r/PrintConfig.cpp:305 xs/src/libslic3r/PrintConfig.cpp:415
+#: xs/src/libslic3r/PrintConfig.cpp:689 xs/src/libslic3r/PrintConfig.cpp:807
+#: xs/src/libslic3r/PrintConfig.cpp:1200 xs/src/libslic3r/PrintConfig.cpp:1540
+#: xs/src/libslic3r/PrintConfig.cpp:1702 xs/src/libslic3r/PrintConfig.cpp:1860
 msgid "Extrusion Width"
 msgstr "Ширина екструзії"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:269
+#: xs/src/libslic3r/PrintConfig.cpp:306
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for external "
 "perimeters. If left zero, default extrusion width will be used if set, "
@@ -1495,17 +2535,14 @@ msgstr ""
 "сопла. Якщо він виражений у відсотках (наприклад, 200%), він буде "
 "обчислюватися за висотою шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:272
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:597
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:715
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:972
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1296
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1458
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1619
+#: xs/src/libslic3r/PrintConfig.cpp:309 xs/src/libslic3r/PrintConfig.cpp:694
+#: xs/src/libslic3r/PrintConfig.cpp:812 xs/src/libslic3r/PrintConfig.cpp:1205
+#: xs/src/libslic3r/PrintConfig.cpp:1544 xs/src/libslic3r/PrintConfig.cpp:1706
+#: xs/src/libslic3r/PrintConfig.cpp:1865
 msgid "mm or % (leave 0 for default)"
 msgstr "мм або % (залиште 0 за замовчанням)"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:279
+#: xs/src/libslic3r/PrintConfig.cpp:316
 msgid ""
 "This separate setting will affect the speed of external perimeters (the "
 "visible ones). If expressed as percentage (for example: 80%) it will be "
@@ -1516,20 +2553,17 @@ msgstr ""
 "налаштування швидкості периметра вище. Встановити 0 для автоматичного "
 "використання."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:282
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:619
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1255
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1306
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1501
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1631
+#: xs/src/libslic3r/PrintConfig.cpp:319 xs/src/libslic3r/PrintConfig.cpp:716
+#: xs/src/libslic3r/PrintConfig.cpp:1503 xs/src/libslic3r/PrintConfig.cpp:1554
+#: xs/src/libslic3r/PrintConfig.cpp:1749 xs/src/libslic3r/PrintConfig.cpp:1877
 msgid "mm/s or %"
 msgstr "мм/с або %"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:289
+#: xs/src/libslic3r/PrintConfig.cpp:326
 msgid "External perimeters first"
 msgstr "Спочатку зовнішні периметри"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:291
+#: xs/src/libslic3r/PrintConfig.cpp:328
 msgid ""
 "Print contour perimeters from the outermost one to the innermost one instead "
 "of the default inverse order."
@@ -1537,11 +2571,11 @@ msgstr ""
 "Друкувати контури периметра від найзовнішнього до найвнутрішнього, замість "
 "інверсного порядку за замовчанням."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:297
+#: xs/src/libslic3r/PrintConfig.cpp:334
 msgid "Extra perimeters if needed"
 msgstr "Додаткові периметри, якщо необхідно"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:299
+#: xs/src/libslic3r/PrintConfig.cpp:336
 #, no-c-format
 msgid ""
 "Add more perimeters when needed for avoiding gaps in sloping walls. Slic3r "
@@ -1552,7 +2586,7 @@ msgstr ""
 "Slic3r продовжує додавати периметри, поки підтримується більше 70% петель "
 "безпосередньо вище."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:309
+#: xs/src/libslic3r/PrintConfig.cpp:346
 msgid ""
 "The extruder to use (unless more specific extruder settings are specified). "
 "This value overrides perimeter and infill extruders, but not the support "
@@ -1562,12 +2596,11 @@ msgstr ""
 "екструдера). Це значення перевизначає екструдери периметра та наповнювача, "
 "але не екструдери підтримки."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:320
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:69
+#: xs/src/libslic3r/PrintConfig.cpp:358 lib/Slic3r/GUI/Plater/3DPreview.pm:75
 msgid "Height"
 msgstr "Висота"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:321
+#: xs/src/libslic3r/PrintConfig.cpp:359
 msgid ""
 "Set this to the vertical distance between your nozzle tip and (usually) the "
 "X carriage rods. In other words, this is the height of the clearance "
@@ -1579,11 +2612,11 @@ msgstr ""
 "навколо вашого екструдера, і це являє собою максимальну глибину, яку "
 "екструдер може розглядати до зіткнення з іншими друкованими предметами."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:331
+#: xs/src/libslic3r/PrintConfig.cpp:369
 msgid "Radius"
 msgstr "Радіус"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:332
+#: xs/src/libslic3r/PrintConfig.cpp:370
 msgid ""
 "Set this to the clearance radius around your extruder. If the extruder is "
 "not centered, choose the largest value for safety. This setting is used to "
@@ -1594,21 +2627,20 @@ msgstr ""
 "параметр використовується для перевірки зіткнень та відображення графічного "
 "попереднього перегляду в панелі."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:342
+#: xs/src/libslic3r/PrintConfig.cpp:380
 msgid "Extruder Color"
 msgstr "Колір екструдера"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:343
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:406
+#: xs/src/libslic3r/PrintConfig.cpp:381 xs/src/libslic3r/PrintConfig.cpp:444
 msgid "This is only used in the Slic3r interface as a visual help."
 msgstr ""
 "Ця опція використовується лише у інтерфейсі Slic3r як візуальна допомога."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:350
+#: xs/src/libslic3r/PrintConfig.cpp:388
 msgid "Extruder offset"
 msgstr "Зміщення екструдеру"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:351
+#: xs/src/libslic3r/PrintConfig.cpp:389
 msgid ""
 "If your firmware doesn't handle the extruder displacement you need the G-"
 "code to take it into account. This option lets you specify the displacement "
@@ -1620,11 +2652,11 @@ msgstr ""
 "відносно першого. Він очікує позитивних координат (вони будуть віднімані від "
 "координати XY)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:360
+#: xs/src/libslic3r/PrintConfig.cpp:398
 msgid "Extrusion axis"
 msgstr "Ось екструзії"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:361
+#: xs/src/libslic3r/PrintConfig.cpp:399
 msgid ""
 "Use this option to set the axis letter associated to your printer's extruder "
 "(usually E but some printers use A)."
@@ -1632,11 +2664,11 @@ msgstr ""
 "Використовуйте цю опцію, щоб встановити букву осей, пов'язану з екструдером "
 "принтера (зазвичай E, але деякі принтери використовують A)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:367
+#: xs/src/libslic3r/PrintConfig.cpp:405
 msgid "Extrusion multiplier"
 msgstr "Коефіцієнт екструзії"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:368
+#: xs/src/libslic3r/PrintConfig.cpp:406
 msgid ""
 "This factor changes the amount of flow proportionally. You may need to tweak "
 "this setting to get nice surface finish and correct single wall widths. "
@@ -1649,11 +2681,11 @@ msgstr ""
 "вважаєте, що його потрібно більше змінити, перевірте діаметр нитки та E "
 "кроки прошивки ."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:376
+#: xs/src/libslic3r/PrintConfig.cpp:414
 msgid "Default extrusion width"
 msgstr "Ширина екструзії за замовчанням"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:378
+#: xs/src/libslic3r/PrintConfig.cpp:416
 msgid ""
 "Set this to a non-zero value to allow a manual extrusion width. If left to "
 "zero, Slic3r derives extrusion widths from the nozzle diameter (see the "
@@ -1667,15 +2699,15 @@ msgstr ""
 "наповнювача тощо). Якщо значення виражене у відсотках (наприклад: 230%), "
 "воно буде обчислюватися за висотою шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:382
+#: xs/src/libslic3r/PrintConfig.cpp:420
 msgid "mm or % (leave 0 for auto)"
 msgstr "мм або % (залиште 0 для автообчислення)"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:387
+#: xs/src/libslic3r/PrintConfig.cpp:425
 msgid "Keep fan always on"
 msgstr "Тримайте вентилятор завжди"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:388
+#: xs/src/libslic3r/PrintConfig.cpp:426
 msgid ""
 "If this is enabled, fan will never be disabled and will be kept running at "
 "least at its minimum speed. Useful for PLA, harmful for ABS."
@@ -1684,11 +2716,11 @@ msgstr ""
 "триматися, як мінімум, на мінімальній швидкості. Корисно для PLA, шкідливо "
 "для ABS."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:394
+#: xs/src/libslic3r/PrintConfig.cpp:432
 msgid "Enable fan if layer print time is below"
 msgstr "Увімкнути вентилятор, якщо час друку шару нижче"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:395
+#: xs/src/libslic3r/PrintConfig.cpp:433
 msgid ""
 "If layer print time is estimated below this number of seconds, fan will be "
 "enabled and its speed will be calculated by interpolating the minimum and "
@@ -1698,29 +2730,27 @@ msgstr ""
 "активований, а його швидкість буде розрахована шляхом інтерполяції "
 "мінімальної та максимальної швидкості."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:397
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1242
+#: xs/src/libslic3r/PrintConfig.cpp:435 xs/src/libslic3r/PrintConfig.cpp:1490
 msgid "approximate seconds"
 msgstr "приблизні секунди"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:405
+#: xs/src/libslic3r/PrintConfig.cpp:443
 msgid "Color"
 msgstr "Колір"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:412
+#: xs/src/libslic3r/PrintConfig.cpp:450
 msgid "Filament notes"
 msgstr "Примітки до філаменту"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:413
+#: xs/src/libslic3r/PrintConfig.cpp:451
 msgid "You can put your notes regarding the filament here."
 msgstr "Тут ви можете помістити свої нотатки щодо філаменту."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:421
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:817
+#: xs/src/libslic3r/PrintConfig.cpp:459 xs/src/libslic3r/PrintConfig.cpp:1025
 msgid "Max volumetric speed"
 msgstr "Максимальна об'ємна швидкість"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:422
+#: xs/src/libslic3r/PrintConfig.cpp:460
 msgid ""
 "Maximum volumetric speed allowed for this filament. Limits the maximum "
 "volumetric speed of a print to the minimum of print and filament volumetric "
@@ -1730,12 +2760,76 @@ msgstr ""
 "максимальну об'ємну швидкість друку до мінімуму об'ємної швидкості друку та "
 "філаметну. Встановити 0 для відсутності обмежень."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:425
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:820
+#: xs/src/libslic3r/PrintConfig.cpp:463 xs/src/libslic3r/PrintConfig.cpp:1028
 msgid "mm³/s"
 msgstr "мм³/с"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:432
+#: xs/src/libslic3r/PrintConfig.cpp:469
+msgid "Loading speed"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:470
+msgid "Speed used for loading the filament on the wipe tower. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:477
+msgid "Unloading speed"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:478
+msgid ""
+"Speed used for unloading the filament on the wipe tower (does not affect  "
+"initial part of unloading just after ramming). "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:486
+msgid "Delay after unloading"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:487
+msgid ""
+"Time to wait after the filament is unloaded. May help to get reliable "
+"toolchanges with flexible materials that may need more time to shrink to "
+"original dimensions. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:496
+msgid "Number of cooling moves"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:497
+msgid ""
+"Filament is cooled by being moved back and forth in the cooling tubes. "
+"Specify desired number of these moves "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:505
+msgid "Speed of the first cooling move"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:506
+msgid "Cooling moves are gradually accelerating beginning at this speed. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:513
+msgid "Speed of the last cooling move"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:514
+msgid "Cooling moves are gradually accelerating towards this speed. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:521
+msgid "Ramming parameters"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:522
+msgid ""
+"This string is edited by RammingDialog and contains ramming specific "
+"parameters "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:529
 msgid ""
 "Enter your filament diameter here. Good precision is required, so use a "
 "caliper and do multiple measurements along the filament, then compute the "
@@ -1745,11 +2839,11 @@ msgstr ""
 "використовуйте суматор і виконайте декілька вимірювань вздовж нитки, потім "
 "обчисліть середнє значення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:440
+#: xs/src/libslic3r/PrintConfig.cpp:537
 msgid "Density"
 msgstr "Щільність"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:441
+#: xs/src/libslic3r/PrintConfig.cpp:538
 msgid ""
 "Enter your filament density here. This is only for statistical information. "
 "A decent way is to weigh a known length of filament and compute the ratio of "
@@ -1761,16 +2855,15 @@ msgstr ""
 "обчислення співвідношення довжини до обсягу. Краще обчислити об'єм "
 "безпосередньо через зміщення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:444
+#: xs/src/libslic3r/PrintConfig.cpp:541
 msgid "g/cm³"
 msgstr "г/см³"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:450
+#: xs/src/libslic3r/PrintConfig.cpp:547
 msgid "Filament type"
 msgstr "Тип філаменту"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:451
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1002
+#: xs/src/libslic3r/PrintConfig.cpp:548 xs/src/libslic3r/PrintConfig.cpp:1235
 msgid ""
 "If you want to process the output G-code through custom scripts, just list "
 "their absolute paths here. Separate multiple scripts with a semicolon. "
@@ -1784,20 +2877,19 @@ msgstr ""
 "аргумент, і вони можуть отримати доступ до параметрів конфігурації Slic3r, "
 "прочитавши змінні середовища."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:470
+#: xs/src/libslic3r/PrintConfig.cpp:567
 msgid "Soluble material"
 msgstr "Розчинний матеріал"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:471
+#: xs/src/libslic3r/PrintConfig.cpp:568
 msgid "Soluble material is most likely used for a soluble support."
 msgstr "Розчинний матеріал переважно використовується для розчинної підтримки."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:476
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:450
+#: xs/src/libslic3r/PrintConfig.cpp:573 lib/Slic3r/GUI/Plater.pm:1616
 msgid "Cost"
 msgstr "Вартість"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:477
+#: xs/src/libslic3r/PrintConfig.cpp:574
 msgid ""
 "Enter your filament cost per kg here. This is only for statistical "
 "information."
@@ -1805,15 +2897,15 @@ msgstr ""
 "Введіть тут свою вартість філаменту на кг. Це тільки для статистичної "
 "інформації."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:478
+#: xs/src/libslic3r/PrintConfig.cpp:575
 msgid "money/kg"
 msgstr "грошових одиниць/кг"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:487
+#: xs/src/libslic3r/PrintConfig.cpp:584
 msgid "Fill angle"
 msgstr "Кут наповнення"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:489
+#: xs/src/libslic3r/PrintConfig.cpp:586
 msgid ""
 "Default base angle for infill orientation. Cross-hatching will be applied to "
 "this. Bridges will be infilled using the best direction Slic3r can detect, "
@@ -1823,31 +2915,61 @@ msgstr ""
 "застосовуватися крос-штрих. Мости будуть заповнені, використовуючи найкращий "
 "напрям, який може виявити Slic3r, тому цей параметр на них не впливає."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:501
+#: xs/src/libslic3r/PrintConfig.cpp:598
 msgid "Fill density"
 msgstr "Щільність заповнення"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:503
+#: xs/src/libslic3r/PrintConfig.cpp:600
 #, no-c-format
 msgid "Density of internal infill, expressed in the range 0% - 100%."
 msgstr "Щільність внутрішнього заповнення, виражена в діапазоні 0% - 100%."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:539
+#: xs/src/libslic3r/PrintConfig.cpp:636
 msgid "Fill pattern"
 msgstr "Шаблон заповнення"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:541
+#: xs/src/libslic3r/PrintConfig.cpp:638
 msgid "Fill pattern for general low-density infill."
 msgstr "Шаблон заповнення для загального низько-швидкісного наповнення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:573
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:582
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:591
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:625
+#: xs/src/libslic3r/PrintConfig.cpp:655
+msgid "Grid"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:656
+msgid "Triangles"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:657
+msgid "Stars"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:658
+msgid "Cubic"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:659
+msgid "Line"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:661 xs/src/libslic3r/PrintConfig.cpp:1766
+msgid "Honeycomb"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:662
+msgid "3D Honeycomb"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:663
+msgid "Gyroid"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:670 xs/src/libslic3r/PrintConfig.cpp:679
+#: xs/src/libslic3r/PrintConfig.cpp:688 xs/src/libslic3r/PrintConfig.cpp:722
 msgid "First layer"
 msgstr "Перший шар"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:574
+#: xs/src/libslic3r/PrintConfig.cpp:671
 msgid ""
 "This is the acceleration your printer will use for first layer. Set zero to "
 "disable acceleration control for first layer."
@@ -1855,7 +2977,7 @@ msgstr ""
 "Це прискорення, яке ваш принтер використовуватиме для першого шару. "
 "Встановити 0, щоб вимкнути керування прискоренням для першого шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:583
+#: xs/src/libslic3r/PrintConfig.cpp:680
 msgid ""
 "Heated build plate temperature for the first layer. Set this to zero to "
 "disable bed temperature control commands in the output."
@@ -1863,7 +2985,7 @@ msgstr ""
 "Температура підігрітої збірної пластини для першого шару. Установіть 0, щоб "
 "відключити команди керування температурою полотна на виході."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:593
+#: xs/src/libslic3r/PrintConfig.cpp:690
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for first "
 "layer. You can use this to force fatter extrudates for better adhesion. If "
@@ -1876,11 +2998,11 @@ msgstr ""
 "(наприклад, 120%), вона буде обчислена за висотою першого шару. Якщо "
 "встановлено на 0 - використовуватиме стандартну ширину екструзії."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:603
+#: xs/src/libslic3r/PrintConfig.cpp:700
 msgid "First layer height"
 msgstr "Висота першого шару"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:605
+#: xs/src/libslic3r/PrintConfig.cpp:702
 msgid ""
 "When printing with very low layer heights, you might still want to print a "
 "thicker bottom layer to improve adhesion and tolerance for non perfect build "
@@ -1892,17 +3014,16 @@ msgstr ""
 "до невідповідних збірних пластин. Можна виразити як абсолютне значення або "
 "як відсоток (наприклад: 150%) по висоті шару за замовчуванням."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:609
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:740
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1390
+#: xs/src/libslic3r/PrintConfig.cpp:706 xs/src/libslic3r/PrintConfig.cpp:837
+#: xs/src/libslic3r/PrintConfig.cpp:1638
 msgid "mm or %"
 msgstr "мм або %"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:615
+#: xs/src/libslic3r/PrintConfig.cpp:712
 msgid "First layer speed"
 msgstr "Швидкість першого шару"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:616
+#: xs/src/libslic3r/PrintConfig.cpp:713
 msgid ""
 "If expressed as absolute value in mm/s, this speed will be applied to all "
 "the print moves of the first layer, regardless of their type. If expressed "
@@ -1913,7 +3034,7 @@ msgstr ""
 "вона виражена у відсотках (наприклад: 40%), вона буде масштабувати швидкість "
 "за замовчуванням."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:626
+#: xs/src/libslic3r/PrintConfig.cpp:723
 msgid ""
 "Extruder temperature for first layer. If you want to control temperature "
 "manually during print, set this to zero to disable temperature control "
@@ -1923,13 +3044,13 @@ msgstr ""
 "температуру вручну під час друку, встановіть 0, щоб вимкнути команди "
 "керування температурою у вихідному файлі."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:634
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:145
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:87
+#: xs/src/libslic3r/PrintConfig.cpp:731
+#: xs/src/libslic3r/GCode/PreviewData.cpp:170
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:97
 msgid "Gap fill"
 msgstr "Заповнення розриву"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:636
+#: xs/src/libslic3r/PrintConfig.cpp:733
 msgid ""
 "Speed for filling small gaps using short zigzag moves. Keep this reasonably "
 "low to avoid too much shaking and resonance issues. Set zero to disable gaps "
@@ -1940,11 +3061,11 @@ msgstr ""
 "надмірних потрясінь та резонансних проблем. Встановити 0, щоб вимкнути "
 "заповнення розривів."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:644
+#: xs/src/libslic3r/PrintConfig.cpp:741
 msgid "Verbose G-code"
 msgstr "Докладний G-код"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:645
+#: xs/src/libslic3r/PrintConfig.cpp:742
 msgid ""
 "Enable this to get a commented G-code file, with each line explained by a "
 "descriptive text. If you print from SD card, the additional weight of the "
@@ -1954,11 +3075,11 @@ msgstr ""
 "пояснюється описовим текстом. Якщо ви друкуєте з SD-карти, додаткова вага "
 "файлу може призвести до уповільнення прошивки."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:652
+#: xs/src/libslic3r/PrintConfig.cpp:749
 msgid "G-code flavor"
 msgstr "Особливість G-коду"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:653
+#: xs/src/libslic3r/PrintConfig.cpp:750
 msgid ""
 "Some G/M-code commands, including temperature control and others, are not "
 "universal. Set this option to your printer's firmware to get a compatible "
@@ -1970,7 +3091,11 @@ msgstr ""
 "сумісний вихід. \"Відсутність екструзії\" не дозволяє Slic3r експортувати "
 "будь-яке значення екструзії."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:682
+#: xs/src/libslic3r/PrintConfig.cpp:774
+msgid "No extrusion"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:779
 msgid ""
 "This is the acceleration your printer will use for infill. Set zero to "
 "disable acceleration control for infill."
@@ -1978,11 +3103,11 @@ msgstr ""
 "Це прискорення, яке ваш принтер використовуватиме для наповнення. Встановити "
 "0, щоб вимкнути регулятор прискорення для заповнення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:690
+#: xs/src/libslic3r/PrintConfig.cpp:787
 msgid "Combine infill every"
 msgstr "Об'єднати наповнення кожні"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:692
+#: xs/src/libslic3r/PrintConfig.cpp:789
 msgid ""
 "This feature allows to combine infill and speed up your print by extruding "
 "thicker infill layers while preserving thin perimeters, thus accuracy."
@@ -1990,19 +3115,19 @@ msgstr ""
 "Ця функція дозволяє поєднувати наповнення та прискорити друк, екструдуючи "
 "більш товсті шари наповнення, зберігаючи тонкі периметри, а отже, і точністю."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:696
+#: xs/src/libslic3r/PrintConfig.cpp:793
 msgid "Combine infill every n layers"
 msgstr "Об'єднати наповнення кожні n шарів"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:701
+#: xs/src/libslic3r/PrintConfig.cpp:798
 msgid "Infill extruder"
 msgstr "Наповнювач екструдера"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:703
+#: xs/src/libslic3r/PrintConfig.cpp:800
 msgid "The extruder to use when printing infill."
 msgstr "Екструдер, використовуваний під час друку наповнення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:711
+#: xs/src/libslic3r/PrintConfig.cpp:808
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for infill. If "
 "left zero, default extrusion width will be used if set, otherwise 1.125 x "
@@ -2017,11 +3142,11 @@ msgstr ""
 "прискорити наповнення та зміцнити свої деталі. Якщо він виражений у "
 "відсотках (наприклад, 90%), він буде обчислюватися за висотою шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:720
+#: xs/src/libslic3r/PrintConfig.cpp:817
 msgid "Infill before perimeters"
 msgstr "Заповнення перед периметрами"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:721
+#: xs/src/libslic3r/PrintConfig.cpp:818
 msgid ""
 "This option will switch the print order of perimeters and infill, making the "
 "latter first."
@@ -2029,11 +3154,11 @@ msgstr ""
 "За допомогою цього параметра можна буде змінити порядок друку периметрів та "
 "наповнювачів, зробивши останнє першим."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:726
+#: xs/src/libslic3r/PrintConfig.cpp:823
 msgid "Only infill where needed"
 msgstr "Заповнити тільки там, де потрібно"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:728
+#: xs/src/libslic3r/PrintConfig.cpp:825
 msgid ""
 "This option will limit infill to the areas actually needed for supporting "
 "ceilings (it will act as internal support material). If enabled, slows down "
@@ -2043,11 +3168,11 @@ msgstr ""
 "стель (це буде діяти як внутрішній матеріал підтримки). Якщо це ввімкнено, "
 "сповільнюється генерація G-коду через декілька перевірок."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:735
+#: xs/src/libslic3r/PrintConfig.cpp:832
 msgid "Infill/perimeters overlap"
 msgstr "Перекриття наповнення/периметрів"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:737
+#: xs/src/libslic3r/PrintConfig.cpp:834
 msgid ""
 "This setting applies an additional overlap between infill and perimeters for "
 "better bonding. Theoretically this shouldn't be needed, but backlash might "
@@ -2059,17 +3184,25 @@ msgstr ""
 "може спричинити розриви. Якщо він виражений у відсотках (приклад: 15%), його "
 "розраховують за шириною екструзії по периметру."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:748
+#: xs/src/libslic3r/PrintConfig.cpp:845
 msgid "Speed for printing the internal fill. Set to zero for auto."
 msgstr ""
 "Швидкість друку внутрішнього заповнення. Встановити 0 для автоматичного "
 "обчислення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:757
+#: xs/src/libslic3r/PrintConfig.cpp:854
+msgid "Inherits profile"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:855
+msgid "Name of the profile, from which this profile inherits."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:866
 msgid "Interface shells"
 msgstr "Інтерфейсні оболонки"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:758
+#: xs/src/libslic3r/PrintConfig.cpp:867
 msgid ""
 "Force the generation of solid shells between adjacent materials/volumes. "
 "Useful for multi-extruder prints with translucent materials or manual "
@@ -2079,7 +3212,7 @@ msgstr ""
 "Корисно для друку з багатьма екструдерами з напівпрозорими матеріалами або "
 "ручним розчинним матеріалом для підтримки."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:767
+#: xs/src/libslic3r/PrintConfig.cpp:876
 msgid ""
 "This custom code is inserted at every layer change, right after the Z move "
 "and before the extruder moves to the first layer point. Note that you can "
@@ -2091,7 +3224,7 @@ msgstr ""
 "Зауважте, що ви можете використовувати змінні-заповнювачі для всіх "
 "параметрів Slic3r, а також [layer_num] і [layer_z]."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:779
+#: xs/src/libslic3r/PrintConfig.cpp:888
 msgid ""
 "This setting controls the height (and thus the total number) of the slices/"
 "layers. Thinner layers give better accuracy but take more time to print."
@@ -2099,16 +3232,69 @@ msgstr ""
 "Цей параметр визначає висоту (і, таким чином, загальну кількість) шарів. "
 "Тонкі шари забезпечують більшу точність, але для друку потрібно більше часу."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:787
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:796
+#: xs/src/libslic3r/PrintConfig.cpp:896
+msgid "Support silent mode"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:897
+msgid "Set silent mode for the G-code flavor"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:919
+#, c-format
+msgid "Maximum feedrate %1%"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:921
+#, c-format
+msgid "Maximum feedrate of the %1% axis"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:928
+#, c-format
+msgid "Maximum acceleration %1%"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:930
+#, c-format
+msgid "Maximum acceleration of the %1% axis"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:937
+#, c-format
+msgid "Maximum jerk %1%"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:939
+#, c-format
+msgid "Maximum jerk of the %1% axis"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:949 xs/src/libslic3r/PrintConfig.cpp:951
+msgid "Minimum feedrate when extruding"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:959 xs/src/libslic3r/PrintConfig.cpp:961
+msgid "Minimum travel feedrate"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:969 xs/src/libslic3r/PrintConfig.cpp:971
+msgid "Maximum acceleration when extruding"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:979 xs/src/libslic3r/PrintConfig.cpp:981
+msgid "Maximum acceleration when retracting"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:988 xs/src/libslic3r/PrintConfig.cpp:997
 msgid "Max"
 msgstr "Максимально"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:788
+#: xs/src/libslic3r/PrintConfig.cpp:989
 msgid "This setting represents the maximum speed of your fan."
 msgstr "Цей параметр відображає максимальну швидкість вашого вентилятора."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:797
+#: xs/src/libslic3r/PrintConfig.cpp:998
 #, no-c-format
 msgid ""
 "This is the highest printable layer height for this extruder, used to cap "
@@ -2122,11 +3308,21 @@ msgstr ""
 "для досягнення розумної міжшарової адгезії. Якщо встановлено 0, висота шару "
 "обмежена 75% діаметра сопла."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:807
+#: xs/src/libslic3r/PrintConfig.cpp:1008
+msgid "Max print height"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1009
+msgid ""
+"Set this to the maximum height that can be reached by your extruder while "
+"printing."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1015
 msgid "Max print speed"
 msgstr "Максимальна швидкість друку"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:808
+#: xs/src/libslic3r/PrintConfig.cpp:1016
 msgid ""
 "When setting other speed settings to 0 Slic3r will autocalculate the optimal "
 "speed in order to keep constant extruder pressure. This experimental setting "
@@ -2137,7 +3333,7 @@ msgstr ""
 "екструдера. Цей експериментальний параметр використовується для встановлення "
 "максимальної швидкості друку, яку ви хочете дозволити."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:818
+#: xs/src/libslic3r/PrintConfig.cpp:1026
 msgid ""
 "This experimental setting is used to set the maximum volumetric speed your "
 "extruder supports."
@@ -2145,12 +3341,11 @@ msgstr ""
 "Цей експериментальний параметр використовується для встановлення "
 "максимальної об'ємної швидкості, яку підтримує екструдер."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:826
+#: xs/src/libslic3r/PrintConfig.cpp:1034
 msgid "Max volumetric slope positive"
 msgstr "Максимальний об'ємний нахил позитивний"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:827
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:838
+#: xs/src/libslic3r/PrintConfig.cpp:1035 xs/src/libslic3r/PrintConfig.cpp:1046
 msgid ""
 "This experimental setting is used to limit the speed of change in extrusion "
 "rate. A value of 1.8 mm³/s² ensures, that a change from the extrusion rate "
@@ -2163,27 +3358,25 @@ msgstr ""
 "швидкість подачі 20 мм/с) до 5,4 мм³/с (подача 60 мм/с) займе принаймні 2 "
 "секунди."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:831
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:842
+#: xs/src/libslic3r/PrintConfig.cpp:1039 xs/src/libslic3r/PrintConfig.cpp:1050
 msgid "mm³/s²"
 msgstr "мм³/с²"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:837
+#: xs/src/libslic3r/PrintConfig.cpp:1045
 msgid "Max volumetric slope negative"
 msgstr "Максимальний об'ємний схил негативний"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:848
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:857
+#: xs/src/libslic3r/PrintConfig.cpp:1056 xs/src/libslic3r/PrintConfig.cpp:1065
 msgid "Min"
 msgstr "Мінімально"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:849
+#: xs/src/libslic3r/PrintConfig.cpp:1057
 msgid "This setting represents the minimum PWM your fan needs to work."
 msgstr ""
 "Цей параметр відповідає мінімальній ШІМ, на якій повинен працювати ваш "
 "вентилятор."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:858
+#: xs/src/libslic3r/PrintConfig.cpp:1066
 msgid ""
 "This is the lowest printable layer height for this extruder and limits the "
 "resolution for variable layer height. Typical values are between 0.05 mm and "
@@ -2193,19 +3386,19 @@ msgstr ""
 "роздільну здатність для висоти змінного шару. Типові значення - від 0,05 мм "
 "до 0,1 мм."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:866
+#: xs/src/libslic3r/PrintConfig.cpp:1074
 msgid "Min print speed"
 msgstr "Мінімальна швидкість друку"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:867
+#: xs/src/libslic3r/PrintConfig.cpp:1075
 msgid "Slic3r will not scale speed down below this speed."
 msgstr "Slic3r не буде масштабувати швидкість нижче цієї швидкості."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:874
-msgid "Minimum extrusion length"
-msgstr "Мінімальна довжина екструзії"
+#: xs/src/libslic3r/PrintConfig.cpp:1082
+msgid "Minimal filament extrusion length"
+msgstr ""
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:875
+#: xs/src/libslic3r/PrintConfig.cpp:1083
 msgid ""
 "Generate no less than the number of skirt loops required to consume the "
 "specified amount of filament on the bottom layer. For multi-extruder "
@@ -2215,11 +3408,11 @@ msgstr ""
 "зазначеної кількості філаменту на нижньому шарі. Для машин із декількома "
 "екструдерами цей мінімум застосовується до кожного екструдера."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:884
+#: xs/src/libslic3r/PrintConfig.cpp:1092
 msgid "Configuration notes"
 msgstr "Примітки до конфігурації"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:885
+#: xs/src/libslic3r/PrintConfig.cpp:1093
 msgid ""
 "You can put here your personal notes. This text will be added to the G-code "
 "header comments."
@@ -2227,20 +3420,20 @@ msgstr ""
 "Ви можете додати тут свої особисті примітки. Цей текст буде додано до "
 "коментарів заголовка G-коду."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:894
+#: xs/src/libslic3r/PrintConfig.cpp:1102
 msgid "Nozzle diameter"
 msgstr "Діаметр сопла"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:895
+#: xs/src/libslic3r/PrintConfig.cpp:1103
 msgid ""
 "This is the diameter of your extruder nozzle (for example: 0.5, 0.35 etc.)"
 msgstr "Це діаметр сопла вашого екструдера (наприклад: 0.5, 0.35 тощо)"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:901
+#: xs/src/libslic3r/PrintConfig.cpp:1109
 msgid "API Key"
 msgstr "Ключ API"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:902
+#: xs/src/libslic3r/PrintConfig.cpp:1110
 msgid ""
 "Slic3r can upload G-code files to OctoPrint. This field should contain the "
 "API Key required for authentication."
@@ -2248,23 +3441,21 @@ msgstr ""
 "Slic3r може завантажувати файли G-коду в OctoPrint. Це поле має містити ключ "
 "API, необхідний для аутентифікації."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:908
-msgid "Host or IP"
-msgstr "Host або IP"
+#: xs/src/libslic3r/PrintConfig.cpp:1123
+msgid "Hostname, IP or URL"
+msgstr ""
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:909
+#: xs/src/libslic3r/PrintConfig.cpp:1124
 msgid ""
 "Slic3r can upload G-code files to OctoPrint. This field should contain the "
-"hostname or IP address of the OctoPrint instance."
+"hostname, IP address or URL of the OctoPrint instance."
 msgstr ""
-"Slic3r може завантажувати файли G-коду в OctoPrint. Це поле повинно містити "
-"ім'я хоста або IP-адресу екземпляру OctoPrint."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:915
+#: xs/src/libslic3r/PrintConfig.cpp:1130
 msgid "Only retract when crossing perimeters"
 msgstr "Перервати тільки у разі перетину периметрів"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:916
+#: xs/src/libslic3r/PrintConfig.cpp:1131
 msgid ""
 "Disables retraction when the travel path does not exceed the upper layer's "
 "perimeters (and thus any ooze will be probably invisible)."
@@ -2272,7 +3463,7 @@ msgstr ""
 "Вимикає переривання, коли шлях не перевищує периметри верхніх шарів (і, "
 "таким чином, будь-який розрядник буде, мабуть, невидимим)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:923
+#: xs/src/libslic3r/PrintConfig.cpp:1138
 msgid ""
 "This option will drop the temperature of the inactive extruders to prevent "
 "oozing. It will enable a tall skirt automatically and move extruders outside "
@@ -2282,11 +3473,11 @@ msgstr ""
 "протіканню. Це дозволить автоматично ввімкнути високий плінтус та "
 "перемістить екструдери за межі такого плінтуса у разі зміни температури."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:930
+#: xs/src/libslic3r/PrintConfig.cpp:1145
 msgid "Output filename format"
 msgstr "Формат вихідного файлу"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:931
+#: xs/src/libslic3r/PrintConfig.cpp:1146
 msgid ""
 "You can use all configuration options as variables inside this template. For "
 "example: [layer_height], [fill_density] etc. You can also use [timestamp], "
@@ -2298,11 +3489,11 @@ msgstr ""
 "можете використовувати [timestamp], [year], [month], [day], [hour], "
 "[minute], [second], [version], [input_filename] ], [input_filename_base]."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:940
+#: xs/src/libslic3r/PrintConfig.cpp:1155
 msgid "Detect bridging perimeters"
 msgstr "Виявлення висячих периметрів"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:942
+#: xs/src/libslic3r/PrintConfig.cpp:1157
 msgid ""
 "Experimental option to adjust flow for overhangs (bridge flow will be used), "
 "to apply bridge speed to them and enable fan."
@@ -2311,14 +3502,34 @@ msgstr ""
 "використано мостовий потік), щоб застосувати до них швидкість мосту та "
 "увімкнути вентилятор."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:948
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:966
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:978
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:988
+#: xs/src/libslic3r/PrintConfig.cpp:1163
+msgid "Filament parking position"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1164
+msgid ""
+"Distance of the extruder tip from the position where the filament is parked "
+"when unloaded. This should match the value in printer firmware. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1172
+msgid "Extra loading distance"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1173
+msgid ""
+"When set to zero, the distance the filament is moved from parking position "
+"during load is exactly the same as it was moved back during unload. When "
+"positive, it is loaded further,  if negative, the loading move is shorter "
+"than unloading. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1181 xs/src/libslic3r/PrintConfig.cpp:1199
+#: xs/src/libslic3r/PrintConfig.cpp:1211 xs/src/libslic3r/PrintConfig.cpp:1221
 msgid "Perimeters"
 msgstr "Периметри"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:949
+#: xs/src/libslic3r/PrintConfig.cpp:1182
 msgid ""
 "This is the acceleration your printer will use for perimeters. A high value "
 "like 9000 usually gives good results if your hardware is up to the job. Set "
@@ -2329,18 +3540,18 @@ msgstr ""
 "забезпечення відповідає завданню. Встановити 0, щоб вимкнути регулятор "
 "прискорення для периметрів."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:957
+#: xs/src/libslic3r/PrintConfig.cpp:1190
 msgid "Perimeter extruder"
 msgstr "Екструдер периметру"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:959
+#: xs/src/libslic3r/PrintConfig.cpp:1192
 msgid ""
 "The extruder to use when printing perimeters and brim. First extruder is 1."
 msgstr ""
 "Екструдер, що використовується при друці периметрів і краю. Перший екструдер "
 "- 1."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:968
+#: xs/src/libslic3r/PrintConfig.cpp:1201
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for perimeters. "
 "You may want to use thinner extrudates to get more accurate surfaces. If "
@@ -2355,14 +3566,14 @@ msgstr ""
 "діаметр сопла. Якщо він виражений у відсотках (наприклад, 200%), він буде "
 "обчислюватися за висотою шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:980
+#: xs/src/libslic3r/PrintConfig.cpp:1213
 msgid ""
 "Speed for perimeters (contours, aka vertical shells). Set to zero for auto."
 msgstr ""
 "Швидкість для периметрів (контури, вертикальні оболонки). Встановити 0 для "
 "автоматичного використання."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:990
+#: xs/src/libslic3r/PrintConfig.cpp:1223
 msgid ""
 "This option sets the number of perimeters to generate for each layer. Note "
 "that Slic3r may increase this number automatically when it detects sloping "
@@ -2374,23 +3585,49 @@ msgstr ""
 "які отримують вигоду від більшої кількості периметрів, якщо опція «Додаткові "
 "периметри» увімкнена."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:994
+#: xs/src/libslic3r/PrintConfig.cpp:1227
 msgid "(minimum)"
 msgstr "(мінімум)"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1014
+#: xs/src/libslic3r/PrintConfig.cpp:1247
+msgid "Printer type"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1248
+msgid "Type of the printer."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1252
 msgid "Printer notes"
 msgstr "Примітки принтера"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1015
+#: xs/src/libslic3r/PrintConfig.cpp:1253
 msgid "You can put your notes regarding the printer here."
 msgstr "Тут ви можете помістити свої нотатки щодо принтера."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1029
+#: xs/src/libslic3r/PrintConfig.cpp:1261
+msgid "Printer vendor"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1262
+msgid "Name of the printer vendor."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1266
+msgid "Printer variant"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1267
+msgid ""
+"Name of the printer variant. For example, the printer variants may be "
+"differentiated by a nozzle diameter."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1277
 msgid "Raft layers"
 msgstr "Плоскі шари"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1031
+#: xs/src/libslic3r/PrintConfig.cpp:1279
 msgid ""
 "The object will be raised by this number of layers, and support material "
 "will be generated under it."
@@ -2398,11 +3635,11 @@ msgstr ""
 "Об'єкт буде піднятий цією кількістю шарів, і під ним буде згенерований "
 "матеріал підтримки."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1039
+#: xs/src/libslic3r/PrintConfig.cpp:1287
 msgid "Resolution"
 msgstr "Роздільна здатність"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1040
+#: xs/src/libslic3r/PrintConfig.cpp:1288
 msgid ""
 "Minimum detail resolution, used to simplify the input file for speeding up "
 "the slicing job and reducing memory usage. High-resolution models often "
@@ -2416,20 +3653,20 @@ msgstr ""
 "вимкнути будь-яке спрощення та використовувати повну роздільну здатність від "
 "введення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1050
+#: xs/src/libslic3r/PrintConfig.cpp:1298
 msgid "Minimum travel after retraction"
 msgstr "Мінімальне переміщення після переривання"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1051
+#: xs/src/libslic3r/PrintConfig.cpp:1299
 msgid ""
 "Retraction is not triggered when travel moves are shorter than this length."
 msgstr "Переривання не спрацьовує, коли переміщення коротше за цю довжину."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1057
+#: xs/src/libslic3r/PrintConfig.cpp:1305
 msgid "Retract amount before wipe"
 msgstr "Кількість переривань перед чищенням"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1058
+#: xs/src/libslic3r/PrintConfig.cpp:1306
 msgid ""
 "With bowden extruders, it may be wise to do some amount of quick retract "
 "before doing the wipe movement."
@@ -2437,26 +3674,25 @@ msgstr ""
 "Завдяки екструдерам з бандами, має зміст зробити певну кількість переривань "
 "перед рухами очищення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1065
+#: xs/src/libslic3r/PrintConfig.cpp:1313
 msgid "Retract on layer change"
 msgstr "Переривання на зміну шарів"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1066
+#: xs/src/libslic3r/PrintConfig.cpp:1314
 msgid "This flag enforces a retraction whenever a Z move is done."
 msgstr ""
 "Цей прапор забезпечує переривання кожного разу, коли виконується переміщення "
 "Z."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1071
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1080
+#: xs/src/libslic3r/PrintConfig.cpp:1319 xs/src/libslic3r/PrintConfig.cpp:1328
 msgid "Length"
 msgstr "Довжина"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1072
+#: xs/src/libslic3r/PrintConfig.cpp:1320
 msgid "Retraction Length"
 msgstr "Довжина переривання"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1073
+#: xs/src/libslic3r/PrintConfig.cpp:1321
 msgid ""
 "When retraction is triggered, filament is pulled back by the specified "
 "amount (the length is measured on raw filament, before it enters the "
@@ -2466,16 +3702,15 @@ msgstr ""
 "кількості (довжина вимірюється на сирого філаменту перед тим, як вона "
 "надходить у екструдер)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1075
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1085
+#: xs/src/libslic3r/PrintConfig.cpp:1323 xs/src/libslic3r/PrintConfig.cpp:1333
 msgid "mm (zero to disable)"
 msgstr "мм (0, щоб вимкнути)"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1081
+#: xs/src/libslic3r/PrintConfig.cpp:1329
 msgid "Retraction Length (Toolchange)"
 msgstr "Довжина переривання (зміна інструмента)"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1082
+#: xs/src/libslic3r/PrintConfig.cpp:1330
 msgid ""
 "When retraction is triggered before changing tool, filament is pulled back "
 "by the specified amount (the length is measured on raw filament, before it "
@@ -2485,11 +3720,11 @@ msgstr ""
 "назад до вказаної кількості (довжина вимірюється на сирого філаменту перед "
 "тим, як вона надходить у екструдер)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1090
+#: xs/src/libslic3r/PrintConfig.cpp:1338
 msgid "Lift Z"
 msgstr "Підняти Z"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1091
+#: xs/src/libslic3r/PrintConfig.cpp:1339
 msgid ""
 "If you set this to a positive value, Z is quickly raised every time a "
 "retraction is triggered. When using multiple extruders, only the setting for "
@@ -2499,15 +3734,15 @@ msgstr ""
 "коли спрацьовує переривання. При використанні декількох екструдерів буде "
 "розглянуто налаштування лише першого екструдера."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1099
+#: xs/src/libslic3r/PrintConfig.cpp:1347
 msgid "Above Z"
 msgstr "Вище Z"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1100
+#: xs/src/libslic3r/PrintConfig.cpp:1348
 msgid "Only lift Z above"
 msgstr "Тільки піднімати Z"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1101
+#: xs/src/libslic3r/PrintConfig.cpp:1349
 msgid ""
 "If you set this to a positive value, Z lift will only take place above the "
 "specified absolute Z. You can tune this setting for skipping lift on the "
@@ -2517,15 +3752,15 @@ msgstr ""
 "вказаним абсолютним Z. Ви можете налаштувати цей параметр так, що підняття "
 "буде пропускатися на перших шарах."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1108
+#: xs/src/libslic3r/PrintConfig.cpp:1356
 msgid "Below Z"
 msgstr "Нижче Z"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1109
+#: xs/src/libslic3r/PrintConfig.cpp:1357
 msgid "Only lift Z below"
 msgstr "Тільки опускати Z"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1110
+#: xs/src/libslic3r/PrintConfig.cpp:1358
 msgid ""
 "If you set this to a positive value, Z lift will only take place below the "
 "specified absolute Z. You can tune this setting for limiting lift to the "
@@ -2535,12 +3770,11 @@ msgstr ""
 "вказаного абсолютного Z. Ви можете налаштувати цей параметр так, що підняття "
 "буде обмежене на перших шарах."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1118
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1126
+#: xs/src/libslic3r/PrintConfig.cpp:1366 xs/src/libslic3r/PrintConfig.cpp:1374
 msgid "Extra length on restart"
 msgstr "Додаткова довжина при перезапуску"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1119
+#: xs/src/libslic3r/PrintConfig.cpp:1367
 msgid ""
 "When the retraction is compensated after the travel move, the extruder will "
 "push this additional amount of filament. This setting is rarely needed."
@@ -2548,7 +3782,7 @@ msgstr ""
 "Коли переривання компенсується після руху переміщення, екструдер буде "
 "проштовхувати цю додаткову кількість філамента. Цей параметр рідко потрібний."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1127
+#: xs/src/libslic3r/PrintConfig.cpp:1375
 msgid ""
 "When the retraction is compensated after changing tool, the extruder will "
 "push this additional amount of filament."
@@ -2556,21 +3790,19 @@ msgstr ""
 "Коли переривання компенсується після зміни інструмента, екструдер буде "
 "проштовхувати цю додаткову кількість філамента."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1134
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1135
+#: xs/src/libslic3r/PrintConfig.cpp:1382 xs/src/libslic3r/PrintConfig.cpp:1383
 msgid "Retraction Speed"
 msgstr "Швидкість переривання"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1136
+#: xs/src/libslic3r/PrintConfig.cpp:1384
 msgid "The speed for retractions (it only applies to the extruder motor)."
 msgstr "Швидкість переривання (це стосується лише двигуна екструдера)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1142
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1143
+#: xs/src/libslic3r/PrintConfig.cpp:1390 xs/src/libslic3r/PrintConfig.cpp:1391
 msgid "Deretraction Speed"
 msgstr "Швидкість після-переривання"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1144
+#: xs/src/libslic3r/PrintConfig.cpp:1392
 msgid ""
 "The speed for loading of a filament into extruder after retraction (it only "
 "applies to the extruder motor). If left to zero, the retraction speed is "
@@ -2580,55 +3812,71 @@ msgstr ""
 "лише двигуна екструдера ). Якщо залишити 0, використовується швидкість "
 "переривання ."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1151
+#: xs/src/libslic3r/PrintConfig.cpp:1399
 msgid "Seam position"
 msgstr "Позиція шва"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1153
+#: xs/src/libslic3r/PrintConfig.cpp:1401
 msgid "Position of perimeters starting points."
 msgstr "Позиція стартових точок периметра."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1169
+#: xs/src/libslic3r/PrintConfig.cpp:1408
+msgid "Random"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1409
+msgid "Nearest"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1410
+msgid "Aligned"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1411 lib/Slic3r/GUI/MainFrame.pm:330
+msgid "Rear"
+msgstr "Ззаду"
+
+#: xs/src/libslic3r/PrintConfig.cpp:1417
 msgid "Direction"
 msgstr "Напрямок"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1171
+#: xs/src/libslic3r/PrintConfig.cpp:1419
 msgid "Preferred direction of the seam"
 msgstr "Бажаний напрямок шва"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1172
+#: xs/src/libslic3r/PrintConfig.cpp:1420
 msgid "Seam preferred direction"
 msgstr "Бажаний напрямок шва"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1180
+#: xs/src/libslic3r/PrintConfig.cpp:1428
 msgid "Jitter"
 msgstr "Джиттер"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1182
+#: xs/src/libslic3r/PrintConfig.cpp:1430
 msgid "Seam preferred direction jitter"
 msgstr "Бажаний напрямок шва джитера"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1183
+#: xs/src/libslic3r/PrintConfig.cpp:1431
 msgid "Preferred direction of the seam - jitter"
 msgstr "Бажаний напрямок шва - джитера"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1194
+#: xs/src/libslic3r/PrintConfig.cpp:1442
 msgid "USB/serial port for printer connection."
 msgstr "USB / послідовний порт для підключення принтера."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1202
+#: xs/src/libslic3r/PrintConfig.cpp:1450
 msgid "Serial port speed"
 msgstr "Швидкість послідовного порту"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1203
+#: xs/src/libslic3r/PrintConfig.cpp:1451
 msgid "Speed (baud) of USB/serial port for printer connection."
 msgstr "Швидкість (бод) USB / послідовного порту для підключення принтера."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1212
+#: xs/src/libslic3r/PrintConfig.cpp:1460
 msgid "Distance from object"
 msgstr "Відстань від об'єкту"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1213
+#: xs/src/libslic3r/PrintConfig.cpp:1461
 msgid ""
 "Distance between skirt and object(s). Set this to zero to attach the skirt "
 "to the object(s) and get a brim for better adhesion."
@@ -2636,11 +3884,11 @@ msgstr ""
 "Відстань між плінтусом та об'єктом (-ами). Установіть 0, щоб прикріпити "
 "плінтус до об'єкта (-ів) і отримати край для кращої адгезії."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1221
+#: xs/src/libslic3r/PrintConfig.cpp:1469
 msgid "Skirt height"
 msgstr "Висота плінтусу"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1222
+#: xs/src/libslic3r/PrintConfig.cpp:1470
 msgid ""
 "Height of skirt expressed in layers. Set this to a tall value to use skirt "
 "as a shield against drafts."
@@ -2648,15 +3896,15 @@ msgstr ""
 "Висота плінтусу виражена в шарах. Встановіть це значення на високе, щоб "
 "використовувати плінтус як щит проти протягів."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1229
+#: xs/src/libslic3r/PrintConfig.cpp:1477
 msgid "Loops (minimum)"
 msgstr "Петлі (мінімум)"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1230
+#: xs/src/libslic3r/PrintConfig.cpp:1478
 msgid "Skirt Loops"
 msgstr "Петлі плінтусу"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1231
+#: xs/src/libslic3r/PrintConfig.cpp:1479
 msgid ""
 "Number of loops for the skirt. If the Minimum Extrusion Length option is "
 "set, the number of loops might be greater than the one configured here. Set "
@@ -2666,11 +3914,11 @@ msgstr ""
 "довжина екструзії\", кількість петель може бути більшою, ніж налаштована "
 "тут. Установіть 0, щоб повністю вимкнути плінтус."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1239
+#: xs/src/libslic3r/PrintConfig.cpp:1487
 msgid "Slow down if layer print time is below"
 msgstr "Уповільнення, якщо час друку шару нижче"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1240
+#: xs/src/libslic3r/PrintConfig.cpp:1488
 msgid ""
 "If layer print time is estimated below this number of seconds, print moves "
 "speed will be scaled down to extend duration to this value."
@@ -2678,11 +3926,11 @@ msgstr ""
 "Якщо час друку шару оцінюється нижче цієї кількості секунд, швидкість друку "
 "рухів зменшуватиметься, щоб збільшити тривалість до цього значення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1250
+#: xs/src/libslic3r/PrintConfig.cpp:1498
 msgid "Small perimeters"
 msgstr "Маленькі периметри"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1252
+#: xs/src/libslic3r/PrintConfig.cpp:1500
 msgid ""
 "This separate setting will affect the speed of perimeters having radius <= "
 "6.5mm (usually holes). If expressed as percentage (for example: 80%) it will "
@@ -2693,11 +3941,11 @@ msgstr ""
 "вона буде розрахована за наведеним вище параметром швидкості. Встановити 0 "
 "для автоматичного використання."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1262
+#: xs/src/libslic3r/PrintConfig.cpp:1510
 msgid "Solid infill threshold area"
 msgstr "Порогова площа суцільного наповнення"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1264
+#: xs/src/libslic3r/PrintConfig.cpp:1512
 msgid ""
 "Force solid infill for regions having a smaller area than the specified "
 "threshold."
@@ -2705,23 +3953,23 @@ msgstr ""
 "Встановити суцільне заповнення для регіонів, що мають площу, меншу "
 "зазначеного порогу."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1265
+#: xs/src/libslic3r/PrintConfig.cpp:1513
 msgid "mm²"
 msgstr "мм²"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1271
+#: xs/src/libslic3r/PrintConfig.cpp:1519
 msgid "Solid infill extruder"
 msgstr "Екструдер суцільних наповнень"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1273
+#: xs/src/libslic3r/PrintConfig.cpp:1521
 msgid "The extruder to use when printing solid infill."
 msgstr "Екструдер для друку суцільних наповнень."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1279
+#: xs/src/libslic3r/PrintConfig.cpp:1527
 msgid "Solid infill every"
 msgstr "Суцільне наповнення кожні"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1281
+#: xs/src/libslic3r/PrintConfig.cpp:1529
 msgid ""
 "This feature allows to force a solid layer every given number of layers. "
 "Zero to disable. You can set this to any value (for example 9999); Slic3r "
@@ -2733,14 +3981,13 @@ msgstr ""
 "Slic3r автоматично вибере максимально можливу кількість шарів для "
 "комбінування відповідно до діаметра сопла та висоти шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1291
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1301
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:142
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:84
+#: xs/src/libslic3r/PrintConfig.cpp:1539 xs/src/libslic3r/PrintConfig.cpp:1549
+#: xs/src/libslic3r/GCode/PreviewData.cpp:167
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:94
 msgid "Solid infill"
 msgstr "Суцільне наповнення"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1293
+#: xs/src/libslic3r/PrintConfig.cpp:1541
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for infill for "
 "solid surfaces. If left zero, default extrusion width will be used if set, "
@@ -2753,7 +4000,7 @@ msgstr ""
 "діаметр сопла. Якщо він виражений у відсотках (наприклад, 90%), він буде "
 "обчислюватися за висотою шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1303
+#: xs/src/libslic3r/PrintConfig.cpp:1551
 msgid ""
 "Speed for printing solid regions (top/bottom/internal horizontal shells). "
 "This can be expressed as a percentage (for example: 80%) over the default "
@@ -2764,16 +4011,16 @@ msgstr ""
 "швидкості заповнення за замовчуванням. Встановити 0 для автоматичного "
 "використання."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1315
+#: xs/src/libslic3r/PrintConfig.cpp:1563
 msgid "Number of solid layers to generate on top and bottom surfaces."
 msgstr ""
 "Кількість суцільних шарів для генерування на верхній і нижній поверхні."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1322
+#: xs/src/libslic3r/PrintConfig.cpp:1570
 msgid "Spiral vase"
 msgstr "Спіральна ваза"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1323
+#: xs/src/libslic3r/PrintConfig.cpp:1571
 msgid ""
 "This feature will raise Z gradually while printing a single-walled object in "
 "order to remove any visible seam. This option requires a single perimeter, "
@@ -2788,11 +4035,11 @@ msgstr ""
 "яку кількість нижніх суцільних шарів, а також петель плінтусу/краю. Це не "
 "спрацює при друку більше, ніж одного об'єкта."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1332
+#: xs/src/libslic3r/PrintConfig.cpp:1580
 msgid "Temperature variation"
 msgstr "Варіація температури"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1333
+#: xs/src/libslic3r/PrintConfig.cpp:1581
 msgid ""
 "Temperature difference to be applied when an extruder is not active. Enables "
 "a full-height \"sacrificial\" skirt on which the nozzles are periodically "
@@ -2801,7 +4048,7 @@ msgstr ""
 "Відмітка температури, яка застосовується, коли екструдер не активний. Вмикає "
 "\"жертовний\" плінтус на повній висоті, на які періодично очищуються сопла."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1343
+#: xs/src/libslic3r/PrintConfig.cpp:1591
 msgid ""
 "This start procedure is inserted at the beginning, after bed has reached the "
 "target temperature and extruder just started heating, and before extruder "
@@ -2820,7 +4067,7 @@ msgstr ""
 "заповнювачі для всіх параметрів Slic3r, щоб ви могли поставити команду "
 "\"M109 S [first_layer_temperature]\" де завгодно."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1358
+#: xs/src/libslic3r/PrintConfig.cpp:1606
 msgid ""
 "This start procedure is inserted at the beginning, after any printer start "
 "gcode. This is used to override settings for a specific filament. If Slic3r "
@@ -2841,27 +4088,27 @@ msgstr ""
 "де завгодно. Якщо у вас є кілька екструдерів, G-code обробляється в порядку "
 "екструдерів."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1373
+#: xs/src/libslic3r/PrintConfig.cpp:1621
 msgid "Single Extruder Multi Material"
 msgstr "Одиночний екструдер кількох матеріалів"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1374
+#: xs/src/libslic3r/PrintConfig.cpp:1622
 msgid "The printer multiplexes filaments into a single hot end."
 msgstr "Принтер мультиплексує нитки в єдиний гарячий кінець."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1379
+#: xs/src/libslic3r/PrintConfig.cpp:1627
 msgid "Generate support material"
 msgstr "Створити підтримуючий матеріал"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1381
+#: xs/src/libslic3r/PrintConfig.cpp:1629
 msgid "Enable support material generation."
 msgstr "Увімкнути генерацію матеріалів підтримки."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1386
+#: xs/src/libslic3r/PrintConfig.cpp:1634
 msgid "XY separation between an object and its support"
 msgstr "Розподіл XY між об'єктом та його підтримкою"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1388
+#: xs/src/libslic3r/PrintConfig.cpp:1636
 msgid ""
 "XY separation between an object and its support. If expressed as percentage "
 "(for example 50%), it will be calculated over external perimeter width."
@@ -2869,11 +4116,11 @@ msgstr ""
 "Розподіл XY між об'єктом та його підтримкою. Якщо вона виражена у відсотках "
 "(наприклад, 50%), вона буде розрахована за зовнішньою шириною периметру."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1398
+#: xs/src/libslic3r/PrintConfig.cpp:1646
 msgid "Pattern angle"
 msgstr "Кут шаблону"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1400
+#: xs/src/libslic3r/PrintConfig.cpp:1648
 msgid ""
 "Use this setting to rotate the support material pattern on the horizontal "
 "plane."
@@ -2881,11 +4128,7 @@ msgstr ""
 "Використовуйте цей параметр, щоб повернути шаблон підтримуючого матеріалу на "
 "горизонтальній площині."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1408
-msgid "Support on build plate only"
-msgstr "Підтримка тільки на збірній пластині"
-
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1410
+#: xs/src/libslic3r/PrintConfig.cpp:1658
 msgid ""
 "Only create support if it lies on a build plate. Don't create support on a "
 "print."
@@ -2893,11 +4136,11 @@ msgstr ""
 "Створити підтримку лише, для того, що лежить на збірній пластині. Не "
 "створювати підтримку на друк."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1416
+#: xs/src/libslic3r/PrintConfig.cpp:1664
 msgid "Contact Z distance"
 msgstr "Контактна відстань по осі Z"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1418
+#: xs/src/libslic3r/PrintConfig.cpp:1666
 msgid ""
 "The vertical distance between object and support material interface. Setting "
 "this to 0 will also prevent Slic3r from using bridge flow and speed for the "
@@ -2907,11 +4150,19 @@ msgstr ""
 "Встановлення значення 0 також захистить Slic3r від використання потоку "
 "мостів та швидкості для першого шару об'єктну."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1431
+#: xs/src/libslic3r/PrintConfig.cpp:1674
+msgid "soluble"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1675
+msgid "detachable"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1679
 msgid "Enforce support for the first"
 msgstr "Забезпечити підтримку першого(их)"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1433
+#: xs/src/libslic3r/PrintConfig.cpp:1681
 msgid ""
 "Generate support material for the specified number of layers counting from "
 "bottom, regardless of whether normal support material is enabled or not and "
@@ -2924,15 +4175,15 @@ msgstr ""
 "більшої адгезії об'єктів, що мають дуже тонкий або поганий слід на збірній "
 "пластині."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1439
+#: xs/src/libslic3r/PrintConfig.cpp:1687
 msgid "Enforce support for the first n layers"
 msgstr "Забезпечити підтримку перших n шарів"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1444
+#: xs/src/libslic3r/PrintConfig.cpp:1692
 msgid "Support material/raft/skirt extruder"
 msgstr "Підтримуючий матеріал / пліт / плінтус екструдеру"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1446
+#: xs/src/libslic3r/PrintConfig.cpp:1694
 msgid ""
 "The extruder to use when printing support material, raft and skirt (1+, 0 to "
 "use the current extruder to minimize tool changes)."
@@ -2940,7 +4191,7 @@ msgstr ""
 "Екструдер для друку підтримуючого матеріалу, плоту та плінтусу (1+, 0 для "
 "використання поточного екструдера, щоб мінімізувати зміни інструменту)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1455
+#: xs/src/libslic3r/PrintConfig.cpp:1703
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for support "
 "material. If left zero, default extrusion width will be used if set, "
@@ -2953,21 +4204,21 @@ msgstr ""
 "Якщо він виражений у відсотках (наприклад, 90%), він буде обчислюватися за "
 "висотою шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1463
+#: xs/src/libslic3r/PrintConfig.cpp:1711
 msgid "Interface loops"
 msgstr "Інтерфейсні петлі"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1465
+#: xs/src/libslic3r/PrintConfig.cpp:1713
 msgid ""
 "Cover the top contact layer of the supports with loops. Disabled by default."
 msgstr ""
 "Закрити петлями верхній контактний шар підтримки. За замовчанням вимкнено."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1470
+#: xs/src/libslic3r/PrintConfig.cpp:1718
 msgid "Support material/raft interface extruder"
 msgstr "Екструдер інтерфейсу підтримуючого матеріалу / плоту"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1472
+#: xs/src/libslic3r/PrintConfig.cpp:1720
 msgid ""
 "The extruder to use when printing support material interface (1+, 0 to use "
 "the current extruder to minimize tool changes). This affects raft too."
@@ -2976,11 +4227,11 @@ msgstr ""
 "(1+, 0 для використання поточного екструдера, щоб звести до мінімуму зміни "
 "інструменту). Це також впливає на плот."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1479
+#: xs/src/libslic3r/PrintConfig.cpp:1727
 msgid "Interface layers"
 msgstr "Інтерфейсні шари"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1481
+#: xs/src/libslic3r/PrintConfig.cpp:1729
 msgid ""
 "Number of interface layers to insert between the object(s) and support "
 "material."
@@ -2988,23 +4239,23 @@ msgstr ""
 "Кількість шарів інтерфейсу для вставки між об'єктом(ами) та підтримуючим "
 "матеріалом."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1488
+#: xs/src/libslic3r/PrintConfig.cpp:1736
 msgid "Interface pattern spacing"
 msgstr "Відстань між шаблонами інтерфейсу"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1490
+#: xs/src/libslic3r/PrintConfig.cpp:1738
 msgid "Spacing between interface lines. Set zero to get a solid interface."
 msgstr ""
 "Відстань між інтерфейсними лініями. Встановити 0, щоб отримати надійний "
 "інтерфейс."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1497
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:148
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:90
+#: xs/src/libslic3r/PrintConfig.cpp:1745
+#: xs/src/libslic3r/GCode/PreviewData.cpp:173
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:100
 msgid "Support material interface"
 msgstr "Інтерфейс підтримуючого матеріалу"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1499
+#: xs/src/libslic3r/PrintConfig.cpp:1747
 msgid ""
 "Speed for printing support material interface layers. If expressed as "
 "percentage (for example 50%) it will be calculated over support material "
@@ -3014,31 +4265,35 @@ msgstr ""
 "виражена у відсотках (наприклад, 50%), вона буде розрахована за швидкістю "
 "матеріалу підтримки."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1508
+#: xs/src/libslic3r/PrintConfig.cpp:1756
 msgid "Pattern"
 msgstr "Шаблон"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1510
+#: xs/src/libslic3r/PrintConfig.cpp:1758
 msgid "Pattern used to generate support material."
 msgstr "Шаблон, що використовується для створення матеріалу підтримки."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1524
+#: xs/src/libslic3r/PrintConfig.cpp:1765
+msgid "Rectilinear grid"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1770
 msgid "Pattern spacing"
 msgstr "Відстань між шаблонами"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1526
+#: xs/src/libslic3r/PrintConfig.cpp:1772
 msgid "Spacing between support material lines."
 msgstr "Відстань між лініями підтримуючого матеріалу."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1535
+#: xs/src/libslic3r/PrintConfig.cpp:1781
 msgid "Speed for printing support material."
 msgstr "Швидкість друку підтримуючого матеріалу."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1542
+#: xs/src/libslic3r/PrintConfig.cpp:1788
 msgid "Synchronize with object layers"
 msgstr "Синхронізувати з шарами об'єкту"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1544
+#: xs/src/libslic3r/PrintConfig.cpp:1790
 msgid ""
 "Synchronize support layers with the object print layers. This is useful with "
 "multi-material printers, where the extruder switch is expensive."
@@ -3047,11 +4302,11 @@ msgstr ""
 "використовувати з багато-матеріальними принтерами, де перемикання "
 "екструдерів -затратна процедура."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1550
+#: xs/src/libslic3r/PrintConfig.cpp:1796
 msgid "Overhang threshold"
 msgstr "Порог нависання"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1552
+#: xs/src/libslic3r/PrintConfig.cpp:1798
 msgid ""
 "Support material will not be generated for overhangs whose slope angle (90° "
 "= vertical) is above the given threshold. In other words, this value "
@@ -3065,11 +4320,11 @@ msgstr ""
 "площини), який ви можете надрукувати без підтримуючого матеріалу. Встановити "
 "0 для автоматичного визначення (рекомендовано)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1564
+#: xs/src/libslic3r/PrintConfig.cpp:1810
 msgid "With sheath around the support"
 msgstr "З оболонкою навколо підтримки"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1566
+#: xs/src/libslic3r/PrintConfig.cpp:1812
 msgid ""
 "Add a sheath (a single perimeter line) around the base support. This makes "
 "the support more reliable, but also more difficult to remove."
@@ -3077,7 +4332,7 @@ msgstr ""
 "Додати оболонку (одну лінію периметра) навколо базової підтримки. Це робить "
 "підтримку більш надійною, але її важче видалити."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1573
+#: xs/src/libslic3r/PrintConfig.cpp:1819
 msgid ""
 "Extruder temperature for layers after the first one. Set this to zero to "
 "disable temperature control commands in the output."
@@ -3085,15 +4340,15 @@ msgstr ""
 "Температура екструдеру для шарів після першого. Установіть 0, щоб вимкнути "
 "команди керування температурою на виході."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1576
+#: xs/src/libslic3r/PrintConfig.cpp:1822
 msgid "Temperature"
 msgstr "Температура"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1582
+#: xs/src/libslic3r/PrintConfig.cpp:1828
 msgid "Detect thin walls"
 msgstr "Виявлення тонких стін"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1584
+#: xs/src/libslic3r/PrintConfig.cpp:1830
 msgid ""
 "Detect single-width walls (parts where two extrusions don't fit and we need "
 "to collapse them into a single trace)."
@@ -3101,11 +4356,11 @@ msgstr ""
 "Визначення одношарової стінки (частини, де два екструзії не підходять, і нам "
 "потрібно згорнути їх у єдиний слід)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1590
+#: xs/src/libslic3r/PrintConfig.cpp:1836
 msgid "Threads"
 msgstr "Нитки"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1591
+#: xs/src/libslic3r/PrintConfig.cpp:1837
 msgid ""
 "Threads are used to parallelize long-running tasks. Optimal threads number "
 "is slightly above the number of available cores/processors."
@@ -3113,7 +4368,7 @@ msgstr ""
 "Нитки використовуються для паралелізації довготривалих завдань. Оптимальна "
 "кількість ниток трохи перевищує кількість доступних ядер / процесорів."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1603
+#: xs/src/libslic3r/PrintConfig.cpp:1849
 msgid ""
 "This custom code is inserted right before every extruder change. Note that "
 "you can use placeholder variables for all Slic3r settings as well as "
@@ -3123,14 +4378,13 @@ msgstr ""
 "екструдера. Зверніть увагу, що ви можете використовувати змінні-заповнювачі "
 "для всіх параметрів Slic3r, а також [previous_extruder] і [next_extruder]."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1613
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1624
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:143
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:85
+#: xs/src/libslic3r/PrintConfig.cpp:1859 xs/src/libslic3r/PrintConfig.cpp:1870
+#: xs/src/libslic3r/GCode/PreviewData.cpp:168
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:95
 msgid "Top solid infill"
 msgstr "Верхнє суцільне наповнення"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1615
+#: xs/src/libslic3r/PrintConfig.cpp:1861
 msgid ""
 "Set this to a non-zero value to set a manual extrusion width for infill for "
 "top surfaces. You may want to use thinner extrudates to fill all narrow "
@@ -3146,7 +4400,7 @@ msgstr ""
 "виражена у відсотках (наприклад, 90%), вона буде обчислюватися за висотою "
 "шару."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1626
+#: xs/src/libslic3r/PrintConfig.cpp:1872
 msgid ""
 "Speed for printing top solid layers (it only applies to the uppermost "
 "external layers and not to their internal solid layers). You may want to "
@@ -3160,33 +4414,31 @@ msgstr ""
 "відсотком (наприклад, 80%) звищення швидкості щільного наповнення . "
 "Встановити 0 для автоматичного обчислення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1638
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:369
+#: xs/src/libslic3r/PrintConfig.cpp:1884 lib/Slic3r/GUI/MainFrame.pm:327
 msgid "Top"
 msgstr "Зверху"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1640
+#: xs/src/libslic3r/PrintConfig.cpp:1886
 msgid "Number of solid layers to generate on top surfaces."
 msgstr "Кількість суцільних шарів, генерованих на верхніх поверхнях."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1642
+#: xs/src/libslic3r/PrintConfig.cpp:1888
 msgid "Top solid layers"
 msgstr "Верхні суцільні шари"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1647
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:95
+#: xs/src/libslic3r/PrintConfig.cpp:1893 lib/Slic3r/GUI/Plater/3DPreview.pm:105
 msgid "Travel"
 msgstr "Пересування"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1648
+#: xs/src/libslic3r/PrintConfig.cpp:1894
 msgid "Speed for travel moves (jumps between distant extrusion points)."
 msgstr "Швидкість рухів пересування (стрибки між далекими точками екструзії)."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1656
+#: xs/src/libslic3r/PrintConfig.cpp:1902
 msgid "Use firmware retraction"
 msgstr "Використовувати відмову прошивки"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1657
+#: xs/src/libslic3r/PrintConfig.cpp:1903
 msgid ""
 "This experimental setting uses G10 and G11 commands to have the firmware "
 "handle the retraction. This is only supported in recent Marlin."
@@ -3194,11 +4446,11 @@ msgstr ""
 "Цей експериментальний параметр використовує команди G10 і G11 для обробки "
 "відмови прошивки. Останнім часом це підтримується лише Marlin-ом."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1663
+#: xs/src/libslic3r/PrintConfig.cpp:1909
 msgid "Use relative E distances"
 msgstr "Використовувати відносні E відстані"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1664
+#: xs/src/libslic3r/PrintConfig.cpp:1910
 msgid ""
 "If your firmware requires relative E values, check this, otherwise leave it "
 "unchecked. Most firmwares use absolute values."
@@ -3206,11 +4458,11 @@ msgstr ""
 "Якщо ваша прошивка потребує відносне значення E, зазначте це, інакше залиште "
 "його незазначеним. Більшість прошивок використовують абсолютні значення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1670
+#: xs/src/libslic3r/PrintConfig.cpp:1916
 msgid "Use volumetric E"
 msgstr "Використовувати об'ємний Е"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1671
+#: xs/src/libslic3r/PrintConfig.cpp:1917
 msgid ""
 "This experimental setting uses outputs the E values in cubic millimeters "
 "instead of linear millimeters. If your firmware doesn't already know "
@@ -3226,11 +4478,11 @@ msgstr ""
 "режим і використовувати діаметр нитки, пов'язаний з вибраною ниткою в "
 "Slic3r. Останнім часом це підтримується лише Marlin-ом."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1681
+#: xs/src/libslic3r/PrintConfig.cpp:1927
 msgid "Enable variable layer height feature"
 msgstr "Увімкнути функцію шарів змінної висоти"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1682
+#: xs/src/libslic3r/PrintConfig.cpp:1928
 msgid ""
 "Some printers or printer setups may have difficulties printing with a "
 "variable layer height. Enabled by default."
@@ -3238,11 +4490,11 @@ msgstr ""
 "Деякі принтери або налаштування принтера можуть мати труднощі з друкуванням "
 "шарів змінної висоти. Увімкнено за умовчанням."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1688
+#: xs/src/libslic3r/PrintConfig.cpp:1934
 msgid "Wipe while retracting"
 msgstr "Вичіщувати при відмові"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1689
+#: xs/src/libslic3r/PrintConfig.cpp:1935
 msgid ""
 "This flag will move the nozzle while retracting to minimize the possible "
 "blob on leaky extruders."
@@ -3250,7 +4502,7 @@ msgstr ""
 "Цей прапорець перемістить сопло під час відмови, щоб мінімізувати можливість "
 "утворення краплі на витікаючих екструдерах."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1696
+#: xs/src/libslic3r/PrintConfig.cpp:1942
 msgid ""
 "Multi material printers may need to prime or purge extruders on tool "
 "changes. Extrude the excess material into the wipe tower."
@@ -3259,50 +4511,98 @@ msgstr ""
 "екструдерів при зміні інструмента. Екструдуйте надлишок матеріалу до "
 "вичищуючої вежі."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1702
+#: xs/src/libslic3r/PrintConfig.cpp:1948
+msgid "Purging volumes - load/unload volumes"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1949
+msgid ""
+"This vector saves required volumes to change from/to each tool used on the "
+"wipe tower. These values are used to simplify creation of the full purging "
+"volumes below. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1956
+msgid "Purging volumes - matrix"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1957
+msgid ""
+"This matrix describes volumes (in cubic milimetres) required to purge the "
+"new filament on the wipe tower for any given pair of tools. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1967
 msgid "Position X"
 msgstr "Позиція X"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1703
+#: xs/src/libslic3r/PrintConfig.cpp:1968
 msgid "X coordinate of the left front corner of a wipe tower"
 msgstr "X координата лівого переднього кута вичищуючої вежі"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1709
+#: xs/src/libslic3r/PrintConfig.cpp:1974
 msgid "Position Y"
 msgstr "Позиція Y"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1710
+#: xs/src/libslic3r/PrintConfig.cpp:1975
 msgid "Y coordinate of the left front corner of a wipe tower"
 msgstr "Y координата лівого переднього кута вичищуючої вежі"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1716
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:70
+#: xs/src/libslic3r/PrintConfig.cpp:1981 lib/Slic3r/GUI/Plater/3DPreview.pm:76
 msgid "Width"
 msgstr "Ширина"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1717
+#: xs/src/libslic3r/PrintConfig.cpp:1982
 msgid "Width of a wipe tower"
 msgstr "Ширина вичищуючої вежі"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1723
-msgid "Per color change depth"
-msgstr "Змінити глибину за кольором"
-
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1724
-msgid ""
-"Depth of a wipe color per color change. For N colors, there will be maximum "
-"(N-1) tool switches performed, therefore the total depth of the wipe tower "
-"will be (N-1) times this value."
+#: xs/src/libslic3r/PrintConfig.cpp:1988
+msgid "Wipe tower rotation angle"
 msgstr ""
-"Глибина вичищення кольору для кожної зміни кольору. Для N кольорів буде "
-"виконано максимум (N-1) інструментальних перемикачів, тому загальна глибина "
-"вичищуючої вежі буде (N-1) разів до цього значення."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1732
+#: xs/src/libslic3r/PrintConfig.cpp:1989
+msgid "Wipe tower rotation angle with respect to x-axis "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1990
+msgid "degrees"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1996
+msgid "Purging into infill"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:1997
+msgid ""
+"Wiping after toolchange will be preferentially done inside infills. This "
+"lowers the amount of waste but may result in longer print time  due to "
+"additional travel moves."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:2005
+msgid "Purging into objects"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:2006
+msgid ""
+"Objects will be used to wipe the nozzle after a toolchange to save material "
+"that would otherwise end up in the wipe tower and decrease print time. "
+"Colours of the objects will be mixed as a result."
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:2013
+msgid "Maximal bridging distance"
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:2014
+msgid "Maximal distance between supports on sparse infill sections. "
+msgstr ""
+
+#: xs/src/libslic3r/PrintConfig.cpp:2020
 msgid "XY Size Compensation"
 msgstr "Зрівноваження розміру за XY"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1734
+#: xs/src/libslic3r/PrintConfig.cpp:2022
 msgid ""
 "The object will be grown/shrunk in the XY plane by the configured value "
 "(negative = inwards, positive = outwards). This might be useful for fine-"
@@ -3312,11 +4612,11 @@ msgstr ""
 "(негативний - внутрішній, позитивний - ззовнішній). Це може бути корисним "
 "для точного налаштування розмірів отворів."
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1742
+#: xs/src/libslic3r/PrintConfig.cpp:2030
 msgid "Z offset"
 msgstr "Зміщення Z"
 
-#: C:\src\Slic3r\xs\src\libslic3r\PrintConfig.cpp:1743
+#: xs/src/libslic3r/PrintConfig.cpp:2031
 msgid ""
 "This value will be added (or subtracted) from all the Z coordinates in the "
 "output G-code. It is used to compensate for bad Z endstop position: for "
@@ -3328,678 +4628,608 @@ msgstr ""
 "наприклад, якщо ваш кінцевий нуль фактично залишає сопло на 0,3 мм від "
 "полотна друку, встановіть його на значення -0,3 (або виправте ваш endstop)."
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:137
-msgid "None"
-msgstr "Жодне"
-
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:138
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:80
+#: xs/src/libslic3r/GCode/PreviewData.cpp:163
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:90
 msgid "Perimeter"
 msgstr "Периметр"
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:139
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:81
+#: xs/src/libslic3r/GCode/PreviewData.cpp:164
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:91
 msgid "External perimeter"
 msgstr "Зовнішній периметр"
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:140
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:82
+#: xs/src/libslic3r/GCode/PreviewData.cpp:165
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:92
 msgid "Overhang perimeter"
 msgstr "Нависаючий периметр"
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:141
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:83
+#: xs/src/libslic3r/GCode/PreviewData.cpp:166
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:93
 msgid "Internal infill"
 msgstr "Внутрішнє наповнення"
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:144
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:86
+#: xs/src/libslic3r/GCode/PreviewData.cpp:169
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:96
 msgid "Bridge infill"
 msgstr "Мостове наповнення"
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:151
+#: xs/src/libslic3r/GCode/PreviewData.cpp:176
 msgid "Mixed"
 msgstr ""
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:330
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:68
+#: xs/src/libslic3r/GCode/PreviewData.cpp:367
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:74
 msgid "Feature type"
 msgstr "Тип ознаки"
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:332
+#: xs/src/libslic3r/GCode/PreviewData.cpp:369
 msgid "Height (mm)"
 msgstr "Висота (мм)"
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:334
+#: xs/src/libslic3r/GCode/PreviewData.cpp:371
 msgid "Width (mm)"
 msgstr "Ширина (мм)"
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:336
+#: xs/src/libslic3r/GCode/PreviewData.cpp:373
 msgid "Speed (mm/s)"
 msgstr "Швидкість (мм/с)"
 
-#: c:\src\Slic3r\xs\src\libslic3r\GCode\PreviewData.cpp:338
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:72
+#: xs/src/libslic3r/GCode/PreviewData.cpp:375
+msgid "Volumetric flow rate (mm3/s)"
+msgstr ""
+
+#: xs/src/libslic3r/GCode/PreviewData.cpp:377
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:79
 msgid "Tool"
 msgstr "Інструмент"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI.pm:286
+#: lib/Slic3r/GUI.pm:308
 msgid "Choose one or more files (STL/OBJ/AMF/3MF/PRUSA):"
 msgstr "Виберіть один чи кілька файлів (STL/OBJ/AMF/PRUSA):"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:66
+#: lib/Slic3r/GUI/MainFrame.pm:66
 msgid "Version "
 msgstr "Версія "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:66
+#: lib/Slic3r/GUI/MainFrame.pm:66
 msgid ""
 " - Remember to check for updates at http://github.com/prusa3d/slic3r/releases"
 msgstr " - Пам'ятайте оновлювати з http://github.com/prusa3d/slic3r/releases"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:118
+#: lib/Slic3r/GUI/MainFrame.pm:135
 msgid "Plater"
 msgstr "Платер"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:120
+#: lib/Slic3r/GUI/MainFrame.pm:137
 msgid "Controller"
 msgstr "Контролер"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:192
-msgid "No Bonjour device found"
-msgstr "Немає пристрою Bonjour"
+#: lib/Slic3r/GUI/MainFrame.pm:215
+msgid "Open STL/OBJ/AMF/3MF…\tCtrl+O"
+msgstr ""
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:192
-msgid "Device Browser"
-msgstr "Браузер(список) пристроїв"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:211
-msgid "Connection to OctoPrint works correctly."
-msgstr "Підключення до OctoPrint працює правильно."
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:214
-msgid "I wasn't able to connect to OctoPrint ("
-msgstr "Не можливо підключитися до OctoPrint ("
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:215
-msgid "). Check hostname and OctoPrint version (at least 1.1.0 is required)."
-msgstr ") Перевірте версію хоста та OctoPrint (принаймні 1.1.0 - обов'язкова)."
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:251
-msgid "Open STL/OBJ/AMF…\tCtrl+O"
-msgstr "Відкрити STL/OBJ/AMF…\tCtrl+O"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:251
+#: lib/Slic3r/GUI/MainFrame.pm:215
 msgid "Open a model"
 msgstr "Відкрити модель"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:254
+#: lib/Slic3r/GUI/MainFrame.pm:218
 msgid "&Load Config…\tCtrl+L"
 msgstr "Завантажити конфігурацію... \tCtrl+L"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:254
+#: lib/Slic3r/GUI/MainFrame.pm:218
 msgid "Load exported configuration file"
 msgstr "Завантажити експортований файл конфігурації"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:257
+#: lib/Slic3r/GUI/MainFrame.pm:221
 msgid "&Export Config…\tCtrl+E"
 msgstr "Експортувати конфігурацію...\tCtrl+E"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:257
+#: lib/Slic3r/GUI/MainFrame.pm:221
 msgid "Export current configuration to file"
 msgstr "Експортувати поточну конфігурацію в файл"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:260
+#: lib/Slic3r/GUI/MainFrame.pm:224
 msgid "&Load Config Bundle…"
 msgstr "Завантажити пакет конфігурації…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:260
+#: lib/Slic3r/GUI/MainFrame.pm:224
 msgid "Load presets from a bundle"
 msgstr "Завантажити налаштування з пакету"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:263
+#: lib/Slic3r/GUI/MainFrame.pm:227
 msgid "&Export Config Bundle…"
 msgstr "Експортувати пакет налаштування…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:263
+#: lib/Slic3r/GUI/MainFrame.pm:227
 msgid "Export all presets to file"
 msgstr "Експортувати всі налаштування у файл"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:268
+#: lib/Slic3r/GUI/MainFrame.pm:232
 msgid "Q&uick Slice…\tCtrl+U"
 msgstr "Швидке нарізання…\tCtrl+U"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:268
+#: lib/Slic3r/GUI/MainFrame.pm:232
 msgid "Slice a file into a G-code"
 msgstr "Нарізати файл у G-код"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:274
+#: lib/Slic3r/GUI/MainFrame.pm:238
 msgid "Quick Slice and Save &As…\tCtrl+Alt+U"
 msgstr "Швидко нарізати та зберегти як…\tCtrl+Alt+U"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:274
+#: lib/Slic3r/GUI/MainFrame.pm:238
 msgid "Slice a file into a G-code, save as"
 msgstr "Нарізати файл у G-код, зберегти як"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:280
+#: lib/Slic3r/GUI/MainFrame.pm:244
 msgid "&Repeat Last Quick Slice\tCtrl+Shift+U"
 msgstr "Повторити останнє швидке нарізання\tCtrl+Shift+U"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:280
+#: lib/Slic3r/GUI/MainFrame.pm:244
 msgid "Repeat last quick slice"
 msgstr "Повторити останнє швидке нарізання"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:287
+#: lib/Slic3r/GUI/MainFrame.pm:251
 msgid "Slice to SV&G…\tCtrl+G"
 msgstr "Нарізати в SV&G…\tCtrl+G"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:287
+#: lib/Slic3r/GUI/MainFrame.pm:251
 msgid "Slice file to a multi-layer SVG"
 msgstr "Нарізати файл в багатошаровий SVG"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:291
+#: lib/Slic3r/GUI/MainFrame.pm:255
 msgid "(&Re)Slice Now\tCtrl+S"
 msgstr "(Пере)Нарізати зараз\tCtrl+S"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:291
+#: lib/Slic3r/GUI/MainFrame.pm:255
 msgid "Start new slicing process"
 msgstr "Почати новий процес нарізання"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:294
+#: lib/Slic3r/GUI/MainFrame.pm:258
 msgid "Repair STL file…"
 msgstr "Відновити STL-файл…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:294
+#: lib/Slic3r/GUI/MainFrame.pm:258
 msgid "Automatically repair an STL file"
 msgstr "Автоматично відновити як STL-файл"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:299
-msgid "Preferences…\tCtrl+,"
-msgstr "Преференції…\tCtrl+,"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:299
-msgid "Application preferences"
-msgstr "Преференції застосування"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:304
+#: lib/Slic3r/GUI/MainFrame.pm:262
 msgid "&Quit"
 msgstr "Вихід"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:304
+#: lib/Slic3r/GUI/MainFrame.pm:262
 msgid "Quit Slic3r"
 msgstr "Вийти зі Slic3r"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:314
+#: lib/Slic3r/GUI/MainFrame.pm:272
 msgid "Export G-code..."
 msgstr "Експорт G-code..."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:314
+#: lib/Slic3r/GUI/MainFrame.pm:272
 msgid "Export current plate as G-code"
 msgstr "Експорт поточної пластини як G-код"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:317
+#: lib/Slic3r/GUI/MainFrame.pm:275
 msgid "Export plate as STL..."
 msgstr "Експорт пластини як STL..."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:317
+#: lib/Slic3r/GUI/MainFrame.pm:275
 msgid "Export current plate as STL"
 msgstr "Експорт поточної пластини як STL"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:320
+#: lib/Slic3r/GUI/MainFrame.pm:278
 msgid "Export plate as AMF..."
 msgstr "Експорт пластини як AMF..."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:320
+#: lib/Slic3r/GUI/MainFrame.pm:278
 msgid "Export current plate as AMF"
 msgstr "Експорт поточної пластини як AMF"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:323
+#: lib/Slic3r/GUI/MainFrame.pm:281
 msgid "Export plate as 3MF..."
 msgstr "Експорт пластини як 3MF..."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:323
+#: lib/Slic3r/GUI/MainFrame.pm:281
 msgid "Export current plate as 3MF"
 msgstr "Експорт поточної пластини як 3MF"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:336
+#: lib/Slic3r/GUI/MainFrame.pm:294
 msgid "Select &Plater Tab\tCtrl+1"
 msgstr "Вибрати вкладку Plater\tCtrl+1"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:336
+#: lib/Slic3r/GUI/MainFrame.pm:294
 msgid "Show the plater"
 msgstr "Показати plater"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:342
+#: lib/Slic3r/GUI/MainFrame.pm:300
 msgid "Select &Controller Tab\tCtrl+T"
 msgstr "Вибрати вкладку Контроллер"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:342
+#: lib/Slic3r/GUI/MainFrame.pm:300
 msgid "Show the printer controller"
 msgstr "Показати контролер принтера"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:350
+#: lib/Slic3r/GUI/MainFrame.pm:308
 msgid "Select P&rint Settings Tab\tCtrl+2"
 msgstr "Вибрати вкладку параметрів друку\tCtrl+2"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:350
+#: lib/Slic3r/GUI/MainFrame.pm:308
 msgid "Show the print settings"
 msgstr "Показати параметри друку"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:353
+#: lib/Slic3r/GUI/MainFrame.pm:311
 msgid "Select &Filament Settings Tab\tCtrl+3"
 msgstr "Вибрати вкладку параметрів філаменту\tCtrl+3"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:353
+#: lib/Slic3r/GUI/MainFrame.pm:311
 msgid "Show the filament settings"
 msgstr "Показати параметри філаменту"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:356
+#: lib/Slic3r/GUI/MainFrame.pm:314
 msgid "Select Print&er Settings Tab\tCtrl+4"
 msgstr "Вибрати вкладку параметрів принтеру\tCtrl+4"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:356
+#: lib/Slic3r/GUI/MainFrame.pm:314
 msgid "Show the printer settings"
 msgstr "Показати параметри принтеру"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:368
+#: lib/Slic3r/GUI/MainFrame.pm:326
 msgid "Iso"
 msgstr ""
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:368
+#: lib/Slic3r/GUI/MainFrame.pm:326
 msgid "Iso View"
 msgstr "Вид Iso"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:369
+#: lib/Slic3r/GUI/MainFrame.pm:327
 msgid "Top View"
 msgstr "Вид зверху"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:370
+#: lib/Slic3r/GUI/MainFrame.pm:328
 msgid "Bottom View"
 msgstr "Вид знизу"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:371
+#: lib/Slic3r/GUI/MainFrame.pm:329
 msgid "Front"
 msgstr "Спереду"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:371
+#: lib/Slic3r/GUI/MainFrame.pm:329
 msgid "Front View"
 msgstr "Вид спереду"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:372
-msgid "Rear"
-msgstr "Ззаду"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:372
+#: lib/Slic3r/GUI/MainFrame.pm:330
 msgid "Rear View"
 msgstr "Вид ззаду"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:373
+#: lib/Slic3r/GUI/MainFrame.pm:331
 msgid "Left"
 msgstr "З лівого боку"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:373
+#: lib/Slic3r/GUI/MainFrame.pm:331
 msgid "Left View"
 msgstr "Вид з лівого боку"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:374
+#: lib/Slic3r/GUI/MainFrame.pm:332
 msgid "Right"
 msgstr "З правого боку"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:374
+#: lib/Slic3r/GUI/MainFrame.pm:332
 msgid "Right View"
 msgstr "Вид з правого боку"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:380
-msgid "&Configuration "
-msgstr "Конфігурація "
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:380
-msgid "Run Configuration "
-msgstr "Запустити конфігурацію "
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:385
+#: lib/Slic3r/GUI/MainFrame.pm:338
 msgid "Prusa 3D Drivers"
 msgstr "Драйвери Prusa3D"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:385
+#: lib/Slic3r/GUI/MainFrame.pm:338
 msgid "Open the Prusa3D drivers download page in your browser"
 msgstr "Відкрити сторінку завантаження драйверів Prusa3D у своєму браузері"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:388
+#: lib/Slic3r/GUI/MainFrame.pm:341
 msgid "Prusa Edition Releases"
 msgstr "Випуски(релізи) Prusa Edition"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:388
+#: lib/Slic3r/GUI/MainFrame.pm:341
 msgid "Open the Prusa Edition releases page in your browser"
 msgstr "Відкрити сторінку релізів Prusa Edition у своєму браузері"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:395
+#: lib/Slic3r/GUI/MainFrame.pm:348
 msgid "Slic3r &Website"
 msgstr "Веб-сайт Slic3r"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:395
+#: lib/Slic3r/GUI/MainFrame.pm:348
 msgid "Open the Slic3r website in your browser"
 msgstr "Відкрити сторінку Slic3r у своєму браузері"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:398
+#: lib/Slic3r/GUI/MainFrame.pm:351
 msgid "Slic3r &Manual"
 msgstr "Посібник до Slic3r"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:398
+#: lib/Slic3r/GUI/MainFrame.pm:351
 msgid "Open the Slic3r manual in your browser"
 msgstr "Відкрити сторінку посібнику до Slic3r у своєму браузері"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:402
+#: lib/Slic3r/GUI/MainFrame.pm:355
 msgid "System Info"
 msgstr "Інформація про систему"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:402
+#: lib/Slic3r/GUI/MainFrame.pm:355
 msgid "Show system information"
 msgstr "Показати інформацію про систему"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:405
+#: lib/Slic3r/GUI/MainFrame.pm:358
+msgid "Show &Configuration Folder"
+msgstr ""
+
+#: lib/Slic3r/GUI/MainFrame.pm:358
+msgid "Show user configuration folder (datadir)"
+msgstr ""
+
+#: lib/Slic3r/GUI/MainFrame.pm:361
 msgid "Report an Issue"
 msgstr "Повідомити про проблему"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:405
+#: lib/Slic3r/GUI/MainFrame.pm:361
 msgid "Report an issue on the Slic3r Prusa Edition"
 msgstr "Повідомити про проблему на Slic3r Prusa Edition"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:408
+#: lib/Slic3r/GUI/MainFrame.pm:364
 msgid "&About Slic3r"
 msgstr "Про Slic3r"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:408
+#: lib/Slic3r/GUI/MainFrame.pm:364
 msgid "Show about dialog"
 msgstr "Показати діалог Про Slic3r"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:418
+#: lib/Slic3r/GUI/MainFrame.pm:374
 msgid "&File"
 msgstr "Файл"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:419
+#: lib/Slic3r/GUI/MainFrame.pm:375
 msgid "&Plater"
 msgstr "&Платер"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:420
+#: lib/Slic3r/GUI/MainFrame.pm:376
 msgid "&Object"
 msgstr "&Об'єкт"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:421
+#: lib/Slic3r/GUI/MainFrame.pm:377
 msgid "&Window"
 msgstr "Вікно"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:422
+#: lib/Slic3r/GUI/MainFrame.pm:378
 msgid "&View"
 msgstr "Вид"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:426
+#: lib/Slic3r/GUI/MainFrame.pm:381
 msgid "&Help"
 msgstr "Доромога"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:457
+#: lib/Slic3r/GUI/MainFrame.pm:412
 msgid "Choose a file to slice (STL/OBJ/AMF/3MF/PRUSA):"
 msgstr "Вибрати файл для нарізання (STL/OBJ/AMF/3MF/PRUSA):"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:469
+#: lib/Slic3r/GUI/MainFrame.pm:424
 msgid "No previously sliced file."
 msgstr "Немає попередньо нарізаного файлу."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:474
+#: lib/Slic3r/GUI/MainFrame.pm:425 lib/Slic3r/GUI/Plater.pm:1405
+msgid "Error"
+msgstr "Помилка"
+
+#: lib/Slic3r/GUI/MainFrame.pm:429
 msgid "Previously sliced file ("
 msgstr "Попередньо нарізаний файл ("
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:474
+#: lib/Slic3r/GUI/MainFrame.pm:429
 msgid ") not found."
 msgstr ") не знайдено."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:475
+#: lib/Slic3r/GUI/MainFrame.pm:430
 msgid "File Not Found"
 msgstr "Файл не знайдено"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:514
+#: lib/Slic3r/GUI/MainFrame.pm:469
 msgid "SVG"
 msgstr ""
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:514
+#: lib/Slic3r/GUI/MainFrame.pm:469
 msgid "G-code"
 msgstr "G-код"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:514
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1645
+#: lib/Slic3r/GUI/MainFrame.pm:469 lib/Slic3r/GUI/Plater.pm:1795
 msgid " file as:"
 msgstr " файл як:"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:528
+#: lib/Slic3r/GUI/MainFrame.pm:483
 msgid "Slicing…"
 msgstr "Нарізання…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:528
+#: lib/Slic3r/GUI/MainFrame.pm:483
 msgid "Processing "
 msgstr "Обробка "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:548
+#: lib/Slic3r/GUI/MainFrame.pm:503
 msgid " was successfully sliced."
 msgstr " був успішно нарізаний."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:550
+#: lib/Slic3r/GUI/MainFrame.pm:505
 msgid "Slicing Done!"
 msgstr "Нарізання завершено!"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:566
+#: lib/Slic3r/GUI/MainFrame.pm:521
 msgid "Select the STL file to repair:"
 msgstr "Вибрати STL-файл для відновлення:"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:580
+#: lib/Slic3r/GUI/MainFrame.pm:535
 msgid "Save OBJ file (less prone to coordinate errors than STL) as:"
 msgstr "Зберегти OBJ-файл (менш схильний координувати помилки, ніж STL) як:"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:594
+#: lib/Slic3r/GUI/MainFrame.pm:549
 msgid "Your file was repaired."
 msgstr "Ваш файл було відновлено."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:594
+#: lib/Slic3r/GUI/MainFrame.pm:549
 msgid "Repair"
 msgstr "Відновити"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:605
+#: lib/Slic3r/GUI/MainFrame.pm:560
 msgid "Save configuration as:"
 msgstr "Зберегти конфігурацію як:"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:623
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:667
+#: lib/Slic3r/GUI/MainFrame.pm:578 lib/Slic3r/GUI/MainFrame.pm:622
 msgid "Select configuration to load:"
 msgstr "Вибрати конфігурацію для завантаження:"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:646
+#: lib/Slic3r/GUI/MainFrame.pm:601
 msgid "Save presets bundle as:"
 msgstr "Зберегти набір налаштувань як:"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:687
+#: lib/Slic3r/GUI/MainFrame.pm:642
 #, perl-format
 msgid "%d presets successfully imported."
 msgstr "%d налаштувань успішно імпортовано."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:749
-msgid "You have unsaved changes "
-msgstr "У вас є незбережені зміни "
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:749
-msgid ". Discard changes and continue anyway?"
-msgstr ". Відхилити зміни і продовжити в будь-якому випадку?"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\MainFrame.pm:750
-msgid "Unsaved Presets"
-msgstr "Незбереженні налаштування"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:104
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2124
+#: lib/Slic3r/GUI/Plater.pm:164 lib/Slic3r/GUI/Plater.pm:2323
 msgid "3D"
 msgstr ""
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:138
+#: lib/Slic3r/GUI/Plater.pm:206
 msgid "2D"
 msgstr ""
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:157
+#: lib/Slic3r/GUI/Plater.pm:224
 msgid "Layers"
 msgstr "Шари"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:177
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:195
+#: lib/Slic3r/GUI/Plater.pm:250 lib/Slic3r/GUI/Plater.pm:268
 msgid "Add…"
 msgstr "Додати…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:179
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:197
+#: lib/Slic3r/GUI/Plater.pm:252 lib/Slic3r/GUI/Plater.pm:270
 msgid "Delete All"
 msgstr "Видалити все"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:180
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:198
+#: lib/Slic3r/GUI/Plater.pm:253 lib/Slic3r/GUI/Plater.pm:271
 msgid "Arrange"
 msgstr "Організувати"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:182
+#: lib/Slic3r/GUI/Plater.pm:255
 msgid "More"
 msgstr "Більше"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:183
+#: lib/Slic3r/GUI/Plater.pm:256
 msgid "Fewer"
 msgstr "Менше"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:185
+#: lib/Slic3r/GUI/Plater.pm:258
 msgid "45° ccw"
 msgstr "45° пгс"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:186
+#: lib/Slic3r/GUI/Plater.pm:259
 msgid "45° cw"
 msgstr "45° згс"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:187
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:203
+#: lib/Slic3r/GUI/Plater.pm:260 lib/Slic3r/GUI/Plater.pm:276
 msgid "Scale…"
 msgstr "Масштаб…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:188
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:204
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2099
+#: lib/Slic3r/GUI/Plater.pm:261 lib/Slic3r/GUI/Plater.pm:277
+#: lib/Slic3r/GUI/Plater.pm:2293
 msgid "Split"
 msgstr "Розділити"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:189
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:205
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2102
+#: lib/Slic3r/GUI/Plater.pm:262 lib/Slic3r/GUI/Plater.pm:278
+#: lib/Slic3r/GUI/Plater.pm:2296
 msgid "Cut…"
 msgstr "Вирізати…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:191
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:206
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2106
+#: lib/Slic3r/GUI/Plater.pm:264 lib/Slic3r/GUI/Plater.pm:279
+#: lib/Slic3r/GUI/Plater.pm:2300
 msgid "Settings…"
 msgstr "Параметри…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:192
+#: lib/Slic3r/GUI/Plater.pm:265
 msgid "Layer Editing"
 msgstr "Редагування шарів"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:207
+#: lib/Slic3r/GUI/Plater.pm:280
 msgid "Layer editing"
 msgstr "Редагування шарів"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:220
+#: lib/Slic3r/GUI/Plater.pm:303
 msgid "Name"
 msgstr "Ім'я"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:221
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:900
+#: lib/Slic3r/GUI/Plater.pm:304 lib/Slic3r/GUI/Plater.pm:992
 msgid "Copies"
 msgstr "Копії"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:222
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1056
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1061
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2068
+#: lib/Slic3r/GUI/Plater.pm:305 lib/Slic3r/GUI/Plater.pm:1158
+#: lib/Slic3r/GUI/Plater.pm:1163 lib/Slic3r/GUI/Plater.pm:2262
 msgid "Scale"
 msgstr "Масштаб"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:236
+#: lib/Slic3r/GUI/Plater.pm:322
 msgid "Export G-code…"
 msgstr "Експортувати G-код…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:237
+#: lib/Slic3r/GUI/Plater.pm:323
 msgid "Slice now"
 msgstr "Нарізати зараз"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:238
+#: lib/Slic3r/GUI/Plater.pm:324
 msgid "Print…"
 msgstr "Друк…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:239
+#: lib/Slic3r/GUI/Plater.pm:325
 msgid "Send to printer"
 msgstr "Надіслати на принтер"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:240
+#: lib/Slic3r/GUI/Plater.pm:326
 msgid "Export STL…"
 msgstr "Експортувати STL…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:367
+#: lib/Slic3r/GUI/Plater.pm:453
 msgid "Print settings"
 msgstr "Параметри друку"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:369
+#: lib/Slic3r/GUI/Plater.pm:455
 msgid "Printer"
 msgstr "Принтер"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:398
+#: lib/Slic3r/GUI/Plater.pm:488
 msgid "Info"
 msgstr "Інфо"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:409
+#: lib/Slic3r/GUI/Plater.pm:499
 msgid "Volume"
 msgstr "Обсяг"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:410
+#: lib/Slic3r/GUI/Plater.pm:500
 msgid "Facets"
 msgstr "Грані"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:411
+#: lib/Slic3r/GUI/Plater.pm:501
 msgid "Materials"
 msgstr "Матеріали"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:412
+#: lib/Slic3r/GUI/Plater.pm:502
 msgid "Manifold"
 msgstr "Різноманіття"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:438
+#: lib/Slic3r/GUI/Plater.pm:527
 msgid "Sliced Info"
 msgstr "Інформація з нарізання"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:447
-msgid "Used Filament (m)"
-msgstr "Використано філаметну (м)"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:448
-msgid "Used Filament (mm³)"
-msgstr "Використано філаметну (мм³)"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:449
-msgid "Used Filament (g)"
-msgstr "Використано філаметну (г)"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:451
-msgid "Estimated printing time"
-msgstr "Приблизний час друку"
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:629
+#: lib/Slic3r/GUI/Plater.pm:713
 msgid "Loading…"
 msgstr "Завантаження…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:629
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:643
+#: lib/Slic3r/GUI/Plater.pm:713 lib/Slic3r/GUI/Plater.pm:727
 msgid "Processing input file\n"
 msgstr "Обробка вхідного файлу\n"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:663
+#: lib/Slic3r/GUI/Plater.pm:750
 msgid ""
 "This file contains several objects positioned at multiple heights. Instead "
 "of considering them as multiple objects, should I consider\n"
@@ -4009,12 +5239,11 @@ msgstr ""
 "того, щоб розглядати їх як кілька об'єктів, чи потрібно розглянути\n"
 "цей файл як єдиний об'єкт, що має декілька частин?\n"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:666
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:683
+#: lib/Slic3r/GUI/Plater.pm:753 lib/Slic3r/GUI/Plater.pm:770
 msgid "Multi-part object detected"
 msgstr "Виявлено об'єкт, що складається з кількох частин"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:680
+#: lib/Slic3r/GUI/Plater.pm:767
 msgid ""
 "Multiple objects were loaded for a multi-material printer.\n"
 "Instead of considering them as multiple objects, should I consider\n"
@@ -4024,11 +5253,11 @@ msgstr ""
 "Замість того, щоб розглядати їх як кілька об'єктів, чи потрібно розглянути\n"
 "ці файл як єдиний об'єкт, що має декілька частин?\n"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:692
+#: lib/Slic3r/GUI/Plater.pm:779
 msgid "Loaded "
 msgstr "Завантажений "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:744
+#: lib/Slic3r/GUI/Plater.pm:837
 msgid ""
 "Your object appears to be too large, so it was automatically scaled down to "
 "fit your print bed."
@@ -4036,15 +5265,15 @@ msgstr ""
 "Ваш об'єкт видався занадто великим, тому він автоматично зменшився "
 "відповідно до вашої полотна друку."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:745
+#: lib/Slic3r/GUI/Plater.pm:838
 msgid "Object too large?"
 msgstr "Об'єкт занадто великий?"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:900
+#: lib/Slic3r/GUI/Plater.pm:992
 msgid "Enter the number of copies of the selected object:"
 msgstr "Введіть кількість копій обраного об'єкта:"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:927
+#: lib/Slic3r/GUI/Plater.pm:1019
 msgid ""
 "\n"
 "Non-positive value."
@@ -4052,7 +5281,7 @@ msgstr ""
 "\n"
 "Непозитивне значення."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:928
+#: lib/Slic3r/GUI/Plater.pm:1020
 msgid ""
 "\n"
 "Not a numeric value."
@@ -4060,50 +5289,46 @@ msgstr ""
 "\n"
 "Не числове значення."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:929
+#: lib/Slic3r/GUI/Plater.pm:1021
 msgid "Slic3r Error"
 msgstr "Помилка Slic3r"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:950
+#: lib/Slic3r/GUI/Plater.pm:1042
 msgid "Enter the rotation angle:"
 msgstr "Введіть кут повороту:"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:950
+#: lib/Slic3r/GUI/Plater.pm:1042
 msgid "Rotate around "
 msgstr "Обертати навколо "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:950
+#: lib/Slic3r/GUI/Plater.pm:1042
 msgid "Invalid rotation angle entered"
 msgstr "Введено неправильний кут повороту"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1030
+#: lib/Slic3r/GUI/Plater.pm:1132
 #, perl-format
 msgid "Enter the new size for the selected object (print bed: %smm):"
 msgstr "Введіть новий розмір для обраного об'єкта (полотна друку: %smm):"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1031
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1035
+#: lib/Slic3r/GUI/Plater.pm:1133 lib/Slic3r/GUI/Plater.pm:1137
 msgid "Scale along "
 msgstr "Масштабувати разом "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1031
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1035
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1056
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1061
+#: lib/Slic3r/GUI/Plater.pm:1133 lib/Slic3r/GUI/Plater.pm:1137
+#: lib/Slic3r/GUI/Plater.pm:1158 lib/Slic3r/GUI/Plater.pm:1163
 msgid "Invalid scaling value entered"
 msgstr "Введено неправильне значення масштабування"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1035
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1061
+#: lib/Slic3r/GUI/Plater.pm:1137 lib/Slic3r/GUI/Plater.pm:1163
 #, no-perl-format
 msgid "Enter the scale % for the selected object:"
 msgstr "Введіть шкалу % для обраного об'єкта:"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1056
+#: lib/Slic3r/GUI/Plater.pm:1158
 msgid "Enter the new max size for the selected object:"
 msgstr "Введіть новий максимальний розмір для обраного об'єкта:"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1112
+#: lib/Slic3r/GUI/Plater.pm:1218
 msgid ""
 "The selected object can't be split because it contains more than one volume/"
 "material."
@@ -4111,76 +5336,87 @@ msgstr ""
 "Вибраний об'єкт не можна розділити, оскільки містить більше одного об'єму/"
 "матеріалу."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1121
+#: lib/Slic3r/GUI/Plater.pm:1227
 msgid ""
 "The selected object couldn't be split because it contains only one part."
 msgstr ""
 "Вибраний об'єкт не можна розділити, оскільки він містить лише одну частину."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1286
+#: lib/Slic3r/GUI/Plater.pm:1391
 msgid "Slicing cancelled"
 msgstr "Нарізання скасовано"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1300
+#: lib/Slic3r/GUI/Plater.pm:1405
 msgid "Another export job is currently running."
 msgstr "На даний час виконується інший експорт."
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1445
+#: lib/Slic3r/GUI/Plater.pm:1555
 msgid "File added to print queue"
 msgstr "Файл додано до черги друку"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1448
-msgid "Sending G-code file to the OctoPrint server..."
-msgstr "Відправка файлу G-коду на сервер OctoPrint..."
-
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1451
+#: lib/Slic3r/GUI/Plater.pm:1561
 msgid "G-code file exported to "
 msgstr "Файл G-коду експортується до "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1454
+#: lib/Slic3r/GUI/Plater.pm:1564
 msgid "Export failed"
 msgstr "Експортувати не вдалося"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1524
-msgid "G-code file successfully uploaded to the OctoPrint server"
-msgstr "Файл G-коду успішно завантажений на сервер OctoPrint"
+#: lib/Slic3r/GUI/Plater.pm:1576
+msgid "OctoPrint upload finished."
+msgstr ""
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1526
-msgid "Error while uploading to the OctoPrint server: "
-msgstr "Помилка під час завантаження на сервер OctoPrint: "
+#: lib/Slic3r/GUI/Plater.pm:1610
+msgid "Used Filament (m)"
+msgstr "Використано філаметну (м)"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1539
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1581
+#: lib/Slic3r/GUI/Plater.pm:1612
+msgid "Used Filament (mm³)"
+msgstr "Використано філаметну (мм³)"
+
+#: lib/Slic3r/GUI/Plater.pm:1614
+msgid "Used Filament (g)"
+msgstr "Використано філаметну (г)"
+
+#: lib/Slic3r/GUI/Plater.pm:1618
+msgid "Estimated printing time (normal mode)"
+msgstr ""
+
+#: lib/Slic3r/GUI/Plater.pm:1620
+msgid "Estimated printing time (silent mode)"
+msgstr ""
+
+#: lib/Slic3r/GUI/Plater.pm:1659 lib/Slic3r/GUI/Plater.pm:1701
 msgid "STL file exported to "
 msgstr "STL-файл експортовано в "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1592
+#: lib/Slic3r/GUI/Plater.pm:1740
 msgid "AMF file exported to "
 msgstr "AMF-файл експортовано в "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1596
+#: lib/Slic3r/GUI/Plater.pm:1744
 msgid "Error exporting AMF file "
 msgstr "Помилка експортування AMF-файлу "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1608
+#: lib/Slic3r/GUI/Plater.pm:1756
 msgid "3MF file exported to "
 msgstr "3MF-файл експортовано в "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1612
+#: lib/Slic3r/GUI/Plater.pm:1760
 msgid "Error exporting 3MF file "
 msgstr "Помилка експортування 3MF-файлу "
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1958
+#: lib/Slic3r/GUI/Plater.pm:2140
 #, perl-format
 msgid "%d (%d shells)"
 msgstr "%d (%d оболонок)"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1960
+#: lib/Slic3r/GUI/Plater.pm:2142
 #, perl-format
 msgid "Auto-repaired (%d errors)"
 msgstr "Автоматичне відновлення (%d помилок)"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1965
+#: lib/Slic3r/GUI/Plater.pm:2147
 #, perl-format
 msgid ""
 "%d degenerate facets, %d edges fixed, %d facets removed, %d facets added, %d "
@@ -4189,219 +5425,302 @@ msgstr ""
 "вироджено %d грані, виправлено %d країв, вилучено %d грані, додано %d грані, "
 "змінено %d грані, повернуто %d країв"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:1970
+#: lib/Slic3r/GUI/Plater.pm:2152
 msgid "Yes"
 msgstr "Так"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2021
+#: lib/Slic3r/GUI/Plater.pm:2215
 msgid "Remove the selected object"
 msgstr "Видалити вибраний об'єкт"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2024
+#: lib/Slic3r/GUI/Plater.pm:2218
 msgid "Increase copies"
 msgstr "Збільшити копії"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2024
+#: lib/Slic3r/GUI/Plater.pm:2218
 msgid "Place one more copy of the selected object"
 msgstr "Розташувати ще одну копію обраного об'єкта"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2027
+#: lib/Slic3r/GUI/Plater.pm:2221
 msgid "Decrease copies"
 msgstr "Зменшити копії"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2027
+#: lib/Slic3r/GUI/Plater.pm:2221
 msgid "Remove one copy of the selected object"
 msgstr "Вилучіть одну копію обраного об'єкта"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2030
+#: lib/Slic3r/GUI/Plater.pm:2224
 msgid "Set number of copies…"
 msgstr "Встановити кількість копій…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2030
+#: lib/Slic3r/GUI/Plater.pm:2224
 msgid "Change the number of copies of the selected object"
 msgstr "Змінити кількість копій обраного об'єкта"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2034
+#: lib/Slic3r/GUI/Plater.pm:2228
 msgid "Rotate 45° clockwise"
 msgstr "Повернути на 45° за годинниковою стрілкою"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2034
+#: lib/Slic3r/GUI/Plater.pm:2228
 msgid "Rotate the selected object by 45° clockwise"
 msgstr "Повернути виділений об'єкт на 45° за годинниковою стрілкою"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2037
+#: lib/Slic3r/GUI/Plater.pm:2231
 msgid "Rotate 45° counter-clockwise"
 msgstr "Повернути 45° проти годинникової стрілки"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2037
+#: lib/Slic3r/GUI/Plater.pm:2231
 msgid "Rotate the selected object by 45° counter-clockwise"
 msgstr "Повернути виділений об'єкт на 45° проти годинникової стрілки"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2042
+#: lib/Slic3r/GUI/Plater.pm:2236
 msgid "Rotate"
 msgstr "Повернути"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2042
+#: lib/Slic3r/GUI/Plater.pm:2236
 msgid "Rotate the selected object by an arbitrary angle"
 msgstr "Повернути виділений об'єкт на довільний кут"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2044
+#: lib/Slic3r/GUI/Plater.pm:2238
 msgid "Around X axis…"
 msgstr "Навколо осі X…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2044
+#: lib/Slic3r/GUI/Plater.pm:2238
 msgid "Rotate the selected object by an arbitrary angle around X axis"
 msgstr "Повернути виділений об'єкт на довільний кут навколо осі Х"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2047
+#: lib/Slic3r/GUI/Plater.pm:2241
 msgid "Around Y axis…"
 msgstr "Навколо осі Y…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2047
+#: lib/Slic3r/GUI/Plater.pm:2241
 msgid "Rotate the selected object by an arbitrary angle around Y axis"
 msgstr "Повернути виділений об'єкт на довільний кут навколо осі Y"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2050
+#: lib/Slic3r/GUI/Plater.pm:2244
 msgid "Around Z axis…"
 msgstr "Навколо осі Z…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2050
+#: lib/Slic3r/GUI/Plater.pm:2244
 msgid "Rotate the selected object by an arbitrary angle around Z axis"
 msgstr "Повернути виділений об'єкт на довільний кут навколо осі Z"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2055
+#: lib/Slic3r/GUI/Plater.pm:2249
 msgid "Mirror"
 msgstr "Віддзеркалити"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2055
+#: lib/Slic3r/GUI/Plater.pm:2249
 msgid "Mirror the selected object"
 msgstr "Віддзеркалити виділений об'єкт"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2057
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2073
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2089
+#: lib/Slic3r/GUI/Plater.pm:2251 lib/Slic3r/GUI/Plater.pm:2267
+#: lib/Slic3r/GUI/Plater.pm:2283
 msgid "Along X axis…"
 msgstr "Уздовж осі X…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2057
+#: lib/Slic3r/GUI/Plater.pm:2251
 msgid "Mirror the selected object along the X axis"
 msgstr "Віддзеркалити виділений об'єкт уздовж осі Х"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2060
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2076
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2092
+#: lib/Slic3r/GUI/Plater.pm:2254 lib/Slic3r/GUI/Plater.pm:2270
+#: lib/Slic3r/GUI/Plater.pm:2286
 msgid "Along Y axis…"
 msgstr "Уздовж осі Y…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2060
+#: lib/Slic3r/GUI/Plater.pm:2254
 msgid "Mirror the selected object along the Y axis"
 msgstr "Віддзеркалити виділений об'єкт уздовж осі Y"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2063
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2079
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2095
+#: lib/Slic3r/GUI/Plater.pm:2257 lib/Slic3r/GUI/Plater.pm:2273
+#: lib/Slic3r/GUI/Plater.pm:2289
 msgid "Along Z axis…"
 msgstr "Уздовж осі Z…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2063
+#: lib/Slic3r/GUI/Plater.pm:2257
 msgid "Mirror the selected object along the Z axis"
 msgstr "Віддзеркалити виділений об'єкт уздовж осі Z"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2068
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2084
+#: lib/Slic3r/GUI/Plater.pm:2262 lib/Slic3r/GUI/Plater.pm:2278
 msgid "Scale the selected object along a single axis"
 msgstr "Масштабувати виділений об'єкт уздовж осі"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2070
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2086
+#: lib/Slic3r/GUI/Plater.pm:2264 lib/Slic3r/GUI/Plater.pm:2280
 msgid "Uniformly…"
 msgstr "Рівномірно…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2070
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2086
+#: lib/Slic3r/GUI/Plater.pm:2264 lib/Slic3r/GUI/Plater.pm:2280
 msgid "Scale the selected object along the XYZ axes"
 msgstr "Масштабувати виділений об'єкт уздовж осей XYZ"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2073
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2089
+#: lib/Slic3r/GUI/Plater.pm:2267 lib/Slic3r/GUI/Plater.pm:2283
 msgid "Scale the selected object along the X axis"
 msgstr "Масштабувати виділений об'єкт уздовж осі X"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2076
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2092
+#: lib/Slic3r/GUI/Plater.pm:2270 lib/Slic3r/GUI/Plater.pm:2286
 msgid "Scale the selected object along the Y axis"
 msgstr "Масштабувати виділений об'єкт уздовж осі Y"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2079
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2095
+#: lib/Slic3r/GUI/Plater.pm:2273 lib/Slic3r/GUI/Plater.pm:2289
 msgid "Scale the selected object along the Z axis"
 msgstr "Масштабувати виділений об'єкт уздовж осі Z"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2084
+#: lib/Slic3r/GUI/Plater.pm:2278
 msgid "Scale to size"
 msgstr "Масштабувати до розміру"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2099
+#: lib/Slic3r/GUI/Plater.pm:2293
 msgid "Split the selected object into individual parts"
 msgstr "Розділити вибраний об'єкт на окремі частини"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2102
+#: lib/Slic3r/GUI/Plater.pm:2296
 msgid "Open the 3D cutting tool"
 msgstr "Відкрити інструмент 3D-нарізки"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2106
+#: lib/Slic3r/GUI/Plater.pm:2300
 msgid "Open the object editor dialog"
 msgstr "Відкрити діалог редактора об'єктів"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2110
+#: lib/Slic3r/GUI/Plater.pm:2304
 msgid "Reload from Disk"
 msgstr "Перезавантажити з диска"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2110
+#: lib/Slic3r/GUI/Plater.pm:2304
 msgid "Reload the selected file from Disk"
 msgstr "Перезавантажити вибраний файл із диска"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2113
+#: lib/Slic3r/GUI/Plater.pm:2307
 msgid "Export object as STL…"
 msgstr "Експортувати об'єкт як STL…"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater.pm:2113
+#: lib/Slic3r/GUI/Plater.pm:2307
 msgid "Export this single object as STL file"
 msgstr "Експортувати цей окремий об'єкт як STL-файл"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\2D.pm:131
+#: lib/Slic3r/GUI/Plater.pm:2311
+msgid "Fix STL through Netfabb"
+msgstr ""
+
+#: lib/Slic3r/GUI/Plater.pm:2311
+msgid ""
+"Fix the model by sending it to a Netfabb cloud service through Windows 10 API"
+msgstr ""
+
+#: lib/Slic3r/GUI/Plater/2D.pm:131
 msgid "What do you want to print today? ™"
 msgstr "Що б Ви хотіли надрукувати сьогодні? ™"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\2D.pm:132
+#: lib/Slic3r/GUI/Plater/2D.pm:132
 msgid "Drag your objects here"
 msgstr "Перетягніть сюди свій об'єкт"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:63
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:69
 msgid "1 Layer"
 msgstr "1 Шар"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:65
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:71
 msgid "View"
 msgstr "Вид"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:75
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:78
+msgid "Volumetric flow rate"
+msgstr ""
+
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:85
 msgid "Show"
 msgstr "Показати"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:78
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:79
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:88 lib/Slic3r/GUI/Plater/3DPreview.pm:89
 msgid "Feature types"
 msgstr "Типи ознак"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:96
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:106
 msgid "Retractions"
 msgstr "Переривання"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:97
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:107
 msgid "Unretractions"
 msgstr "Непереривання"
 
-#: c:\src\Slic3r\lib\Slic3r\GUI\Plater\3DPreview.pm:98
+#: lib/Slic3r/GUI/Plater/3DPreview.pm:108
 msgid "Shells"
 msgstr "Оболонки"
+
+#~ msgid "&Localization"
+#~ msgstr "Локалізація"
+
+#~ msgid ""
+#~ "The Wipe Tower currently supports only:\n"
+#~ "- first layer height 0.2mm\n"
+#~ "- layer height from 0.15mm to 0.35mm\n"
+#~ "\n"
+#~ "Shall I adjust those settings in order to enable the Wipe Tower?"
+#~ msgstr ""
+#~ "Вичіщуюча веж в даний час підтримує тільки:\n"
+#~ "- висота першого шару 0,2 мм\n"
+#~ "- висота шару від 0,15 мм до 0,35 мм\n"
+#~ "\n"
+#~ "Чи потрібно коригувати ці налаштування, щоб увімкнути вичіщуючу веж?"
+
+#~ msgid ""
+#~ "The supplied name is not valid; the following characters are not allowed:"
+#~ msgstr "Надане ім'я недійсне; такі символи не допускаються:"
+
+#~ msgid "Minimum extrusion length"
+#~ msgstr "Мінімальна довжина екструзії"
+
+#~ msgid "Host or IP"
+#~ msgstr "Host або IP"
+
+#~ msgid ""
+#~ "Slic3r can upload G-code files to OctoPrint. This field should contain "
+#~ "the hostname or IP address of the OctoPrint instance."
+#~ msgstr ""
+#~ "Slic3r може завантажувати файли G-коду в OctoPrint. Це поле повинно "
+#~ "містити ім'я хоста або IP-адресу екземпляру OctoPrint."
+
+#~ msgid "Per color change depth"
+#~ msgstr "Змінити глибину за кольором"
+
+#~ msgid ""
+#~ "Depth of a wipe color per color change. For N colors, there will be "
+#~ "maximum (N-1) tool switches performed, therefore the total depth of the "
+#~ "wipe tower will be (N-1) times this value."
+#~ msgstr ""
+#~ "Глибина вичищення кольору для кожної зміни кольору. Для N кольорів буде "
+#~ "виконано максимум (N-1) інструментальних перемикачів, тому загальна "
+#~ "глибина вичищуючої вежі буде (N-1) разів до цього значення."
+
+#~ msgid "No Bonjour device found"
+#~ msgstr "Немає пристрою Bonjour"
+
+#~ msgid "Device Browser"
+#~ msgstr "Браузер(список) пристроїв"
+
+#~ msgid "I wasn't able to connect to OctoPrint ("
+#~ msgstr "Не можливо підключитися до OctoPrint ("
+
+#~ msgid ""
+#~ "). Check hostname and OctoPrint version (at least 1.1.0 is required)."
+#~ msgstr ""
+#~ ") Перевірте версію хоста та OctoPrint (принаймні 1.1.0 - обов'язкова)."
+
+#~ msgid "Open STL/OBJ/AMF…\tCtrl+O"
+#~ msgstr "Відкрити STL/OBJ/AMF…\tCtrl+O"
+
+#~ msgid "Preferences…\tCtrl+,"
+#~ msgstr "Преференції…\tCtrl+,"
+
+#~ msgid "&Configuration "
+#~ msgstr "Конфігурація "
+
+#~ msgid "Run Configuration "
+#~ msgstr "Запустити конфігурацію "
+
+#~ msgid "Estimated printing time"
+#~ msgstr "Приблизний час друку"
+
+#~ msgid "G-code file successfully uploaded to the OctoPrint server"
+#~ msgstr "Файл G-коду успішно завантажений на сервер OctoPrint"
+
+#~ msgid "Error while uploading to the OctoPrint server: "
+#~ msgstr "Помилка під час завантаження на сервер OctoPrint: "
diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx
index 5c06353ca..ba4123588 100644
--- a/resources/profiles/PrusaResearch.idx
+++ b/resources/profiles/PrusaResearch.idx
@@ -1,4 +1,11 @@
 min_slic3r_version = 1.41.0-alpha
+0.2.0-beta Removed limit on the MK3MMU2 height, added legacy M204 S T format to the MK2 profiles
+0.2.0-alpha8 Added filament_load/unload_time for the PLA/ABS MMU2 filament presets.
+0.2.0-alpha7 Fixed the *MK3* references
+0.2.0-alpha6
+0.2.0-alpha5 Bumped up firmware versions for MK2.5/MK3 to 3.3.1, disabled priming areas for MK3MMU2
+0.2.0-alpha4 Extended the custom start/end G-codes of the MMU2.0 printers for no priming towers.
+0.2.0-alpha3 Adjusted machine limits for time estimates, added filament density and cost
 0.2.0-alpha2 Renamed the key MK3SMMU to MK3MMU2, added a generic PLA MMU2 material
 0.2.0-alpha1 added initial profiles for the i3 MK3 Multi Material Upgrade 2.0
 0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters
diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini
index fe403263d..32ec800e7 100644
--- a/resources/profiles/PrusaResearch.ini
+++ b/resources/profiles/PrusaResearch.ini
@@ -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.2.0-alpha2
+config_version = 0.2.0-beta
 # Where to get the updates from?
 config_update_url = https://raw.githubusercontent.com/prusa3d/Slic3r-settings/master/live/PrusaResearch/
 
@@ -14,26 +14,27 @@ config_update_url = https://raw.githubusercontent.com/prusa3d/Slic3r-settings/ma
 #TODO: One day we may differentiate variants of the nozzles / hot ends,
 #for example by the melt zone size, or whether the nozzle is hardened.
 # Printer model name will be shown by the installation wizard.
+
 [printer_model:MK3]
 name = Original Prusa i3 MK3
 variants = 0.4; 0.25; 0.6
 
-[printer_model:MK2S]
-name = Original Prusa i3 MK2S
-variants = 0.4; 0.25; 0.6
-
 [printer_model:MK2.5]
 name = Original Prusa i3 MK2.5
 variants = 0.4; 0.25; 0.6
 
-[printer_model:MK2SMM]
-name = Original Prusa i3 MK2S Multi Material Upgrade
-variants = 0.4; 0.6
+[printer_model:MK2S]
+name = Original Prusa i3 MK2/S
+variants = 0.4; 0.25; 0.6
 
-[printer_model:MK3MM2]
-name = Original Prusa i3 MK3 Multi Material Upgrade 2.0
+[printer_model:MK3MMU2]
+name = Original Prusa i3 MK3 MMU 2.0
 variants = 0.4
 
+[printer_model:MK2SMM]
+name = Original Prusa i3 MK2/S MMU 1.0
+variants = 0.4; 0.6
+
 # All presets starting with asterisk, for example *common*, are intermediate and they will
 # not make it into the user interface.
 
@@ -85,7 +86,7 @@ notes =
 overhangs = 0
 only_retract_when_crossing_perimeters = 0
 ooze_prevention = 0
-output_filename_format = [input_filename_base].gcode
+output_filename_format = {input_filename_base}_{layer_height}mm_{filament_type[0]}_{printer_model}.gcode
 perimeters = 2
 perimeter_extruder = 1
 perimeter_extrusion_width = 0.45
@@ -94,6 +95,7 @@ print_settings_id =
 raft_layers = 0
 resolution = 0
 seam_position = nearest
+single_extruder_multi_material_priming = 1
 skirts = 1
 skirt_distance = 2
 skirt_height = 3
@@ -132,9 +134,13 @@ wipe_tower_bridging = 10
 wipe_tower_rotation_angle = 0
 wipe_tower_width = 60
 wipe_tower_x = 180
-wipe_tower_y = 140
+wipe_tower_y = 135
 xy_size_compensation = 0
 
+[print:*MK3*]
+fill_pattern = grid
+single_extruder_multi_material_priming = 0
+
 # Print parameters common to a 0.25mm diameter nozzle.
 [print:*0.25nozzle*]
 external_perimeter_extrusion_width = 0.25
@@ -210,9 +216,8 @@ compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and
 infill_extrusion_width = 0.5
 
 [print:0.05mm ULTRADETAIL MK3]
-inherits = *0.05mm*
+inherits = *0.05mm*; *MK3*
 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/  and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
-fill_pattern = grid
 top_infill_extrusion_width = 0.4
 
 [print:0.05mm ULTRADETAIL 0.25 nozzle]
@@ -227,9 +232,8 @@ solid_infill_speed = 20
 support_material_speed = 20
 
 [print:0.05mm ULTRADETAIL 0.25 nozzle MK3]
-inherits = *0.05mm*; *0.25nozzle*
+inherits = *0.05mm*; *0.25nozzle*; *MK3*
 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1
-fill_pattern = grid
 
 # XXXXXXXXXXXXXXXXXXXX
 # XXX--- 0.10mm ---XXX
@@ -254,12 +258,11 @@ perimeter_speed = 50
 solid_infill_speed = 50
 
 [print:0.10mm DETAIL MK3]
-inherits = *0.10mm*
+inherits = *0.10mm*; *MK3*
 bridge_speed = 30
 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
 external_perimeter_speed = 35
-fill_pattern = grid
-infill_acceleration = 1500
+infill_acceleration = 1250
 infill_speed = 200
 max_print_speed = 200
 perimeter_speed = 45
@@ -281,12 +284,11 @@ solid_infill_speed = 40
 top_solid_infill_speed = 30
 
 [print:0.10mm DETAIL 0.25 nozzle MK3]
-inherits = *0.10mm*; *0.25nozzle*
+inherits = *0.10mm*; *0.25nozzle*; *MK3*
 bridge_speed = 30
 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25
 external_perimeter_speed = 35
-fill_pattern = grid
-infill_acceleration = 1500
+infill_acceleration = 1250
 infill_speed = 200
 max_print_speed = 200
 perimeter_speed = 45
@@ -294,12 +296,11 @@ solid_infill_speed = 200
 top_solid_infill_speed = 50
 
 [print:0.10mm DETAIL 0.6 nozzle MK3]
-inherits = *0.10mm*; *0.6nozzle*
+inherits = *0.10mm*; *0.6nozzle*; *MK3*
 bridge_speed = 30
 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
 external_perimeter_speed = 35
-fill_pattern = grid
-infill_acceleration = 1500
+infill_acceleration = 1250
 infill_speed = 200
 max_print_speed = 200
 perimeter_speed = 45
@@ -360,12 +361,11 @@ inherits = *0.15mm*; *0.6nozzle*
 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK2.*/ and nozzle_diameter[0]==0.6
 
 [print:0.15mm OPTIMAL MK3]
-inherits = *0.15mm*
+inherits = *0.15mm*; *MK3*
 bridge_speed = 30
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4
 external_perimeter_speed = 35
-fill_pattern = grid
-infill_acceleration = 1500
+infill_acceleration = 1250
 infill_speed = 200
 max_print_speed = 200
 perimeter_speed = 45
@@ -392,12 +392,11 @@ support_material_with_sheath = 0
 support_material_xy_spacing = 80%
 
 [print:0.15mm OPTIMAL 0.25 nozzle MK3]
-inherits = *0.15mm*; *0.25nozzle*
+inherits = *0.15mm*; *0.25nozzle*; *MK3*
 bridge_speed = 30
 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25
 external_perimeter_speed = 35
-fill_pattern = grid
-infill_acceleration = 1500
+infill_acceleration = 1250
 infill_speed = 200
 max_print_speed = 200
 perimeter_speed = 45
@@ -408,7 +407,7 @@ inherits = *common*
 bottom_solid_layers = 4
 bridge_flow_ratio = 0.95
 external_perimeter_speed = 40
-infill_acceleration = 2000
+infill_acceleration = 1250
 infill_speed = 60
 layer_height = 0.2
 perimeter_acceleration = 800
@@ -418,44 +417,17 @@ top_infill_extrusion_width = 0.4
 top_solid_layers = 5
 
 [print:0.15mm OPTIMAL 0.6 nozzle MK3]
-inherits = *0.15mm*; *0.6nozzle*
+inherits = *0.15mm*; *0.6nozzle*; *MK3*
 bridge_speed = 30
 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
 external_perimeter_speed = 35
-fill_pattern = grid
-infill_acceleration = 1500
+infill_acceleration = 1250
 infill_speed = 200
 max_print_speed = 200
 perimeter_speed = 45
 solid_infill_speed = 200
 top_solid_infill_speed = 50
 
-[print:0.15mm OPTIMAL MK3 MMU2]
-inherits = 0.15mm OPTIMAL MK3
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material
-bottom_solid_layers = 4
-external_perimeter_speed = 40
-fill_density = 10%
-infill_overlap = 15%
-perimeter_speed = 60
-small_perimeter_speed = 20
-support_material_threshold = 20
-top_solid_layers = 5
-
-[print:0.20mm FAST MK3 MMU2]
-inherits = 0.20mm FAST MK3
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material
-bridge_flow_ratio = 0.8
-external_perimeter_speed = 40
-fill_density = 15%
-infill_overlap = 35%
-infill_speed = 150
-perimeter_speed = 50
-small_perimeter_speed = 20
-solid_infill_speed = 150
-wipe_tower_x = 169
-wipe_tower_y = 137
-
 # XXXXXXXXXXXXXXXXXXXX
 # XXX--- 0.20mm ---XXX
 # XXXXXXXXXXXXXXXXXXXX
@@ -473,12 +445,11 @@ support_material_speed = 60
 top_solid_infill_speed = 70
 
 [print:0.20mm FAST MK3]
-inherits = *0.20mm*
+inherits = *0.20mm*; *MK3*
 bridge_speed = 30
-compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4
 external_perimeter_speed = 35
-fill_pattern = grid
-infill_acceleration = 1500
+infill_acceleration = 1250
 infill_speed = 200
 max_print_speed = 200
 perimeter_speed = 45
@@ -511,12 +482,11 @@ support_material_with_sheath = 0
 support_material_xy_spacing = 80%
 
 [print:0.20mm FAST 0.6 nozzle MK3]
-inherits = *0.20mm*; *0.6nozzle*
+inherits = *0.20mm*; *0.6nozzle*; *MK3*
 bridge_speed = 30
 compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6
 external_perimeter_speed = 35
-fill_pattern = grid
-infill_acceleration = 1500
+infill_acceleration = 1250
 infill_speed = 200
 max_print_speed = 200
 perimeter_speed = 45
@@ -593,6 +563,7 @@ filament_cooling_moves = 4
 filament_cooling_initial_speed = 2.2
 filament_cooling_final_speed = 3.4
 filament_ramming_parameters = "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6"
+filament_minimal_purge_on_wipe_tower = 5
 filament_cost = 0
 filament_density = 0
 filament_diameter = 1.75
@@ -680,6 +651,8 @@ inherits = *PLA*
 # For now, all but selected filaments are disabled for the MMU 2.0
 compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material)
 extrusion_multiplier = 1.2
+filament_cost = 80.65
+filament_density = 4
 filament_colour = #804040
 filament_max_volumetric_speed = 10
 
@@ -700,12 +673,16 @@ temperature = 270
 
 [filament:ColorFabb PLA-PHA]
 inherits = *PLA*
+filament_cost = 55.5
+filament_density = 1.24
 
 [filament:ColorFabb Woodfil]
 inherits = *PLA*
 # For now, all but selected filaments are disabled for the MMU 2.0
 compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material)
 extrusion_multiplier = 1.2
+filament_cost = 62.9
+filament_density = 1.15
 filament_colour = #804040
 filament_max_volumetric_speed = 10
 first_layer_temperature = 200
@@ -714,7 +691,9 @@ temperature = 200
 
 [filament:ColorFabb XT]
 inherits = *PET*
-filament_type = PLA
+filament_type = PET
+filament_cost = 62.9
+filament_density = 1.27
 first_layer_bed_temperature = 90
 first_layer_temperature = 260
 temperature = 270
@@ -722,6 +701,8 @@ temperature = 270
 [filament:ColorFabb XT-CF20]
 inherits = *PET*
 extrusion_multiplier = 1.2
+filament_cost = 80.65
+filament_density = 1.35
 filament_colour = #804040
 filament_max_volumetric_speed = 1
 first_layer_bed_temperature = 90
@@ -731,6 +712,8 @@ temperature = 260
 
 [filament:ColorFabb nGen]
 inherits = *PET*
+filament_cost = 21.2
+filament_density = 1.2
 bridge_fan_speed = 40
 fan_always_on = 0
 fan_below_layer_time = 10
@@ -741,6 +724,8 @@ min_fan_speed = 20
 
 [filament:ColorFabb nGen flex]
 inherits = *FLEX*
+filament_cost = 0
+filament_density = 1
 bed_temperature = 85
 bridge_fan_speed = 40
 cooling = 1
@@ -756,26 +741,36 @@ temperature = 260
 
 [filament:E3D Edge]
 inherits = *PET*
+filament_cost = 0
+filament_density = 1.26
 filament_notes = "List of manufacturers tested with standart PET print settings for MK2:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladeč PETG"
 
 [filament:E3D PC-ABS]
 inherits = *ABS*
+filament_cost = 0
+filament_density = 1.05
 first_layer_temperature = 270
 temperature = 270
 
 [filament:Fillamentum ABS]
 inherits = *ABS*
+filament_cost = 0
+filament_density = 1.04
 first_layer_temperature = 240
 temperature = 240
 
 [filament:Fillamentum ASA]
 inherits = *ABS*
+filament_cost = 0
+filament_density = 1.04
 fan_always_on = 1
 first_layer_temperature = 265
 temperature = 265
 
 [filament:Fillamentum CPE HG100 HM100]
 inherits = *PET*
+filament_cost = 0
+filament_density = 1.25
 filament_notes = "CPE HG100 , CPE HM100"
 first_layer_bed_temperature = 90
 first_layer_temperature = 275
@@ -788,6 +783,8 @@ inherits = *PLA*
 # For now, all but selected filaments are disabled for the MMU 2.0
 compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material)
 extrusion_multiplier = 1.2
+filament_cost = 0
+filament_density = 1.15
 filament_colour = #804040
 filament_max_volumetric_speed = 10
 first_layer_temperature = 190
@@ -796,14 +793,20 @@ temperature = 190
 
 [filament:Generic ABS]
 inherits = *ABS*
+filament_cost = 0
+filament_density = 1.04
 filament_notes = "List of materials tested with standart ABS print settings for MK2:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladeč ABS"
 
 [filament:Generic PET]
 inherits = *PET*
+filament_cost = 0
+filament_density = 1.24
 filament_notes = "List of manufacturers tested with standart PET print settings for MK2:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladeč PETG"
 
 [filament:Generic PLA]
 inherits = *PLA*
+filament_cost = 0
+filament_density = 1.27
 filament_notes = "List of materials tested with standart PLA print settings for MK2:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladeč PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
 
 [filament:Polymaker PC-Max]
@@ -830,8 +833,27 @@ temperature = 195
 
 [filament:Prusa ABS]
 inherits = *ABS*
+filament_cost = 27.82
+filament_density = 1.08
 filament_notes = "List of materials tested with standart ABS print settings for MK2:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladeč ABS"
 
+[filament:*ABS MMU2*]
+inherits = Prusa ABS
+compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and single_extruder_multi_material
+filament_cooling_final_speed = 50 
+filament_cooling_initial_speed = 10
+filament_cooling_moves = 5
+filament_loading_speed = 14
+filament_ramming_parameters = "120 110 5.32258 5.45161 5.67742 6 6.48387 7.12903 7.90323 8.70968 9.3871 9.83871 10.0968 10.2258| 0.05 5.30967 0.45 5.50967 0.95 6.1871 1.45 7.39677 1.95 9.05484 2.45 10 2.95 10.3098 3.45 13.0839 3.95 7.6 4.45 7.6 4.95 7.6";
+filament_load_time = 12
+filament_unload_time = 11
+
+[filament:Generic ABS MMU2]
+inherits = *ABS MMU2*
+
+[filament:Prusa ABS MMU2]
+inherits = *ABS MMU2*
+
 [filament:Prusa HIPS]
 inherits = *ABS*
 bridge_fan_speed = 50
@@ -850,10 +872,14 @@ temperature = 220
 
 [filament:Prusa PET]
 inherits = *PET*
+filament_cost = 27.82
+filament_density = 1.27
 filament_notes = "List of manufacturers tested with standart PET print settings for MK2:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladeč PETG"
 
 [filament:Prusa PLA]
 inherits = *PLA*
+filament_cost = 25.4
+filament_density = 1.24
 filament_notes = "List of materials tested with standart PLA print settings for MK2:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladeč PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH"
 
 [filament:*PLA MMU2*]
@@ -864,6 +890,8 @@ filament_cooling_initial_speed = 10
 filament_cooling_moves = 7
 filament_loading_speed = 14
 filament_ramming_parameters = "120 110 4.03226 4.12903 4.25806 4.41935 4.58065 4.80645 5.35484 6.29032 7.58065 9.09677 10.5806 11.8387 12.6452 12.9677| 0.05 4.01935 0.45 4.15483 0.95 4.50968 1.45 4.94516 1.95 6.79677 2.45 9.87102 2.95 12.4388 3.45 13.0839 3.95 7.6 4.45 7.6 4.95 7.6"
+filament_load_time = 12
+filament_unload_time = 11
 
 [filament:Generic PLA MMU2]
 inherits = *PLA MMU2*
@@ -873,6 +901,8 @@ inherits = *PLA MMU2*
 
 [filament:SemiFlex or Flexfill 98A]
 inherits = *FLEX*
+filament_cost = 0
+filament_density = 1.22
 
 [filament:Taulman Bridge]
 inherits = *common*
@@ -955,8 +985,9 @@ extruder_colour = #FFFF00
 extruder_offset = 0x0
 gcode_flavor = marlin
 silent_mode = 0
+remaining_times = 0
 machine_max_acceleration_e = 10000
-machine_max_acceleration_extruding = 1500
+machine_max_acceleration_extruding = 2000
 machine_max_acceleration_retracting = 1500
 machine_max_acceleration_x = 9000
 machine_max_acceleration_y = 9000
@@ -994,7 +1025,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\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\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\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
@@ -1030,7 +1061,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\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\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\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
 
 [printer:*mm-multi*]
@@ -1039,7 +1070,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\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\nM204 S[machine_max_acceleration_extruding] T[machine_max_acceleration_retracting] ; MK2 firmware only supports the old M204 format\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_single_extruder_multi_material_priming}\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
 
@@ -1099,17 +1130,20 @@ 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\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
+remaining_times = 1
+start_gcode = M115 U3.3.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\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
+remaining_times = 1
+start_gcode = M115 U3.3.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\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
+remaining_times = 1
+start_gcode = M115 U3.3.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
@@ -1118,11 +1152,11 @@ start_gcode = M115 U3.2.1 ; tell printer latest fw version\nM83  ; extruder rela
 [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_e = 5000,5000
+machine_max_acceleration_extruding = 1250,1250
 machine_max_acceleration_retracting = 1250,1250
-machine_max_acceleration_x = 1000,1000
-machine_max_acceleration_y = 1000,1000
+machine_max_acceleration_x = 1000,960
+machine_max_acceleration_y = 1000,960
 machine_max_acceleration_z = 1000,1000
 machine_max_feedrate_e = 120,120
 machine_max_feedrate_x = 200,172
@@ -1135,10 +1169,11 @@ machine_max_jerk_z = 0.4,0.4
 machine_min_extruding_rate = 0,0
 machine_min_travel_rate = 0,0
 silent_mode = 1
+remaining_times = 1
 printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n
 retract_lift_below = 209
 max_print_height = 210
-start_gcode = M115 U3.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}
+start_gcode = M115 U3.3.1 ; tell printer latest fw version\nM83  ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0  F1000.0 ; intro line\nG1 X100.0 E12.5  F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height==0.05}100{else}95{endif}
 printer_model = MK3
 default_print_profile = 0.15mm OPTIMAL MK3
 
@@ -1161,19 +1196,18 @@ default_print_profile = 0.15mm OPTIMAL 0.6 nozzle MK3
 [printer:*mm2*]
 inherits = Original Prusa i3 MK3
 single_extruder_multi_material = 1
-max_print_height = 200
 cooling_tube_length = 10
 cooling_tube_retraction = 30
 parking_pos_retraction = 85
 retract_length_toolchange = 3
 extra_loading_move = -13
-printer_model = MK3MM2
-default_print_profile = 0.15mm OPTIMAL MK3 MMU2
+printer_model = MK3MMU2
+default_print_profile = 0.15mm OPTIMAL MK3
 default_filament_profile = Prusa PLA MMU2
 
 [printer:Original Prusa i3 MK3 MMU2 Single]
 inherits = *mm2*
-start_gcode = M107\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\n\nG21 ; set units to millimeters\n\n ; go outside print area\nG1 Y-3.0 F1000.0 \nG1 Z0.4 F1000\n; select extruder\nT?\n; initial load\nG1 X50 E15 F1073\nG1 X100 E10 F2000\nG1 Z0.3 F1000\n\nG92 E0.0\nG1 X240.0 E15.0  F2400.0 \nG1 Y-2.0 F1000.0\nG1 X100.0 E10  F1400.0 \nG1 Z0.20 F1000\nG1 X0.0 E4  F1000.0\n\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
+start_gcode = M107\nM115 U3.3.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\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT?\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0  F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
 end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
 
 [printer:Original Prusa i3 MK3 MMU2]
@@ -1182,11 +1216,11 @@ inherits = *mm2*
 # (for example the retract values) are duplicaed from the first value, so they do not need 
 # to be defined explicitely.
 nozzle_diameter = 0.4,0.4,0.4,0.4,0.4
-extruder_colour = #FFFF00;#FFFFFF;#804040;#0000FF;#C0C0C0
-start_gcode = M107\n\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\n\nG21 ; set units to millimeters\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
-end_gcode = G1 E-15.0000 F3000\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors
+extruder_colour = #FF8000;#0080FF;#00FFFF;#FF4F4F;#9FFF9F
+start_gcode = M107\nM115 U3.3.1 ; tell printer latest fw version\nM83  ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0  F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\n;M221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n
+end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n
 
 # 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"
+print="0.05mm DETAIL 0.25 nozzle";"0.05mm DETAIL MK3";"0.05mm DETAIL";"0.20mm NORMAL MK3";"0.35mm FAST MK3";"print:0.15mm OPTIMAL MK3 MMU2";"print:0.20mm FAST MK3 MMU2"
 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"
diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt
index 3b6692d2f..80482952d 100644
--- a/xs/CMakeLists.txt
+++ b/xs/CMakeLists.txt
@@ -30,7 +30,7 @@ include_directories(${LIBDIR}/libslic3r)
 
 if(WIN32)
     # BOOST_ALL_NO_LIB: Avoid the automatic linking of Boost libraries on Windows. Rather rely on explicit linking.
-    add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB)
+    add_definitions(-D_USE_MATH_DEFINES -D_WIN32 -DBOOST_ALL_NO_LIB -DBOOST_USE_WINAPI_VERSION=0x601)
     # -D_ITERATOR_DEBUG_LEVEL)
     if(WIN10SDK_PATH)
         message("Building with Win10 Netfabb STL fixing service support")
@@ -140,6 +140,7 @@ add_library(libslic3r STATIC
     ${LIBDIR}/libslic3r/Line.hpp
     ${LIBDIR}/libslic3r/Model.cpp
     ${LIBDIR}/libslic3r/Model.hpp
+    ${LIBDIR}/libslic3r/ModelArrange.hpp
     ${LIBDIR}/libslic3r/MotionPlanner.cpp
     ${LIBDIR}/libslic3r/MotionPlanner.hpp
     ${LIBDIR}/libslic3r/MultiPoint.cpp
@@ -266,6 +267,8 @@ add_library(libslic3r_gui STATIC
     ${LIBDIR}/slic3r/Utils/Time.hpp
     ${LIBDIR}/slic3r/GUI/PngExportDialog.hpp
     ${LIBDIR}/slic3r/GUI/PngExportDialog.cpp
+    ${LIBDIR}/slic3r/Utils/HexFile.cpp
+    ${LIBDIR}/slic3r/Utils/HexFile.hpp
     ${LIBDIR}/slic3r/IProgressIndicator.hpp
     ${LIBDIR}/slic3r/AppController.hpp
     ${LIBDIR}/slic3r/AppController.cpp
@@ -778,6 +781,7 @@ set(LIBNEST2D_UNITTESTS ON CACHE BOOL "Force generating unittests for libnest2d"
 
 add_subdirectory(${LIBDIR}/libnest2d)
 target_include_directories(libslic3r PUBLIC BEFORE ${LIBNEST2D_INCLUDES})
+target_include_directories(libslic3r_gui PUBLIC BEFORE ${LIBNEST2D_INCLUDES})
 
 message(STATUS "Libnest2D Libraries: ${LIBNEST2D_LIBRARIES}")
 target_link_libraries(libslic3r ${LIBNEST2D_LIBRARIES})
diff --git a/xs/src/avrdude/CMakeLists.txt b/xs/src/avrdude/CMakeLists.txt
index 043f8fb7b..d88563368 100644
--- a/xs/src/avrdude/CMakeLists.txt
+++ b/xs/src/avrdude/CMakeLists.txt
@@ -1,3 +1,4 @@
+cmake_minimum_required(VERSION 3.0)
 
 
 add_definitions(-D_BSD_SOURCE -D_DEFAULT_SOURCE)   # To enable various useful macros and functions on Unices
@@ -13,67 +14,74 @@ endif()
 
 
 set(AVRDUDE_SOURCES
-    ${LIBDIR}/avrdude/arduino.c
-    ${LIBDIR}/avrdude/avr.c
-    # ${LIBDIR}/avrdude/avrftdi.c
-    # ${LIBDIR}/avrdude/avrftdi_tpi.c
-    ${LIBDIR}/avrdude/avrpart.c
-    ${LIBDIR}/avrdude/avr910.c
-    ${LIBDIR}/avrdude/bitbang.c
-    ${LIBDIR}/avrdude/buspirate.c
-    ${LIBDIR}/avrdude/butterfly.c
-    ${LIBDIR}/avrdude/config.c
-    ${LIBDIR}/avrdude/config_gram.c
-    # ${LIBDIR}/avrdude/confwin.c
-    ${LIBDIR}/avrdude/crc16.c
-    # ${LIBDIR}/avrdude/dfu.c
-    ${LIBDIR}/avrdude/fileio.c
-    # ${LIBDIR}/avrdude/flip1.c
-    # ${LIBDIR}/avrdude/flip2.c
-    # ${LIBDIR}/avrdude/ft245r.c
-    # ${LIBDIR}/avrdude/jtagmkI.c
-    # ${LIBDIR}/avrdude/jtagmkII.c
-    # ${LIBDIR}/avrdude/jtag3.c
-    ${LIBDIR}/avrdude/lexer.c
-    ${LIBDIR}/avrdude/linuxgpio.c
-    ${LIBDIR}/avrdude/lists.c
-    # ${LIBDIR}/avrdude/par.c
-    ${LIBDIR}/avrdude/pgm.c
-    ${LIBDIR}/avrdude/pgm_type.c
-    ${LIBDIR}/avrdude/pickit2.c
-    ${LIBDIR}/avrdude/pindefs.c
-    # ${LIBDIR}/avrdude/ppi.c
-    # ${LIBDIR}/avrdude/ppiwin.c
-    ${LIBDIR}/avrdude/safemode.c
-    ${LIBDIR}/avrdude/ser_avrdoper.c
-    ${LIBDIR}/avrdude/serbb_posix.c
-    ${LIBDIR}/avrdude/serbb_win32.c
-    ${LIBDIR}/avrdude/ser_posix.c
-    ${LIBDIR}/avrdude/ser_win32.c
-    ${LIBDIR}/avrdude/stk500.c
-    ${LIBDIR}/avrdude/stk500generic.c
-    ${LIBDIR}/avrdude/stk500v2.c
-    ${LIBDIR}/avrdude/term.c
-    ${LIBDIR}/avrdude/update.c
-    # ${LIBDIR}/avrdude/usbasp.c
-    # ${LIBDIR}/avrdude/usb_hidapi.c
-    # ${LIBDIR}/avrdude/usb_libusb.c
-    # ${LIBDIR}/avrdude/usbtiny.c
-    ${LIBDIR}/avrdude/wiring.c
+    arduino.c
+    avr.c
+    # avrftdi.c
+    # avrftdi_tpi.c
+    avrpart.c
+    avr910.c
+    bitbang.c
+    buspirate.c
+    butterfly.c
+    config.c
+    config_gram.c
+    # confwin.c
+    crc16.c
+    # dfu.c
+    fileio.c
+    # flip1.c
+    # flip2.c
+    # ft245r.c
+    # jtagmkI.c
+    # jtagmkII.c
+    # jtag3.c
+    lexer.c
+    linuxgpio.c
+    lists.c
+    # par.c
+    pgm.c
+    pgm_type.c
+    pickit2.c
+    pindefs.c
+    # ppi.c
+    # ppiwin.c
+    safemode.c
+    ser_avrdoper.c
+    serbb_posix.c
+    serbb_win32.c
+    ser_posix.c
+    ser_win32.c
+    stk500.c
+    stk500generic.c
+    stk500v2.c
+    term.c
+    update.c
+    # usbasp.c
+    # usb_hidapi.c
+    # usb_libusb.c
+    # usbtiny.c
+    wiring.c
 
-    ${LIBDIR}/avrdude/main.c
-    ${LIBDIR}/avrdude/avrdude-slic3r.hpp
-    ${LIBDIR}/avrdude/avrdude-slic3r.cpp
+    main.c
+    avrdude-slic3r.hpp
+    avrdude-slic3r.cpp
 )
 if (WIN32)
     set(AVRDUDE_SOURCES ${AVRDUDE_SOURCES}
-        ${LIBDIR}/avrdude/windows/unistd.cpp
-        ${LIBDIR}/avrdude/windows/getopt.c
+        windows/unistd.cpp
+        windows/getopt.c
     )
 endif()
 add_library(avrdude STATIC ${AVRDUDE_SOURCES})
 
+set(STANDALONE_SOURCES
+    main-standalone.c
+)
+add_executable(avrdude-slic3r ${STANDALONE_SOURCES})
+target_link_libraries(avrdude-slic3r avrdude)
+set_target_properties(avrdude-slic3r PROPERTIES EXCLUDE_FROM_ALL TRUE)
+
 if (WIN32)
     target_compile_definitions(avrdude PRIVATE WIN32NATIVE=1)
-    target_include_directories(avrdude SYSTEM PRIVATE ${LIBDIR}/avrdude/windows)    # So that sources find the getopt.h windows drop-in
+    target_include_directories(avrdude SYSTEM PRIVATE windows)    # So that sources find the getopt.h windows drop-in
 endif()
diff --git a/xs/src/avrdude/Makefile.standalone b/xs/src/avrdude/Makefile.standalone
new file mode 100644
index 000000000..d9a773771
--- /dev/null
+++ b/xs/src/avrdude/Makefile.standalone
@@ -0,0 +1,54 @@
+
+TARGET = avrdude-slic3r
+
+SOURCES = \
+    arduino.c \
+    avr.c \
+    avrpart.c \
+    avr910.c \
+    bitbang.c \
+    buspirate.c \
+    butterfly.c \
+    config.c \
+    config_gram.c \
+    crc16.c \
+    fileio.c \
+    lexer.c \
+    linuxgpio.c \
+    lists.c \
+    pgm.c \
+    pgm_type.c \
+    pickit2.c \
+    pindefs.c \
+    safemode.c \
+    ser_avrdoper.c \
+    serbb_posix.c \
+    serbb_win32.c \
+    ser_posix.c \
+    ser_win32.c \
+    stk500.c \
+    stk500generic.c \
+    stk500v2.c \
+    term.c \
+    update.c \
+    wiring.c \
+    main.c \
+    main-standalone.c
+
+OBJECTS = $(SOURCES:.c=.o)
+CFLAGS = -std=c99 -Wall -D_BSD_SOURCE -D_DEFAULT_SOURCE -O3 -DNDEBUG -fPIC
+LDFLAGS = -lm
+
+CC = gcc
+RM = rm
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+	$(CC) -o ./$@ $(OBJECTS) $(LDFLAGS)
+
+$(OBJECTS): %.o: %.c
+	$(CC) $(CFLAGS) -o $@ -c $<
+
+clean:
+	$(RM) -f $(OBJECTS) $(TARGET)
diff --git a/xs/src/avrdude/avrdude-slic3r.cpp b/xs/src/avrdude/avrdude-slic3r.cpp
index 030353413..0577fe6d0 100644
--- a/xs/src/avrdude/avrdude-slic3r.cpp
+++ b/xs/src/avrdude/avrdude-slic3r.cpp
@@ -35,6 +35,8 @@ struct AvrDude::priv
 {
 	std::string sys_config;
 	std::deque<std::vector<std::string>> args;
+	bool cancelled = false;
+	int exit_code = 0;
 	size_t current_args_set = 0;
 	RunFn run_fn;
 	MessageFn message_fn;
@@ -141,14 +143,19 @@ AvrDude::Ptr AvrDude::run()
 
 	if (self->p) {
 		auto avrdude_thread = std::thread([self]() {
+			bool cancel = false;
+			int res = -1;
+
 			if (self->p->run_fn) {
 				self->p->run_fn();
 			}
 
-			auto res = self->p->run();
+			if (! self->p->cancelled) {
+				self->p->exit_code = self->p->run();
+			}
 
 			if (self->p->complete_fn) {
-				self->p->complete_fn(res, self->p->current_args_set);
+				self->p->complete_fn();
 			}
 		});
 
@@ -160,7 +167,10 @@ AvrDude::Ptr AvrDude::run()
 
 void AvrDude::cancel()
 {
-	::avrdude_cancel();
+	if (p) {
+		p->cancelled = true;
+		::avrdude_cancel();
+	}
 }
 
 void AvrDude::join()
@@ -170,5 +180,20 @@ void AvrDude::join()
 	}
 }
 
+bool AvrDude::cancelled()
+{
+	return p ? p->cancelled : false;
+}
+
+int AvrDude::exit_code()
+{
+	return p ? p->exit_code : 0;
+}
+
+size_t AvrDude::last_args_set()
+{
+	return p ? p->current_args_set : 0;
+}
+
 
 }
diff --git a/xs/src/avrdude/avrdude-slic3r.hpp b/xs/src/avrdude/avrdude-slic3r.hpp
index 273aa2378..86e097034 100644
--- a/xs/src/avrdude/avrdude-slic3r.hpp
+++ b/xs/src/avrdude/avrdude-slic3r.hpp
@@ -15,7 +15,7 @@ public:
 	typedef std::function<void()> RunFn;
 	typedef std::function<void(const char * /* msg */, unsigned /* size */)> MessageFn;
 	typedef std::function<void(const char * /* task */, unsigned /* progress */)> ProgressFn;
-	typedef std::function<void(int /* exit status */, size_t /* args_id */)> CompleteFn;
+	typedef std::function<void()> CompleteFn;
 
 	// Main c-tor, sys_config is the location of avrdude's main configuration file
 	AvrDude(std::string sys_config);
@@ -31,7 +31,8 @@ public:
 	AvrDude& push_args(std::vector<std::string> args);
 
 	// Set a callback to be called just after run() before avrdude is ran
-	// This can be used to perform any needed setup tasks from the background thread.
+	// This can be used to perform any needed setup tasks from the background thread,
+	// and, optionally, to cancel by writing true to the `cancel` argument.
 	// This has no effect when using run_sync().
 	AvrDude& on_run(RunFn fn);
 
@@ -53,6 +54,10 @@ public:
 
 	void cancel();
 	void join();
+
+	bool cancelled();          // Whether avrdude run was cancelled
+	int exit_code();           // The exit code of the last invocation
+	size_t last_args_set();    // Index of the last argument set that was processsed
 private:
 	struct priv;
 	std::unique_ptr<priv> p;
diff --git a/xs/src/avrdude/fileio.c b/xs/src/avrdude/fileio.c
index aa57f5587..708159295 100644
--- a/xs/src/avrdude/fileio.c
+++ b/xs/src/avrdude/fileio.c
@@ -98,11 +98,11 @@ static int fileio_num(struct fioparms * fio,
 		char * filename, FILE * f, AVRMEM * mem, int size,
 		FILEFMT fmt);
 
-static int fmt_autodetect(char * fname, size_t offset);
+static int fmt_autodetect(char * fname, unsigned section);
 
 
 
-static FILE *fopen_and_seek(const char *filename, const char *mode, size_t offset)
+static FILE *fopen_and_seek(const char *filename, const char *mode, unsigned section)
 {
   FILE *file;
   // On Windows we need to convert the filename to UTF-16
@@ -118,16 +118,38 @@ static FILE *fopen_and_seek(const char *filename, const char *mode, size_t offse
   file = fopen(filename, mode);
 #endif
 
-  if (file != NULL) {
-    // Some systems allow seeking past the end of file, so we need check for that first and disallow
-    if (fseek(file, 0, SEEK_END) != 0
-      || offset >= ftell(file)
-      || fseek(file, offset, SEEK_SET) != 0
-      ) {
-      fclose(file);
-      file = NULL;
-      errno = EINVAL;
+  if (file == NULL) {
+    return NULL;
+  }
+
+  // Seek to the specified 'section'
+  static const char *hex_terminator = ":00000001FF\r";
+  unsigned terms_seen = 0;
+  char buffer[MAX_LINE_LEN + 1];
+
+  while (terms_seen < section && fgets(buffer, MAX_LINE_LEN, file) != NULL) {
+    size_t len = strlen(buffer);
+
+    if (buffer[len - 1] == '\n') {
+      len--;
+      buffer[len] = 0;
     }
+    if (buffer[len - 1] != '\r') {
+      buffer[len] = '\r';
+      len++;
+      buffer[len] = 0;
+    }
+
+    if (strcmp(buffer, hex_terminator) == 0) {
+      // Found a section terminator
+      terms_seen++;
+    }
+  }
+
+  if (feof(file)) {
+    // Section not found
+    fclose(file);
+    return NULL;
   }
 
   return file;
@@ -1392,7 +1414,7 @@ int fileio_setparms(int op, struct fioparms * fp,
 
 
 
-static int fmt_autodetect(char * fname, size_t offset)
+static int fmt_autodetect(char * fname, unsigned section)
 {
   FILE * f;
   unsigned char buf[MAX_LINE_LEN];
@@ -1402,9 +1424,9 @@ static int fmt_autodetect(char * fname, size_t offset)
   int first = 1;
 
 #if defined(WIN32NATIVE)
-  f = fopen_and_seek(fname, "r", offset);
+  f = fopen_and_seek(fname, "r", section);
 #else
-  f = fopen_and_seek(fname, "rb", offset);
+  f = fopen_and_seek(fname, "rb", section);
 #endif
 
   if (f == NULL) {
@@ -1480,7 +1502,7 @@ static int fmt_autodetect(char * fname, size_t offset)
 
 
 int fileio(int op, char * filename, FILEFMT format, 
-             struct avrpart * p, char * memtype, int size, size_t offset)
+             struct avrpart * p, char * memtype, int size, unsigned section)
 {
   int rc;
   FILE * f;
@@ -1539,7 +1561,7 @@ int fileio(int op, char * filename, FILEFMT format,
       return -1;
     }
 
-    format_detect = fmt_autodetect(fname, offset);
+    format_detect = fmt_autodetect(fname, section);
     if (format_detect < 0) {
       avrdude_message(MSG_INFO, "%s: can't determine file format for %s, specify explicitly\n",
                       progname, fname);
@@ -1570,7 +1592,7 @@ int fileio(int op, char * filename, FILEFMT format,
 
   if (format != FMT_IMM) {
     if (!using_stdio) {
-      f = fopen_and_seek(fname, fio.mode, offset);
+      f = fopen_and_seek(fname, fio.mode, section);
       if (f == NULL) {
         avrdude_message(MSG_INFO, "%s: can't open %s file %s: %s\n",
                 progname, fio.iodesc, fname, strerror(errno));
diff --git a/xs/src/avrdude/libavrdude.h b/xs/src/avrdude/libavrdude.h
index 536f1a2f7..aef792476 100644
--- a/xs/src/avrdude/libavrdude.h
+++ b/xs/src/avrdude/libavrdude.h
@@ -821,7 +821,7 @@ extern "C" {
 char * fmtstr(FILEFMT format);
 
 int fileio(int op, char * filename, FILEFMT format,
-           struct avrpart * p, char * memtype, int size, size_t offset);
+           struct avrpart * p, char * memtype, int size, unsigned section);
 
 #ifdef __cplusplus
 }
@@ -870,7 +870,7 @@ enum updateflags {
 typedef struct update_t {
   char * memtype;
   int    op;
-  size_t offset;
+  unsigned section;
   char * filename;
   int    format;
 } UPDATE;
@@ -882,7 +882,7 @@ extern "C" {
 extern UPDATE * parse_op(char * s);
 extern UPDATE * dup_update(UPDATE * upd);
 extern UPDATE * new_update(int op, char * memtype, int filefmt,
-			   char * filename, size_t offset);
+			   char * filename, unsigned section);
 extern void free_update(UPDATE * upd);
 extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
 		 enum updateflags flags);
diff --git a/xs/src/avrdude/main-standalone.c b/xs/src/avrdude/main-standalone.c
new file mode 100644
index 000000000..359a055ca
--- /dev/null
+++ b/xs/src/avrdude/main-standalone.c
@@ -0,0 +1,9 @@
+#include "avrdude.h"
+
+
+static const char* SYS_CONFIG = "/etc/avrdude-slic3r.conf";
+
+int main(int argc, char *argv[])
+{
+	return avrdude_main(argc, argv, SYS_CONFIG);
+}
diff --git a/xs/src/avrdude/main.c b/xs/src/avrdude/main.c
index d4c34fe44..5d73403b0 100644
--- a/xs/src/avrdude/main.c
+++ b/xs/src/avrdude/main.c
@@ -194,7 +194,7 @@ static void usage(void)
  "  -F                         Override invalid signature check.\n"
  "  -e                         Perform a chip erase.\n"
  "  -O                         Perform RC oscillator calibration (see AVR053). \n"
- "  -U <memtype>:r|w|v:<offset>:<filename>[:format]\n"
+ "  -U <memtype>:r|w|v:<section>:<filename>[:format]\n"
  "                             Memory operation specification.\n"
  "                             Multiple -U options are allowed, each request\n"
  "                             is performed in the order specified.\n"
diff --git a/xs/src/avrdude/ser_win32.c b/xs/src/avrdude/ser_win32.c
index 20d085d13..3a05cfa90 100644
--- a/xs/src/avrdude/ser_win32.c
+++ b/xs/src/avrdude/ser_win32.c
@@ -311,8 +311,10 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
 static void ser_close(union filedescriptor *fd)
 {
 	if (serial_over_ethernet) {
+#ifdef HAVE_LIBWS2_32
 		closesocket(fd->ifd);
 		WSACleanup();
+#endif
 	} else {
 		HANDLE hComPort=(HANDLE)fd->pfd;
 		if (hComPort != INVALID_HANDLE_VALUE)
diff --git a/xs/src/avrdude/update.c b/xs/src/avrdude/update.c
index e9dd6e325..417cbf71d 100644
--- a/xs/src/avrdude/update.c
+++ b/xs/src/avrdude/update.c
@@ -101,22 +101,22 @@ UPDATE * parse_op(char * s)
 
   p++;
 
-  // Extension: Parse file contents offset
-  size_t offset = 0;
+  // Extension: Parse file section number
+  unsigned section = 0;
 
   for (; *p != ':'; p++) {
     if (*p >= '0' && *p <= '9') {
-      offset *= 10;
-      offset += *p - 0x30;
+      section *= 10;
+      section += *p - 0x30;
     } else {
-      avrdude_message(MSG_INFO, "%s: invalid update specification: offset is not a number\n", progname);
+      avrdude_message(MSG_INFO, "%s: invalid update specification: <section> is not a number\n", progname);
       free(upd->memtype);
       free(upd);
       return NULL;
     }
   }
 
-  upd->offset = offset;
+  upd->section = section;
   p++;
 
   /*
@@ -194,7 +194,7 @@ UPDATE * dup_update(UPDATE * upd)
   return u;
 }
 
-UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, size_t offset)
+UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, unsigned section)
 {
   UPDATE * u;
 
@@ -208,7 +208,7 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, size_t
   u->filename = strdup(filename);
   u->op = op;
   u->format = filefmt;
-  u->offset = offset;
+  u->section = section;
 
   return u;
 }
@@ -286,7 +286,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
                       progname,
                       strcmp(upd->filename, "-")==0 ? "<stdin>" : upd->filename);
     }
-    rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset);
+    rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->section);
     if (rc < 0) {
       avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
               progname, upd->filename);
@@ -351,7 +351,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
             progname, mem->desc, upd->filename);
     }
 
-    rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset);
+    rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->section);
     if (rc < 0) {
       avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
               progname, upd->filename);
diff --git a/xs/src/libnest2d/CMakeLists.txt b/xs/src/libnest2d/CMakeLists.txt
index bfdb551fc..835e8311d 100644
--- a/xs/src/libnest2d/CMakeLists.txt
+++ b/xs/src/libnest2d/CMakeLists.txt
@@ -2,8 +2,6 @@ cmake_minimum_required(VERSION 2.8)
 
 project(Libnest2D)
 
-enable_testing()
-
 if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
     # Update if necessary
     set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long ")
@@ -32,6 +30,7 @@ set(LIBNEST2D_SRCFILES
     ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/geometry_traits.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/common.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizer.hpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/metaloop.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/placers/placer_boilerplate.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/placers/bottomleftplacer.hpp
     ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/placers/nfpplacer.hpp
@@ -60,8 +59,7 @@ if(LIBNEST2D_GEOMETRIES_BACKEND STREQUAL "clipper")
     include_directories(BEFORE ${CLIPPER_INCLUDE_DIRS})
     include_directories(${Boost_INCLUDE_DIRS})
 
-    list(APPEND LIBNEST2D_SRCFILES ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/clipper_backend/clipper_backend.cpp
-                                   ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/clipper_backend/clipper_backend.hpp
+    list(APPEND LIBNEST2D_SRCFILES ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/clipper_backend/clipper_backend.hpp
                                    ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/boost_alg.hpp)
     list(APPEND LIBNEST2D_LIBRARIES ${CLIPPER_LIBRARIES})
     list(APPEND LIBNEST2D_HEADERS ${CLIPPER_INCLUDE_DIRS}
@@ -81,22 +79,12 @@ if(LIBNEST2D_OPTIMIZER_BACKEND STREQUAL "nlopt")
                                     ${CMAKE_CURRENT_SOURCE_DIR}/libnest2d/optimizers/subplex.hpp
                                     ${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
-    )
+    list(APPEND LIBNEST2D_LIBRARIES ${NLopt_LIBS})
     list(APPEND LIBNEST2D_HEADERS ${NLopt_INCLUDE_DIR})
 endif()
 
-# Currently we are outsourcing the non-convex NFP implementation from
-# libnfporb and it needs libgmp to work
-#find_package(GMP)
-#if(GMP_FOUND)
-#    list(APPEND LIBNEST2D_LIBRARIES ${GMP_LIBRARIES})
-#    list(APPEND LIBNEST2D_HEADERS ${GMP_INCLUDE_DIR})
-#    add_definitions(-DLIBNFP_USE_RATIONAL)
-#endif()
-
 if(LIBNEST2D_UNITTESTS)
+    enable_testing()
     add_subdirectory(tests)
 endif()
 
diff --git a/xs/src/libnest2d/cmake_modules/DownloadNLopt.cmake b/xs/src/libnest2d/cmake_modules/DownloadNLopt.cmake
index 814213b38..0f5392596 100644
--- a/xs/src/libnest2d/cmake_modules/DownloadNLopt.cmake
+++ b/xs/src/libnest2d/cmake_modules/DownloadNLopt.cmake
@@ -27,5 +27,6 @@ set(NLOPT_LINK_PYTHON OFF CACHE BOOL "" FORCE)
 add_subdirectory(${nlopt_SOURCE_DIR} ${nlopt_BINARY_DIR})
 
 set(NLopt_LIBS nlopt)
-set(NLopt_INCLUDE_DIR ${nlopt_BINARY_DIR})
+set(NLopt_INCLUDE_DIR ${nlopt_BINARY_DIR} 
+                      ${nlopt_BINARY_DIR}/src/api)
 set(SHARED_LIBS_STATE ${SHARED_STATE})
\ No newline at end of file
diff --git a/xs/src/libnest2d/cmake_modules/FindGMP.cmake b/xs/src/libnest2d/cmake_modules/FindGMP.cmake
deleted file mode 100644
index db173bc90..000000000
--- a/xs/src/libnest2d/cmake_modules/FindGMP.cmake
+++ /dev/null
@@ -1,35 +0,0 @@
-# Try to find the GMP libraries:
-# GMP_FOUND - System has GMP lib
-# GMP_INCLUDE_DIR - The GMP include directory
-# GMP_LIBRARIES - Libraries needed to use GMP
-
-if (GMP_INCLUDE_DIR AND GMP_LIBRARIES)
-	# Force search at every time, in case configuration changes
-	unset(GMP_INCLUDE_DIR CACHE)
-	unset(GMP_LIBRARIES CACHE)
-endif (GMP_INCLUDE_DIR AND GMP_LIBRARIES)
-
-find_path(GMP_INCLUDE_DIR NAMES gmp.h)
-
-if(WIN32)
-	find_library(GMP_LIBRARIES NAMES libgmp.a gmp gmp.lib mpir mpir.lib)
-else(WIN32)
-	if(STBIN)
-		message(STATUS "STBIN: ${STBIN}")
-		find_library(GMP_LIBRARIES NAMES libgmp.a gmp)
-	else(STBIN)
-		find_library(GMP_LIBRARIES NAMES libgmp.so gmp)
-	endif(STBIN)
-endif(WIN32)
-
-if(GMP_INCLUDE_DIR AND GMP_LIBRARIES)
-   set(GMP_FOUND TRUE)
-endif(GMP_INCLUDE_DIR AND GMP_LIBRARIES)
-
-if(GMP_FOUND)
-	message(STATUS "Configured GMP: ${GMP_LIBRARIES}")
-else(GMP_FOUND)
-	message(STATUS "Could NOT find GMP")
-endif(GMP_FOUND)
-
-mark_as_advanced(GMP_INCLUDE_DIR GMP_LIBRARIES)
\ No newline at end of file
diff --git a/xs/src/libnest2d/examples/main.cpp b/xs/src/libnest2d/examples/main.cpp
index e5a47161e..d6b2ccc34 100644
--- a/xs/src/libnest2d/examples/main.cpp
+++ b/xs/src/libnest2d/examples/main.cpp
@@ -535,19 +535,34 @@ void arrangeRectangles() {
     proba[0].rotate(Pi/3);
     proba[1].rotate(Pi-Pi/3);
 
+//    std::vector<Item> input(25, Rectangle(70*SCALE, 10*SCALE));
     std::vector<Item> input;
     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(), stegoParts().begin(), stegoParts().end());
 //    input.insert(input.end(), rects.begin(), rects.end());
-    input.insert(input.end(), proba.begin(), proba.end());
+//    input.insert(input.end(), proba.begin(), proba.end());
 //    input.insert(input.end(), crasher.begin(), crasher.end());
 
     Box bin(250*SCALE, 210*SCALE);
+//    PolygonImpl bin = {
+//        {
+//            {25*SCALE, 0},
+//            {0, 25*SCALE},
+//            {0, 225*SCALE},
+//            {25*SCALE, 250*SCALE},
+//            {225*SCALE, 250*SCALE},
+//            {250*SCALE, 225*SCALE},
+//            {250*SCALE, 25*SCALE},
+//            {225*SCALE, 0},
+//            {25*SCALE, 0}
+//        },
+//        {}
+//    };
 
-    Coord min_obj_distance = 6*SCALE;
+    auto min_obj_distance = static_cast<Coord>(0*SCALE);
 
-    using Placer = NfpPlacer;
+    using Placer = strategies::_NofitPolyPlacer<PolygonImpl, Box>;
     using Packer = Arranger<Placer, FirstFitSelection>;
 
     Packer arrange(bin, min_obj_distance);
@@ -556,28 +571,107 @@ void arrangeRectangles() {
     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) {
+    pconf.accuracy = 0.5f;
 
-        auto bb = ShapeLike::boundingBox(pile);
+//    auto bincenter = ShapeLike::boundingBox(bin).center();
+//    pconf.object_function = [&bin, bincenter](
+//            Placer::Pile pile, const Item& item,
+//            double /*area*/, double norm, double penality) {
 
-        auto& sh = pile.back();
-        auto rv = Nfp::referenceVertex(sh);
-        auto c = bin.center();
-        auto d = PointLike::distance(rv, c);
-        double score = double(d)/norm;
+//        using pl = PointLike;
 
-        // 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;
+//        static const double BIG_ITEM_TRESHOLD = 0.2;
+//        static const double GRAVITY_RATIO = 0.5;
+//        static const double DENSITY_RATIO = 1.0 - GRAVITY_RATIO;
 
-        return score;
-    };
+//        // We will treat big items (compared to the print bed) differently
+//        NfpPlacer::Pile bigs;
+//        bigs.reserve(pile.size());
+//        for(auto& p : pile) {
+//            auto pbb = ShapeLike::boundingBox(p);
+//            auto na = std::sqrt(pbb.width()*pbb.height())/norm;
+//            if(na > BIG_ITEM_TRESHOLD) bigs.emplace_back(p);
+//        }
+
+//        // Candidate item bounding box
+//        auto ibb = item.boundingBox();
+
+//        // Calculate the full bounding box of the pile with the candidate item
+//        pile.emplace_back(item.transformedShape());
+//        auto fullbb = ShapeLike::boundingBox(pile);
+//        pile.pop_back();
+
+//        // The bounding box of the big items (they will accumulate in the center
+//        // of the pile
+//        auto bigbb = bigs.empty()? fullbb : ShapeLike::boundingBox(bigs);
+
+//        // The size indicator of the candidate item. This is not the area,
+//        // but almost...
+//        auto itemnormarea = std::sqrt(ibb.width()*ibb.height())/norm;
+
+//        // Will hold the resulting score
+//        double score = 0;
+
+//        if(itemnormarea > BIG_ITEM_TRESHOLD) {
+//            // This branch is for the bigger items..
+//            // Here we will use the closest point of the item bounding box to
+//            // the already arranged pile. So not the bb center nor the a choosen
+//            // corner but whichever is the closest to the center. This will
+//            // prevent unwanted strange arrangements.
+
+//            auto minc = ibb.minCorner(); // bottom left corner
+//            auto maxc = ibb.maxCorner(); // top right corner
+
+//            // top left and bottom right corners
+//            auto top_left = PointImpl{getX(minc), getY(maxc)};
+//            auto bottom_right = PointImpl{getX(maxc), getY(minc)};
+
+//            auto cc = fullbb.center(); // The gravity center
+
+//            // Now the distnce of the gravity center will be calculated to the
+//            // five anchor points and the smallest will be chosen.
+//            std::array<double, 5> dists;
+//            dists[0] = pl::distance(minc, cc);
+//            dists[1] = pl::distance(maxc, cc);
+//            dists[2] = pl::distance(ibb.center(), cc);
+//            dists[3] = pl::distance(top_left, cc);
+//            dists[4] = pl::distance(bottom_right, cc);
+
+//            auto dist = *(std::min_element(dists.begin(), dists.end())) / norm;
+
+//            // Density is the pack density: how big is the arranged pile
+//            auto density = std::sqrt(fullbb.width()*fullbb.height()) / norm;
+
+//            // The score is a weighted sum of the distance from pile center
+//            // and the pile size
+//            score = GRAVITY_RATIO * dist + DENSITY_RATIO * density;
+
+//        } else if(itemnormarea < BIG_ITEM_TRESHOLD && bigs.empty()) {
+//            // If there are no big items, only small, we should consider the
+//            // density here as well to not get silly results
+//            auto bindist = pl::distance(ibb.center(), bincenter) / norm;
+//            auto density = std::sqrt(fullbb.width()*fullbb.height()) / norm;
+//            score = GRAVITY_RATIO * bindist + DENSITY_RATIO * density;
+//        } else {
+//            // Here there are the small items that should be placed around the
+//            // already processed bigger items.
+//            // No need to play around with the anchor points, the center will be
+//            // just fine for small items
+//            score = pl::distance(ibb.center(), bigbb.center()) / norm;
+//        }
+
+//        // If it does not fit into the print bed we will beat it
+//        // 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(!NfpPlacer::wouldFit(fullbb, bin)) score = 2*penality - score;
+
+//        return score;
+//    };
 
     Packer::SelectionConfig sconf;
 //    sconf.allow_parallel = false;
 //    sconf.force_parallel = false;
-//    sconf.try_triplets = false;
+//    sconf.try_triplets = true;
 //    sconf.try_reverse_order = true;
 //    sconf.waste_increment = 0.005;
 
@@ -613,7 +707,7 @@ void arrangeRectangles() {
     std::vector<double> eff;
     eff.reserve(result.size());
 
-    auto bin_area = double(bin.height()*bin.width());
+    auto bin_area = ShapeLike::area<PolygonImpl>(bin);
     for(auto& r : result) {
         double a = 0;
         std::for_each(r.begin(), r.end(), [&a] (Item& e ){ a += e.area(); });
@@ -630,7 +724,7 @@ void arrangeRectangles() {
               << " %" << std::endl;
 
     std::cout << "Bin usage: (";
-    unsigned total = 0;
+    size_t total = 0;
     for(auto& r : result) { std::cout << r.size() << " "; total += r.size(); }
     std::cout << ") Total: " << total << std::endl;
 
@@ -643,10 +737,12 @@ void arrangeRectangles() {
                                         << input.size() - total << " elements!"
                                         << std::endl;
 
-    svg::SVGWriter::Config conf;
+    using SVGWriter = svg::SVGWriter<PolygonImpl>;
+
+    SVGWriter::Config conf;
     conf.mm_in_coord_units = SCALE;
-    svg::SVGWriter svgw(conf);
-    svgw.setSize(bin);
+    SVGWriter svgw(conf);
+    svgw.setSize(Box(250*SCALE, 210*SCALE));
     svgw.writePackGroup(result);
 //    std::for_each(input.begin(), input.end(), [&svgw](Item& item){ svgw.writeItem(item);});
     svgw.save("out");
diff --git a/xs/src/libnest2d/libnest2d.h b/xs/src/libnest2d/libnest2d.h
index 1e0a98f6a..c9e21ecfb 100644
--- a/xs/src/libnest2d/libnest2d.h
+++ b/xs/src/libnest2d/libnest2d.h
@@ -6,7 +6,7 @@
 #include <libnest2d/clipper_backend/clipper_backend.hpp>
 
 // We include the stock optimizers for local and global optimization
-#include <libnest2d/optimizers/simplex.hpp>     // Local subplex for NfpPlacer
+#include <libnest2d/optimizers/subplex.hpp>     // Local subplex for NfpPlacer
 #include <libnest2d/optimizers/genetic.hpp>     // Genetic for min. bounding box
 
 #include <libnest2d/libnest2d.hpp>
diff --git a/xs/src/libnest2d/libnest2d/boost_alg.hpp b/xs/src/libnest2d/libnest2d/boost_alg.hpp
index a50b397d3..67e19fcbd 100644
--- a/xs/src/libnest2d/libnest2d/boost_alg.hpp
+++ b/xs/src/libnest2d/libnest2d/boost_alg.hpp
@@ -8,8 +8,16 @@
 #ifdef __clang__
 #undef _MSC_EXTENSIONS
 #endif
-#include <boost/geometry.hpp>
 
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4267)
+#endif
+#include <boost/geometry.hpp>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
 // this should be removed to not confuse the compiler
 // #include <libnest2d.h>
 
@@ -350,7 +358,7 @@ inline double ShapeLike::area(const PolygonImpl& shape)
 #endif
 
 template<>
-inline bool ShapeLike::isInside(const PointImpl& point,
+inline bool ShapeLike::isInside<PolygonImpl>(const PointImpl& point,
                                 const PolygonImpl& shape)
 {
     return boost::geometry::within(point, shape);
@@ -461,15 +469,6 @@ inline bp2d::Shapes Nfp::merge(const bp2d::Shapes& shapes,
 }
 #endif
 
-//#ifndef DISABLE_BOOST_MINKOWSKI_ADD
-//template<>
-//inline PolygonImpl& Nfp::minkowskiAdd(PolygonImpl& sh,
-//                                      const PolygonImpl& /*other*/)
-//{
-//    return sh;
-//}
-//#endif
-
 #ifndef DISABLE_BOOST_SERIALIZE
 template<> inline std::string ShapeLike::serialize<libnest2d::Formats::SVG>(
         const PolygonImpl& sh, double scale)
diff --git a/xs/src/libnest2d/libnest2d/clipper_backend/clipper_backend.cpp b/xs/src/libnest2d/libnest2d/clipper_backend/clipper_backend.cpp
deleted file mode 100644
index 830d235a3..000000000
--- a/xs/src/libnest2d/libnest2d/clipper_backend/clipper_backend.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//#include "clipper_backend.hpp"
-//#include <atomic>
-
-//namespace libnest2d {
-
-//namespace  {
-
-//class SpinLock {
-//    std::atomic_flag& lck_;
-//public:
-
-//    inline SpinLock(std::atomic_flag& flg): lck_(flg) {}
-
-//    inline void lock() {
-//        while(lck_.test_and_set(std::memory_order_acquire)) {}
-//    }
-
-//    inline void unlock() { lck_.clear(std::memory_order_release); }
-//};
-
-//class HoleCache {
-//    friend struct libnest2d::ShapeLike;
-
-//    std::unordered_map< const PolygonImpl*, ClipperLib::Paths> map;
-
-//    ClipperLib::Paths& _getHoles(const PolygonImpl* p) {
-//        static std::atomic_flag flg = ATOMIC_FLAG_INIT;
-//        SpinLock lock(flg);
-
-//        lock.lock();
-//        ClipperLib::Paths& paths = map[p];
-//        lock.unlock();
-
-//        if(paths.size() != p->Childs.size()) {
-//            paths.reserve(p->Childs.size());
-
-//            for(auto np : p->Childs) {
-//                paths.emplace_back(np->Contour);
-//            }
-//        }
-
-//        return paths;
-//    }
-
-//    ClipperLib::Paths& getHoles(PolygonImpl& p) {
-//        return _getHoles(&p);
-//    }
-
-//    const ClipperLib::Paths& getHoles(const PolygonImpl& p) {
-//        return _getHoles(&p);
-//    }
-//};
-//}
-
-//HoleCache holeCache;
-
-//}
-
diff --git a/xs/src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp b/xs/src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp
index 8cc27573a..15ceb1576 100644
--- a/xs/src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp
+++ b/xs/src/libnest2d/libnest2d/clipper_backend/clipper_backend.hpp
@@ -21,7 +21,7 @@ struct PolygonImpl {
     PathImpl Contour;
     HoleStore Holes;
 
-    inline PolygonImpl() {}
+    inline PolygonImpl() = default;
 
     inline explicit PolygonImpl(const PathImpl& cont): Contour(cont) {}
     inline explicit PolygonImpl(const HoleStore& holes):
@@ -66,6 +66,19 @@ inline PointImpl operator-(const PointImpl& p1, const PointImpl& p2) {
     ret -= p2;
     return ret;
 }
+
+inline PointImpl& operator *=(PointImpl& p, const PointImpl& pa ) {
+    p.X *= pa.X;
+    p.Y *= pa.Y;
+    return p;
+}
+
+inline PointImpl operator*(const PointImpl& p1, const PointImpl& p2) {
+    PointImpl ret = p1;
+    ret *= p2;
+    return ret;
+}
+
 }
 
 namespace libnest2d {
@@ -135,7 +148,7 @@ inline void ShapeLike::reserve(PolygonImpl& sh, size_t vertex_capacity)
 
 namespace _smartarea {
 template<Orientation o>
-inline double area(const PolygonImpl& sh) {
+inline double area(const PolygonImpl& /*sh*/) {
     return std::nan("");
 }
 
@@ -220,22 +233,6 @@ inline void ShapeLike::offset(PolygonImpl& sh, TCoord<PointImpl> distance) {
     }
 }
 
-//template<> // TODO make it support holes if this method will ever be needed.
-//inline PolygonImpl Nfp::minkowskiDiff(const PolygonImpl& sh,
-//                                      const PolygonImpl& other)
-//{
-//    #define DISABLE_BOOST_MINKOWSKI_ADD
-
-//    ClipperLib::Paths solution;
-
-//    ClipperLib::MinkowskiDiff(sh.Contour, other.Contour, solution);
-
-//    PolygonImpl ret;
-//    ret.Contour = solution.front();
-
-//    return sh;
-//}
-
 // Tell libnest2d how to make string out of a ClipperPolygon object
 template<> inline std::string ShapeLike::toString(const PolygonImpl& sh) {
     std::stringstream ss;
@@ -406,35 +403,12 @@ inline void ShapeLike::rotate(PolygonImpl& sh, const Radians& rads)
 }
 
 #define DISABLE_BOOST_NFP_MERGE
-template<> inline Nfp::Shapes<PolygonImpl>
-Nfp::merge(const Nfp::Shapes<PolygonImpl>& shapes, const PolygonImpl& sh)
-{
+inline Nfp::Shapes<PolygonImpl> _merge(ClipperLib::Clipper& clipper) {
     Nfp::Shapes<PolygonImpl> retv;
 
-    ClipperLib::Clipper clipper(ClipperLib::ioReverseSolution);
-
-    bool closed = true;
-    bool valid = false;
-
-    valid = clipper.AddPath(sh.Contour, ClipperLib::ptSubject, closed);
-
-    for(auto& hole : sh.Holes) {
-        valid &= clipper.AddPath(hole, ClipperLib::ptSubject, closed);
-    }
-
-    for(auto& path : shapes) {
-        valid &= clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed);
-
-        for(auto& hole : path.Holes) {
-            valid &= clipper.AddPath(hole, ClipperLib::ptSubject, closed);
-        }
-    }
-
-    if(!valid) throw GeometryException(GeomErr::MERGE);
-
     ClipperLib::PolyTree result;
-    clipper.Execute(ClipperLib::ctUnion, result, ClipperLib::pftNonZero);
-    retv.reserve(result.Total());
+    clipper.Execute(ClipperLib::ctUnion, result, ClipperLib::pftNegative);
+    retv.reserve(static_cast<size_t>(result.Total()));
 
     std::function<void(ClipperLib::PolyNode*, PolygonImpl&)> processHole;
 
@@ -445,7 +419,8 @@ Nfp::merge(const Nfp::Shapes<PolygonImpl>& shapes, const PolygonImpl& sh)
         retv.push_back(poly);
     };
 
-    processHole = [&processPoly](ClipperLib::PolyNode *pptr, PolygonImpl& poly) {
+    processHole = [&processPoly](ClipperLib::PolyNode *pptr, PolygonImpl& poly)
+    {
         poly.Holes.push_back(pptr->Contour);
         poly.Holes.back().push_back(poly.Holes.back().front());
         for(auto c : pptr->Childs) processPoly(c);
@@ -463,6 +438,27 @@ Nfp::merge(const Nfp::Shapes<PolygonImpl>& shapes, const PolygonImpl& sh)
     return retv;
 }
 
+template<> inline Nfp::Shapes<PolygonImpl>
+Nfp::merge(const Nfp::Shapes<PolygonImpl>& shapes)
+{
+    ClipperLib::Clipper clipper(ClipperLib::ioReverseSolution);
+
+    bool closed = true;
+    bool valid = true;
+
+    for(auto& path : shapes) {
+        valid &= clipper.AddPath(path.Contour, ClipperLib::ptSubject, closed);
+
+        for(auto& hole : path.Holes) {
+            valid &= clipper.AddPath(hole, ClipperLib::ptSubject, closed);
+        }
+    }
+
+    if(!valid) throw GeometryException(GeomErr::MERGE);
+
+    return _merge(clipper);
+}
+
 }
 
 //#define DISABLE_BOOST_SERIALIZE
diff --git a/xs/src/libnest2d/libnest2d/common.hpp b/xs/src/libnest2d/libnest2d/common.hpp
index 18f313712..6867f76f3 100644
--- a/xs/src/libnest2d/libnest2d/common.hpp
+++ b/xs/src/libnest2d/libnest2d/common.hpp
@@ -13,6 +13,7 @@
 #if defined(_MSC_VER) &&  _MSC_VER <= 1800 || __cplusplus < 201103L
     #define BP2D_NOEXCEPT
     #define BP2D_CONSTEXPR
+    #define BP2D_COMPILER_MSVC12
 #elif __cplusplus >= 201103L
     #define BP2D_NOEXCEPT noexcept
     #define BP2D_CONSTEXPR constexpr
@@ -84,44 +85,6 @@ struct invoke_result {
 template<class F, class...Args>
 using invoke_result_t = typename invoke_result<F, Args...>::type;
 
-/* ************************************************************************** */
-/* C++14 std::index_sequence implementation:                                  */
-/* ************************************************************************** */
-
-/**
- * \brief C++11 conformant implementation of the index_sequence type from C++14
- */
-template<size_t...Ints> struct index_sequence {
-    using value_type = size_t;
-    BP2D_CONSTEXPR value_type size() const { return sizeof...(Ints); }
-};
-
-// A Help structure to generate the integer list
-template<size_t...Nseq> struct genSeq;
-
-// Recursive template to generate the list
-template<size_t I, size_t...Nseq> struct genSeq<I, Nseq...> {
-    // Type will contain a genSeq with Nseq appended by one element
-    using Type = typename genSeq< I - 1, I - 1, Nseq...>::Type;
-};
-
-// Terminating recursion
-template <size_t ... Nseq> struct genSeq<0, Nseq...> {
-    // If I is zero, Type will contain index_sequence with the fuly generated
-    // integer list.
-    using Type = index_sequence<Nseq...>;
-};
-
-/// Helper alias to make an index sequence from 0 to N
-template<size_t N> using make_index_sequence = typename genSeq<N>::Type;
-
-/// Helper alias to make an index sequence for a parameter pack
-template<class...Args>
-using index_sequence_for = make_index_sequence<sizeof...(Args)>;
-
-
-/* ************************************************************************** */
-
 /**
  * A useful little tool for triggering static_assert error messages e.g. when
  * a mandatory template specialization (implementation) is missing.
@@ -229,7 +192,7 @@ public:
 
     GeomErr errcode() const { return errcode_; }
 
-    virtual const char * what() const BP2D_NOEXCEPT override {
+    const char * what() const BP2D_NOEXCEPT override {
         return errorstr(errcode_).c_str();
     }
 };
diff --git a/xs/src/libnest2d/libnest2d/geometry_traits.hpp b/xs/src/libnest2d/libnest2d/geometry_traits.hpp
index dbd609201..058c47cd4 100644
--- a/xs/src/libnest2d/libnest2d/geometry_traits.hpp
+++ b/xs/src/libnest2d/libnest2d/geometry_traits.hpp
@@ -3,6 +3,7 @@
 
 #include <string>
 #include <type_traits>
+#include <algorithm>
 #include <array>
 #include <vector>
 #include <numeric>
@@ -68,7 +69,7 @@ class _Box: PointPair<RawPoint> {
     using PointPair<RawPoint>::p2;
 public:
 
-    inline _Box() {}
+    inline _Box() = default;
     inline _Box(const RawPoint& p, const RawPoint& pp):
         PointPair<RawPoint>({p, pp}) {}
 
@@ -85,6 +86,31 @@ public:
     inline TCoord<RawPoint> height() const BP2D_NOEXCEPT;
 
     inline RawPoint center() const BP2D_NOEXCEPT;
+
+    inline double area() const BP2D_NOEXCEPT {
+        return double(width()*height());
+    }
+};
+
+template<class RawPoint>
+class _Circle {
+    RawPoint center_;
+    double radius_ = 0;
+public:
+
+    _Circle() = default;
+
+    _Circle(const RawPoint& center, double r): center_(center), radius_(r) {}
+
+    inline const RawPoint& center() const BP2D_NOEXCEPT { return center_; }
+    inline const void center(const RawPoint& c) { center_ = c; }
+
+    inline double radius() const BP2D_NOEXCEPT { return radius_; }
+    inline void radius(double r) { radius_ = r; }
+
+    inline double area() const BP2D_NOEXCEPT {
+        return 2.0*Pi*radius_;
+    }
 };
 
 /**
@@ -97,7 +123,7 @@ class _Segment: PointPair<RawPoint> {
     mutable Radians angletox_ = std::nan("");
 public:
 
-    inline _Segment() {}
+    inline _Segment() = default;
 
     inline _Segment(const RawPoint& p, const RawPoint& pp):
         PointPair<RawPoint>({p, pp}) {}
@@ -188,7 +214,7 @@ struct PointLike {
 
         if( (y < y1 && y < y2) || (y > y1 && y > y2) )
             return {0, false};
-        else if ((y == y1 && y == y2) && (x > x1 && x > x2))
+        if ((y == y1 && y == y2) && (x > x1 && x > x2))
             ret = std::min( x-x1, x -x2);
         else if( (y == y1 && y == y2) && (x < x1 && x < x2))
             ret = -std::min(x1 - x, x2 - x);
@@ -214,7 +240,7 @@ struct PointLike {
 
         if( (x < x1 && x < x2) || (x > x1 && x > x2) )
             return {0, false};
-        else if ((x == x1 && x == x2) && (y > y1 && y > y2))
+        if ((x == x1 && x == x2) && (y > y1 && y > y2))
             ret = std::min( y-y1, y -y2);
         else if( (x == x1 && x == x2) && (y < y1 && y < y2))
             ret = -std::min(y1 - y, y2 - y);
@@ -329,7 +355,7 @@ enum class Formats {
 };
 
 // This struct serves as a namespace. The only difference is that it can be
-// used in friend declarations.
+// used in friend declarations and can be aliased at class scope.
 struct ShapeLike {
 
     template<class RawShape>
@@ -361,6 +387,51 @@ struct ShapeLike {
         return create<RawShape>(contour, {});
     }
 
+    template<class RawShape>
+    static THolesContainer<RawShape>& holes(RawShape& /*sh*/)
+    {
+        static THolesContainer<RawShape> empty;
+        return empty;
+    }
+
+    template<class RawShape>
+    static const THolesContainer<RawShape>& holes(const RawShape& /*sh*/)
+    {
+        static THolesContainer<RawShape> empty;
+        return empty;
+    }
+
+    template<class RawShape>
+    static TContour<RawShape>& getHole(RawShape& sh, unsigned long idx)
+    {
+        return holes(sh)[idx];
+    }
+
+    template<class RawShape>
+    static const TContour<RawShape>& getHole(const RawShape& sh,
+                                              unsigned long idx)
+    {
+        return holes(sh)[idx];
+    }
+
+    template<class RawShape>
+    static size_t holeCount(const RawShape& sh)
+    {
+        return holes(sh).size();
+    }
+
+    template<class RawShape>
+    static TContour<RawShape>& getContour(RawShape& sh)
+    {
+        return sh;
+    }
+
+    template<class RawShape>
+    static const TContour<RawShape>& getContour(const RawShape& sh)
+    {
+        return sh;
+    }
+
     // Optional, does nothing by default
     template<class RawShape>
     static void reserve(RawShape& /*sh*/,  size_t /*vertex_capacity*/) {}
@@ -402,7 +473,7 @@ struct ShapeLike {
     }
 
     template<Formats, class RawShape>
-    static std::string serialize(const RawShape& /*sh*/, double scale=1)
+    static std::string serialize(const RawShape& /*sh*/, double /*scale*/=1)
     {
         static_assert(always_false<RawShape>::value,
                       "ShapeLike::serialize() unimplemented!");
@@ -498,51 +569,6 @@ struct ShapeLike {
         return RawShape();
     }
 
-    template<class RawShape>
-    static THolesContainer<RawShape>& holes(RawShape& /*sh*/)
-    {
-        static THolesContainer<RawShape> empty;
-        return empty;
-    }
-
-    template<class RawShape>
-    static const THolesContainer<RawShape>& holes(const RawShape& /*sh*/)
-    {
-        static THolesContainer<RawShape> empty;
-        return empty;
-    }
-
-    template<class RawShape>
-    static TContour<RawShape>& getHole(RawShape& sh, unsigned long idx)
-    {
-        return holes(sh)[idx];
-    }
-
-    template<class RawShape>
-    static const TContour<RawShape>& getHole(const RawShape& sh,
-                                              unsigned long idx)
-    {
-        return holes(sh)[idx];
-    }
-
-    template<class RawShape>
-    static size_t holeCount(const RawShape& sh)
-    {
-        return holes(sh).size();
-    }
-
-    template<class RawShape>
-    static TContour<RawShape>& getContour(RawShape& sh)
-    {
-        return sh;
-    }
-
-    template<class RawShape>
-    static const TContour<RawShape>& getContour(const RawShape& sh)
-    {
-        return sh;
-    }
-
     template<class RawShape>
     static void rotate(RawShape& /*sh*/, const Radians& /*rads*/)
     {
@@ -614,6 +640,22 @@ struct ShapeLike {
         return box;
     }
 
+    template<class RawShape>
+    static inline _Box<TPoint<RawShape>> boundingBox(
+            const _Circle<TPoint<RawShape>>& circ)
+    {
+        using Coord = TCoord<TPoint<RawShape>>;
+        TPoint<RawShape> pmin = {
+            static_cast<Coord>(getX(circ.center()) - circ.radius()),
+            static_cast<Coord>(getY(circ.center()) - circ.radius()) };
+
+        TPoint<RawShape> pmax = {
+            static_cast<Coord>(getX(circ.center()) + circ.radius()),
+            static_cast<Coord>(getY(circ.center()) + circ.radius()) };
+
+        return {pmin, pmax};
+    }
+
     template<class RawShape>
     static inline double area(const _Box<TPoint<RawShape>>& box)
     {
@@ -621,14 +663,74 @@ struct ShapeLike {
     }
 
     template<class RawShape>
-    static double area(const Shapes<RawShape>& shapes)
+    static inline double area(const _Circle<TPoint<RawShape>>& circ)
     {
-        double ret = 0;
-        std::accumulate(shapes.first(), shapes.end(),
-                        [](const RawShape& a, const RawShape& b) {
-            return area(a) + area(b);
+        return circ.area();
+    }
+
+    template<class RawShape>
+    static inline double area(const Shapes<RawShape>& shapes)
+    {
+        return std::accumulate(shapes.begin(), shapes.end(), 0.0,
+                        [](double a, const RawShape& b) {
+            return a += area(b);
         });
-        return ret;
+    }
+
+    template<class RawShape>
+    static bool isInside(const TPoint<RawShape>& point,
+                         const _Circle<TPoint<RawShape>>& circ)
+    {
+        return PointLike::distance(point, circ.center()) < circ.radius();
+    }
+
+    template<class RawShape>
+    static bool isInside(const TPoint<RawShape>& point,
+                         const _Box<TPoint<RawShape>>& box)
+    {
+        auto px = getX(point);
+        auto py = getY(point);
+        auto minx = getX(box.minCorner());
+        auto miny = getY(box.minCorner());
+        auto maxx = getX(box.maxCorner());
+        auto maxy = getY(box.maxCorner());
+
+        return px > minx && px < maxx && py > miny && py < maxy;
+    }
+
+    template<class RawShape>
+    static bool isInside(const RawShape& sh,
+                         const _Circle<TPoint<RawShape>>& circ)
+    {
+        return std::all_of(cbegin(sh), cend(sh),
+                           [&circ](const TPoint<RawShape>& p){
+            return isInside<RawShape>(p, circ);
+        });
+    }
+
+    template<class RawShape>
+    static bool isInside(const _Box<TPoint<RawShape>>& box,
+                         const _Circle<TPoint<RawShape>>& circ)
+    {
+        return isInside<RawShape>(box.minCorner(), circ) &&
+                isInside<RawShape>(box.maxCorner(), circ);
+    }
+
+    template<class RawShape>
+    static bool isInside(const _Box<TPoint<RawShape>>& ibb,
+                         const _Box<TPoint<RawShape>>& box)
+    {
+        auto iminX = getX(ibb.minCorner());
+        auto imaxX = getX(ibb.maxCorner());
+        auto iminY = getY(ibb.minCorner());
+        auto imaxY = getY(ibb.maxCorner());
+
+        auto minX = getX(box.minCorner());
+        auto maxX = getX(box.maxCorner());
+        auto minY = getY(box.minCorner());
+        auto maxY = getY(box.maxCorner());
+
+        return iminX > minX && imaxX < maxX && iminY > minY && imaxY < maxY;
     }
 
     template<class RawShape> // Potential O(1) implementation may exist
diff --git a/xs/src/libnest2d/libnest2d/geometry_traits_nfp.hpp b/xs/src/libnest2d/libnest2d/geometry_traits_nfp.hpp
index 581b6bed0..90cf21be5 100644
--- a/xs/src/libnest2d/libnest2d/geometry_traits_nfp.hpp
+++ b/xs/src/libnest2d/libnest2d/geometry_traits_nfp.hpp
@@ -3,7 +3,9 @@
 
 #include "geometry_traits.hpp"
 #include <algorithm>
+#include <functional>
 #include <vector>
+#include <iterator>
 
 namespace libnest2d {
 
@@ -23,64 +25,22 @@ struct Nfp {
 template<class RawShape>
 using Shapes = typename ShapeLike::Shapes<RawShape>;
 
-/// Minkowski addition (not used yet)
+/**
+ * Merge a bunch of polygons with the specified additional polygon.
+ *
+ * \tparam RawShape the Polygon data type.
+ * \param shc The pile of polygons that will be unified with sh.
+ * \param sh A single polygon to unify with shc.
+ *
+ * \return A set of polygons that is the union of the input polygons. Note that
+ * mostly it will be a set containing only one big polygon but if the input
+ * polygons are disjuct than the resulting set will contain more polygons.
+ */
 template<class RawShape>
-static RawShape minkowskiDiff(const RawShape& sh, const RawShape& cother)
+static Shapes<RawShape> merge(const Shapes<RawShape>& /*shc*/)
 {
-    using Vertex = TPoint<RawShape>;
-    //using Coord = TCoord<Vertex>;
-    using Edge = _Segment<Vertex>;
-    using sl = ShapeLike;
-    using std::signbit;
-
-    // Copy the orbiter (controur only), we will have to work on it
-    RawShape orbiter = sl::create(sl::getContour(cother));
-
-    // Make the orbiter reverse oriented
-    for(auto &v : sl::getContour(orbiter)) v = -v;
-
-    // An egde with additional data for marking it
-    struct MarkedEdge { Edge e; Radians turn_angle; bool is_turning_point; };
-
-    // Container for marked edges
-    using EdgeList = std::vector<MarkedEdge>;
-
-    EdgeList A, B;
-
-    auto fillEdgeList = [](EdgeList& L, const RawShape& poly) {
-        L.reserve(sl::contourVertexCount(poly));
-
-        auto it = sl::cbegin(poly);
-        auto nextit = std::next(it);
-
-        L.emplace_back({Edge(*it, *nextit), 0, false});
-        it++; nextit++;
-
-        while(nextit != sl::cend(poly)) {
-            Edge e(*it, *nextit);
-            auto& L_prev = L.back();
-            auto phi = L_prev.e.angleToXaxis();
-            auto phi_prev = e.angleToXaxis();
-            auto turn_angle = phi-phi_prev;
-            if(turn_angle > Pi) turn_angle -= 2*Pi;
-            L.emplace_back({
-                              e,
-                              turn_angle,
-                              signbit(turn_angle) != signbit(L_prev.turn_angle)
-                           });
-            it++; nextit++;
-        }
-
-        L.front().turn_angle = L.front().e.angleToXaxis() -
-                               L.back().e.angleToXaxis();
-
-        if(L.front().turn_angle > Pi) L.front().turn_angle -= 2*Pi;
-    };
-
-    fillEdgeList(A, sh);
-    fillEdgeList(B, orbiter);
-
-    return sh;
+    static_assert(always_false<RawShape>::value,
+                  "Nfp::merge(shapes, shape) unimplemented!");
 }
 
 /**
@@ -95,10 +55,12 @@ static RawShape minkowskiDiff(const RawShape& sh, const RawShape& cother)
  * polygons are disjuct than the resulting set will contain more polygons.
  */
 template<class RawShape>
-static Shapes<RawShape> merge(const Shapes<RawShape>& shc, const RawShape& sh)
+static Shapes<RawShape> merge(const Shapes<RawShape>& shc,
+                              const RawShape& sh)
 {
-    static_assert(always_false<RawShape>::value,
-                  "Nfp::merge(shapes, shape) unimplemented!");
+    auto m = merge(shc);
+    m.push_back(sh);
+    return merge(m);
 }
 
 /**
@@ -139,16 +101,20 @@ template<class RawShape>
 static TPoint<RawShape> rightmostUpVertex(const RawShape& sh)
 {
 
-    // find min x and min y vertex
+    // find max x and max y vertex
     auto it = std::max_element(ShapeLike::cbegin(sh), ShapeLike::cend(sh),
                                _vsort<RawShape>);
 
     return *it;
 }
 
+template<class RawShape>
+using NfpResult = std::pair<RawShape, TPoint<RawShape>>;
+
 /// Helper function to get the NFP
 template<NfpLevel nfptype, class RawShape>
-static RawShape noFitPolygon(const RawShape& sh, const RawShape& other)
+static NfpResult<RawShape> noFitPolygon(const RawShape& sh,
+                                        const RawShape& other)
 {
     NfpImpl<RawShape, nfptype> nfp;
     return nfp(sh, other);
@@ -167,44 +133,46 @@ static RawShape noFitPolygon(const RawShape& sh, const RawShape& other)
  * \tparam RawShape the Polygon data type.
  * \param sh The stationary polygon
  * \param cother The orbiting polygon
- * \return Returns the NFP of the two input polygons which have to be strictly
- * convex. The resulting NFP is proven to be convex as well in this case.
+ * \return Returns a pair of the NFP and its reference vertex of the two input
+ * polygons which have to be strictly convex. The resulting NFP is proven to be
+ * convex as well in this case.
  *
  */
 template<class RawShape>
-static RawShape nfpConvexOnly(const RawShape& sh, const RawShape& cother)
+static NfpResult<RawShape> nfpConvexOnly(const RawShape& sh,
+                                         const RawShape& other)
 {
     using Vertex = TPoint<RawShape>; using Edge = _Segment<Vertex>;
-
-    RawShape other = cother;
-
-    // Make the other polygon counter-clockwise
-    std::reverse(ShapeLike::begin(other), ShapeLike::end(other));
+    using sl = ShapeLike;
 
     RawShape rsh;   // Final nfp placeholder
+    Vertex top_nfp;
     std::vector<Edge> edgelist;
 
-    auto cap = ShapeLike::contourVertexCount(sh) +
-            ShapeLike::contourVertexCount(other);
+    auto cap = sl::contourVertexCount(sh) + sl::contourVertexCount(other);
 
     // Reserve the needed memory
     edgelist.reserve(cap);
-    ShapeLike::reserve(rsh, static_cast<unsigned long>(cap));
+    sl::reserve(rsh, static_cast<unsigned long>(cap));
 
     { // place all edges from sh into edgelist
-        auto first = ShapeLike::cbegin(sh);
-        auto next = first + 1;
-        auto endit = ShapeLike::cend(sh);
+        auto first = sl::cbegin(sh);
+        auto next = std::next(first);
 
-        while(next != endit) edgelist.emplace_back(*(first++), *(next++));
+        while(next != sl::cend(sh)) {
+            edgelist.emplace_back(*(first), *(next));
+            ++first; ++next;
+        }
     }
 
     { // place all edges from other into edgelist
-        auto first = ShapeLike::cbegin(other);
-        auto next = first + 1;
-        auto endit = ShapeLike::cend(other);
+        auto first = sl::cbegin(other);
+        auto next = std::next(first);
 
-        while(next != endit) edgelist.emplace_back(*(first++), *(next++));
+        while(next != sl::cend(other)) {
+            edgelist.emplace_back(*(next), *(first));
+            ++first; ++next;
+        }
     }
 
     // Sort the edges by angle to X axis.
@@ -215,10 +183,16 @@ static RawShape nfpConvexOnly(const RawShape& sh, const RawShape& cother)
     });
 
     // Add the two vertices from the first edge into the final polygon.
-    ShapeLike::addVertex(rsh, edgelist.front().first());
-    ShapeLike::addVertex(rsh, edgelist.front().second());
+    sl::addVertex(rsh, edgelist.front().first());
+    sl::addVertex(rsh, edgelist.front().second());
 
-    auto tmp = std::next(ShapeLike::begin(rsh));
+    // Sorting function for the nfp reference vertex search
+    auto& cmp = _vsort<RawShape>;
+
+    // the reference (rightmost top) vertex so far
+    top_nfp = *std::max_element(sl::cbegin(rsh), sl::cend(rsh), cmp );
+
+    auto tmp = std::next(sl::begin(rsh));
 
     // Construct final nfp by placing each edge to the end of the previous
     for(auto eit = std::next(edgelist.begin());
@@ -226,56 +200,325 @@ static RawShape nfpConvexOnly(const RawShape& sh, const RawShape& cother)
         ++eit)
     {
         auto d = *tmp - eit->first();
-        auto p = eit->second() + d;
+        Vertex p = eit->second() + d;
 
-        ShapeLike::addVertex(rsh, p);
+        sl::addVertex(rsh, p);
+
+        // Set the new reference vertex
+        if(cmp(top_nfp, p)) top_nfp = p;
 
         tmp = std::next(tmp);
     }
 
-    // Now we have an nfp somewhere in the dark. We need to get it
-    // to the right position around the stationary shape.
-    // This is done by choosing the leftmost lowest vertex of the
-    // orbiting polygon to be touched with the rightmost upper
-    // vertex of the stationary polygon. In this configuration, the
-    // reference vertex of the orbiting polygon (which can be dragged around
-    // the nfp) will be its rightmost upper vertex that coincides with the
-    // rightmost upper vertex of the nfp. No proof provided other than Jonas
-    // Lindmark's reasoning about the reference vertex of nfp in his thesis
-    // ("No fit polygon problem" - section 2.1.9)
+    return {rsh, top_nfp};
+}
 
-    // TODO: dont do this here. Cache the rmu and lmd in Item and get translate
-    // the nfp after this call
+template<class RawShape>
+static NfpResult<RawShape> nfpSimpleSimple(const RawShape& cstationary,
+                                           const RawShape& cother)
+{
 
-    auto csh = sh;  // Copy sh, we will sort the verices in the copy
-    auto& cmp = _vsort<RawShape>;
-    std::sort(ShapeLike::begin(csh), ShapeLike::end(csh), cmp);
-    std::sort(ShapeLike::begin(other), ShapeLike::end(other), cmp);
+    // Algorithms are from the original algorithm proposed in paper:
+    // https://eprints.soton.ac.uk/36850/1/CORMSIS-05-05.pdf
 
-    // leftmost lower vertex of the stationary polygon
-    auto& touch_sh = *(std::prev(ShapeLike::end(csh)));
-    // rightmost upper vertex of the orbiting polygon
-    auto& touch_other = *(ShapeLike::begin(other));
+    // /////////////////////////////////////////////////////////////////////////
+    // Algorithm 1: Obtaining the minkowski sum
+    // /////////////////////////////////////////////////////////////////////////
 
-    // Calculate the difference and move the orbiter to the touch position.
-    auto dtouch = touch_sh - touch_other;
-    auto top_other = *(std::prev(ShapeLike::end(other))) + dtouch;
+    // I guess this is not a full minkowski sum of the two input polygons by
+    // definition. This yields a subset that is compatible with the next 2
+    // algorithms.
 
-    // Get the righmost upper vertex of the nfp and move it to the RMU of
-    // the orbiter because they should coincide.
-    auto&& top_nfp = rightmostUpVertex(rsh);
-    auto dnfp = top_other - top_nfp;
-    std::for_each(ShapeLike::begin(rsh), ShapeLike::end(rsh),
-                  [&dnfp](Vertex& v) { v+= dnfp; } );
+    using Result = NfpResult<RawShape>;
+    using Vertex = TPoint<RawShape>;
+    using Coord = TCoord<Vertex>;
+    using Edge = _Segment<Vertex>;
+    using sl = ShapeLike;
+    using std::signbit;
+    using std::sort;
+    using std::vector;
+    using std::ref;
+    using std::reference_wrapper;
 
-    return rsh;
+    // TODO The original algorithms expects the stationary polygon in
+    // counter clockwise and the orbiter in clockwise order.
+    // So for preventing any further complication, I will make the input
+    // the way it should be, than make my way around the orientations.
+
+    // Reverse the stationary contour to counter clockwise
+    auto stcont = sl::getContour(cstationary);
+    std::reverse(stcont.begin(), stcont.end());
+    RawShape stationary;
+    sl::getContour(stationary) = stcont;
+
+    // Reverse the orbiter contour to counter clockwise
+    auto orbcont = sl::getContour(cother);
+
+    std::reverse(orbcont.begin(), orbcont.end());
+
+    // Copy the orbiter (contour only), we will have to work on it
+    RawShape orbiter;
+    sl::getContour(orbiter) = orbcont;
+
+    // Step 1: Make the orbiter reverse oriented
+    for(auto &v : sl::getContour(orbiter)) v = -v;
+
+    // An egde with additional data for marking it
+    struct MarkedEdge {
+        Edge e; Radians turn_angle = 0; bool is_turning_point = false;
+        MarkedEdge() = default;
+        MarkedEdge(const Edge& ed, Radians ta, bool tp):
+            e(ed), turn_angle(ta), is_turning_point(tp) {}
+    };
+
+    // Container for marked edges
+    using EdgeList = vector<MarkedEdge>;
+
+    EdgeList A, B;
+
+    // This is how an edge list is created from the polygons
+    auto fillEdgeList = [](EdgeList& L, const RawShape& poly, int dir) {
+        L.reserve(sl::contourVertexCount(poly));
+
+        auto it = sl::cbegin(poly);
+        auto nextit = std::next(it);
+
+        double turn_angle = 0;
+        bool is_turn_point = false;
+
+        while(nextit != sl::cend(poly)) {
+            L.emplace_back(Edge(*it, *nextit), turn_angle, is_turn_point);
+            it++; nextit++;
+        }
+
+        auto getTurnAngle = [](const Edge& e1, const Edge& e2) {
+            auto phi = e1.angleToXaxis();
+            auto phi_prev = e2.angleToXaxis();
+            auto TwoPi = 2.0*Pi;
+            if(phi > Pi) phi -= TwoPi;
+            if(phi_prev > Pi) phi_prev -= TwoPi;
+            auto turn_angle = phi-phi_prev;
+            if(turn_angle > Pi) turn_angle -= TwoPi;
+            return phi-phi_prev;
+        };
+
+        if(dir > 0) {
+            auto eit = L.begin();
+            auto enext = std::next(eit);
+
+            eit->turn_angle = getTurnAngle(L.front().e, L.back().e);
+
+            while(enext != L.end()) {
+                enext->turn_angle = getTurnAngle( enext->e, eit->e);
+                enext->is_turning_point =
+                        signbit(enext->turn_angle) != signbit(eit->turn_angle);
+                ++eit; ++enext;
+            }
+
+            L.front().is_turning_point = signbit(L.front().turn_angle) !=
+                                         signbit(L.back().turn_angle);
+        } else {
+            std::cout << L.size() << std::endl;
+
+            auto eit = L.rbegin();
+            auto enext = std::next(eit);
+
+            eit->turn_angle = getTurnAngle(L.back().e, L.front().e);
+
+            while(enext != L.rend()) {
+                enext->turn_angle = getTurnAngle(enext->e, eit->e);
+                enext->is_turning_point =
+                        signbit(enext->turn_angle) != signbit(eit->turn_angle);
+                std::cout << enext->is_turning_point << " " << enext->turn_angle << std::endl;
+
+                ++eit; ++enext;
+            }
+
+            L.back().is_turning_point = signbit(L.back().turn_angle) !=
+                                        signbit(L.front().turn_angle);
+        }
+    };
+
+    // Step 2: Fill the edgelists
+    fillEdgeList(A, stationary, 1);
+    fillEdgeList(B, orbiter, -1);
+
+    // A reference to a marked edge that also knows its container
+    struct MarkedEdgeRef {
+        reference_wrapper<MarkedEdge> eref;
+        reference_wrapper<vector<MarkedEdgeRef>> container;
+        Coord dir = 1;  // Direction modifier
+
+        inline Radians angleX() const { return eref.get().e.angleToXaxis(); }
+        inline const Edge& edge() const { return eref.get().e; }
+        inline Edge& edge() { return eref.get().e; }
+        inline bool isTurningPoint() const {
+            return eref.get().is_turning_point;
+        }
+        inline bool isFrom(const vector<MarkedEdgeRef>& cont ) {
+            return &(container.get()) == &cont;
+        }
+        inline bool eq(const MarkedEdgeRef& mr) {
+            return &(eref.get()) == &(mr.eref.get());
+        }
+
+        MarkedEdgeRef(reference_wrapper<MarkedEdge> er,
+                      reference_wrapper<vector<MarkedEdgeRef>> ec):
+            eref(er), container(ec), dir(1) {}
+
+        MarkedEdgeRef(reference_wrapper<MarkedEdge> er,
+                      reference_wrapper<vector<MarkedEdgeRef>> ec,
+                      Coord d):
+            eref(er), container(ec), dir(d) {}
+    };
+
+    using EdgeRefList = vector<MarkedEdgeRef>;
+
+    // Comparing two marked edges
+    auto sortfn = [](const MarkedEdgeRef& e1, const MarkedEdgeRef& e2) {
+        return e1.angleX() < e2.angleX();
+    };
+
+    EdgeRefList Aref, Bref;     // We create containers for the references
+    Aref.reserve(A.size()); Bref.reserve(B.size());
+
+    // Fill reference container for the stationary polygon
+    std::for_each(A.begin(), A.end(), [&Aref](MarkedEdge& me) {
+        Aref.emplace_back( ref(me), ref(Aref) );
+    });
+
+    // Fill reference container for the orbiting polygon
+    std::for_each(B.begin(), B.end(), [&Bref](MarkedEdge& me) {
+        Bref.emplace_back( ref(me), ref(Bref) );
+    });
+
+    struct EdgeGroup { typename EdgeRefList::const_iterator first, last; };
+
+    auto mink = [sortfn] // the Mink(Q, R, direction) sub-procedure
+            (const EdgeGroup& Q, const EdgeGroup& R, bool positive)
+    {
+
+        // Step 1 "merge sort_list(Q) and sort_list(R) to form merge_list(Q,R)"
+        // Sort the containers of edge references and merge them.
+        // Q could be sorted only once and be reused here but we would still
+        // need to merge it with sorted(R).
+
+        EdgeRefList merged;
+        EdgeRefList S, seq;
+        merged.reserve((Q.last - Q.first) + (R.last - R.first));
+
+        merged.insert(merged.end(), Q.first, Q.last);
+        merged.insert(merged.end(), R.first, R.last);
+        sort(merged.begin(), merged.end(), sortfn);
+
+        // Step 2 "set i = 1, k = 1, direction = 1, s1 = q1"
+        // we dont use i, instead, q is an iterator into Q. k would be an index
+        // into the merged sequence but we use "it" as an iterator for that
+
+        // here we obtain references for the containers for later comparisons
+        const auto& Rcont = R.first->container.get();
+        const auto& Qcont = Q.first->container.get();
+
+        // Set the intial direction
+        Coord dir = positive? 1 : -1;
+
+        // roughly i = 1 (so q = Q.first) and s1 = q1 so S[0] = q;
+        auto q = Q.first;
+        S.push_back(*q++);
+
+        // Roughly step 3
+        while(q != Q.last) {
+            auto it = merged.begin();
+            while(it != merged.end() && !(it->eq(*(Q.first))) ) {
+                if(it->isFrom(Rcont)) {
+                    auto s = *it;
+                    s.dir = dir;
+                    S.push_back(s);
+                }
+                if(it->eq(*q)) {
+                    S.push_back(*q);
+                    if(it->isTurningPoint()) dir = -dir;
+                    if(q != Q.first) it += dir;
+                }
+                else it += dir;
+            }
+            ++q; // "Set i = i + 1"
+        }
+
+        // Step 4:
+
+        // "Let starting edge r1 be in position si in sequence"
+        // whaaat? I guess this means the following:
+        S[0] = *R.first;
+        auto it = S.begin();
+
+        // "Set j = 1, next = 2, direction = 1, seq1 = si"
+        // we dont use j, seq is expanded dynamically.
+        dir = 1; auto next = std::next(R.first);
+
+        // Step 5:
+        // "If all si edges have been allocated to seqj" should mean that
+        // we loop until seq has equal size with S
+        while(seq.size() < S.size()) {
+            ++it; if(it == S.end()) it = S.begin();
+
+            if(it->isFrom(Qcont)) {
+                seq.push_back(*it); // "If si is from Q, j = j + 1, seqj = si"
+
+                // "If si is a turning point in Q,
+                // direction = - direction, next = next + direction"
+                if(it->isTurningPoint()) { dir = -dir; next += dir; }
+            }
+
+            if(it->eq(*next) && dir == next->dir) { // "If si = direction.rnext"
+                // "j = j + 1, seqj = si, next = next + direction"
+                seq.push_back(*it); next += dir;
+            }
+        }
+
+        return seq;
+    };
+
+    EdgeGroup R{ Bref.begin(), Bref.begin() }, Q{ Aref.begin(), Aref.end() };
+    auto it = Bref.begin();
+    bool orientation = true;
+    EdgeRefList seqlist;
+    seqlist.reserve(3*(Aref.size() + Bref.size()));
+
+    while(it != Bref.end()) // This is step 3 and step 4 in one loop
+        if(it->isTurningPoint()) {
+            R = {R.last, it++};
+            auto seq = mink(Q, R, orientation);
+
+            // TODO step 6 (should be 5 shouldn't it?): linking edges from A
+            // I don't get this step
+
+            seqlist.insert(seqlist.end(), seq.begin(), seq.end());
+            orientation = !orientation;
+        } else ++it;
+
+    if(seqlist.empty()) seqlist = mink(Q, {Bref.begin(), Bref.end()}, true);
+
+    // /////////////////////////////////////////////////////////////////////////
+    // Algorithm 2: breaking Minkowski sums into track line trips
+    // /////////////////////////////////////////////////////////////////////////
+
+
+    // /////////////////////////////////////////////////////////////////////////
+    // Algorithm 3: finding the boundary of the NFP from track line trips
+    // /////////////////////////////////////////////////////////////////////////
+
+
+
+    return Result(stationary, Vertex());
 }
 
 // Specializable NFP implementation class. Specialize it if you have a faster
 // or better NFP implementation
 template<class RawShape, NfpLevel nfptype>
 struct NfpImpl {
-    RawShape operator()(const RawShape& sh, const RawShape& other) {
+    NfpResult<RawShape> operator()(const RawShape& sh, const RawShape& other)
+    {
         static_assert(nfptype == NfpLevel::CONVEX_ONLY,
                       "Nfp::noFitPolygon() unimplemented!");
 
diff --git a/xs/src/libnest2d/libnest2d/libnest2d.hpp b/xs/src/libnest2d/libnest2d/libnest2d.hpp
index 96316c344..7f23de358 100644
--- a/xs/src/libnest2d/libnest2d/libnest2d.hpp
+++ b/xs/src/libnest2d/libnest2d/libnest2d.hpp
@@ -9,6 +9,7 @@
 #include <functional>
 
 #include "geometry_traits.hpp"
+#include "optimizer.hpp"
 
 namespace libnest2d {
 
@@ -27,6 +28,7 @@ class _Item {
     using Coord = TCoord<TPoint<RawShape>>;
     using Vertex = TPoint<RawShape>;
     using Box = _Box<Vertex>;
+    using sl = ShapeLike;
 
     // The original shape that gets encapsulated.
     RawShape sh_;
@@ -51,11 +53,18 @@ class _Item {
 
     enum class Convexity: char {
         UNCHECKED,
-        TRUE,
-        FALSE
+        C_TRUE,
+        C_FALSE
     };
 
     mutable Convexity convexity_ = Convexity::UNCHECKED;
+    mutable TVertexConstIterator<RawShape> rmt_;    // rightmost top vertex
+    mutable TVertexConstIterator<RawShape> lmb_;    // leftmost bottom vertex
+    mutable bool rmt_valid_ = false, lmb_valid_ = false;
+    mutable struct BBCache {
+        Box bb; bool valid; Vertex tr;
+        BBCache(): valid(false), tr(0, 0) {}
+    } bb_cache_;
 
 public:
 
@@ -104,15 +113,15 @@ public:
      * @param il The initializer list of vertices.
      */
     inline _Item(const std::initializer_list< Vertex >& il):
-        sh_(ShapeLike::create<RawShape>(il)) {}
+        sh_(sl::create<RawShape>(il)) {}
 
     inline _Item(const TContour<RawShape>& contour,
                  const THolesContainer<RawShape>& holes = {}):
-        sh_(ShapeLike::create<RawShape>(contour, holes)) {}
+        sh_(sl::create<RawShape>(contour, holes)) {}
 
     inline _Item(TContour<RawShape>&& contour,
                  THolesContainer<RawShape>&& holes):
-        sh_(ShapeLike::create<RawShape>(std::move(contour),
+        sh_(sl::create<RawShape>(std::move(contour),
                                         std::move(holes))) {}
 
     /**
@@ -122,31 +131,31 @@ public:
      */
     inline std::string toString() const
     {
-        return ShapeLike::toString(sh_);
+        return sl::toString(sh_);
     }
 
     /// Iterator tho the first contour vertex in the polygon.
     inline Iterator begin() const
     {
-        return ShapeLike::cbegin(sh_);
+        return sl::cbegin(sh_);
     }
 
     /// Alias to begin()
     inline Iterator cbegin() const
     {
-        return ShapeLike::cbegin(sh_);
+        return sl::cbegin(sh_);
     }
 
     /// Iterator to the last contour vertex.
     inline Iterator end() const
     {
-        return ShapeLike::cend(sh_);
+        return sl::cend(sh_);
     }
 
     /// Alias to end()
     inline Iterator cend() const
     {
-        return ShapeLike::cend(sh_);
+        return sl::cend(sh_);
     }
 
     /**
@@ -161,7 +170,7 @@ public:
      */
     inline Vertex vertex(unsigned long idx) const
     {
-        return ShapeLike::vertex(sh_, idx);
+        return sl::vertex(sh_, idx);
     }
 
     /**
@@ -176,7 +185,7 @@ public:
     inline void setVertex(unsigned long idx, const Vertex& v )
     {
         invalidateCache();
-        ShapeLike::vertex(sh_, idx) = v;
+        sl::vertex(sh_, idx) = v;
     }
 
     /**
@@ -191,7 +200,7 @@ public:
         double ret ;
         if(area_cache_valid_) ret = area_cache_;
         else {
-            ret = ShapeLike::area(offsettedShape());
+            ret = sl::area(offsettedShape());
             area_cache_ = ret;
             area_cache_valid_ = true;
         }
@@ -203,17 +212,17 @@ public:
 
         switch(convexity_) {
         case Convexity::UNCHECKED:
-            ret = ShapeLike::isConvex<RawShape>(ShapeLike::getContour(transformedShape()));
-            convexity_ = ret? Convexity::TRUE : Convexity::FALSE;
+            ret = sl::isConvex<RawShape>(sl::getContour(transformedShape()));
+            convexity_ = ret? Convexity::C_TRUE : Convexity::C_FALSE;
             break;
-        case Convexity::TRUE: ret = true; break;
-        case Convexity::FALSE:;
+        case Convexity::C_TRUE: ret = true; break;
+        case Convexity::C_FALSE:;
         }
 
         return ret;
     }
 
-    inline bool isHoleConvex(unsigned holeidx) const {
+    inline bool isHoleConvex(unsigned /*holeidx*/) const {
         return false;
     }
 
@@ -223,11 +232,11 @@ public:
 
     /// The number of the outer ring vertices.
     inline size_t vertexCount() const {
-        return ShapeLike::contourVertexCount(sh_);
+        return sl::contourVertexCount(sh_);
     }
 
     inline size_t holeCount() const {
-        return ShapeLike::holeCount(sh_);
+        return sl::holeCount(sh_);
     }
 
     /**
@@ -235,36 +244,39 @@ public:
      * @param p
      * @return
      */
-    inline bool isPointInside(const Vertex& p)
+    inline bool isPointInside(const Vertex& p) const
     {
-        return ShapeLike::isInside(p, sh_);
+        return sl::isInside(p, transformedShape());
     }
 
     inline bool isInside(const _Item& sh) const
     {
-        return ShapeLike::isInside(transformedShape(), sh.transformedShape());
+        return sl::isInside(transformedShape(), sh.transformedShape());
     }
 
-    inline bool isInside(const _Box<TPoint<RawShape>>& box);
+    inline bool isInside(const RawShape& sh) const
+    {
+        return sl::isInside(transformedShape(), sh);
+    }
+
+    inline bool isInside(const _Box<TPoint<RawShape>>& box) const;
+    inline bool isInside(const _Circle<TPoint<RawShape>>& box) const;
 
     inline void translate(const Vertex& d) BP2D_NOEXCEPT
     {
-        translation_ += d; has_translation_ = true;
-        tr_cache_valid_ = false;
+        translation(translation() + d);
     }
 
     inline void rotate(const Radians& rads) BP2D_NOEXCEPT
     {
-        rotation_ += rads;
-        has_rotation_ = true;
-        tr_cache_valid_ = false;
+        rotation(rotation() + rads);
     }
 
     inline void addOffset(Coord distance) BP2D_NOEXCEPT
     {
         offset_distance_ = distance;
         has_offset_ = true;
-        offset_cache_valid_ = false;
+        invalidateCache();
     }
 
     inline void removeOffset() BP2D_NOEXCEPT {
@@ -286,6 +298,8 @@ public:
     {
         if(rotation_ != rot) {
             rotation_ = rot; has_rotation_ = true; tr_cache_valid_ = false;
+            rmt_valid_ = false; lmb_valid_ = false;
+            bb_cache_.valid = false;
         }
     }
 
@@ -293,6 +307,7 @@ public:
     {
         if(translation_ != tr) {
             translation_ = tr; has_translation_ = true; tr_cache_valid_ = false;
+            bb_cache_.valid = false;
         }
     }
 
@@ -301,9 +316,10 @@ public:
         if(tr_cache_valid_) return tr_cache_;
 
         RawShape cpy = offsettedShape();
-        if(has_rotation_) ShapeLike::rotate(cpy, rotation_);
-        if(has_translation_) ShapeLike::translate(cpy, translation_);
+        if(has_rotation_) sl::rotate(cpy, rotation_);
+        if(has_translation_) sl::translate(cpy, translation_);
         tr_cache_ = cpy; tr_cache_valid_ = true;
+        rmt_valid_ = false; lmb_valid_ = false;
 
         return tr_cache_;
     }
@@ -321,23 +337,53 @@ public:
     inline void resetTransformation() BP2D_NOEXCEPT
     {
         has_translation_ = false; has_rotation_ = false; has_offset_ = false;
+        invalidateCache();
     }
 
     inline Box boundingBox() const {
-        return ShapeLike::boundingBox(transformedShape());
+        if(!bb_cache_.valid) {
+            bb_cache_.bb = sl::boundingBox(transformedShape());
+            bb_cache_.tr = {0, 0};
+            bb_cache_.valid = true;
+        }
+
+        auto &bb = bb_cache_.bb; auto &tr = bb_cache_.tr;
+        return {bb.minCorner() + tr, bb.maxCorner() + tr};
+    }
+
+    inline Vertex referenceVertex() const {
+        return rightmostTopVertex();
+    }
+
+    inline Vertex rightmostTopVertex() const {
+        if(!rmt_valid_ || !tr_cache_valid_) {  // find max x and max y vertex
+            auto& tsh = transformedShape();
+            rmt_ = std::max_element(sl::cbegin(tsh), sl::cend(tsh), vsort);
+            rmt_valid_ = true;
+        }
+        return *rmt_;
+    }
+
+    inline Vertex leftmostBottomVertex() const {
+        if(!lmb_valid_ || !tr_cache_valid_) {  // find min x and min y vertex
+            auto& tsh = transformedShape();
+            lmb_ = std::min_element(sl::cbegin(tsh), sl::cend(tsh), vsort);
+            lmb_valid_ = true;
+        }
+        return *lmb_;
     }
 
     //Static methods:
 
     inline static bool intersects(const _Item& sh1, const _Item& sh2)
     {
-        return ShapeLike::intersects(sh1.transformedShape(),
+        return sl::intersects(sh1.transformedShape(),
                                      sh2.transformedShape());
     }
 
     inline static bool touches(const _Item& sh1, const _Item& sh2)
     {
-        return ShapeLike::touches(sh1.transformedShape(),
+        return sl::touches(sh1.transformedShape(),
                                   sh2.transformedShape());
     }
 
@@ -346,12 +392,11 @@ private:
     inline const RawShape& offsettedShape() const {
         if(has_offset_ ) {
             if(offset_cache_valid_) return offset_cache_;
-            else {
-                offset_cache_ = sh_;
-                ShapeLike::offset(offset_cache_, offset_distance_);
-                offset_cache_valid_ = true;
-                return offset_cache_;
-            }
+
+            offset_cache_ = sh_;
+            sl::offset(offset_cache_, offset_distance_);
+            offset_cache_valid_ = true;
+            return offset_cache_;
         }
         return sh_;
     }
@@ -359,10 +404,23 @@ private:
     inline void invalidateCache() const BP2D_NOEXCEPT
     {
         tr_cache_valid_ = false;
+        lmb_valid_ = false; rmt_valid_ = false;
         area_cache_valid_ = false;
         offset_cache_valid_ = false;
+        bb_cache_.valid = false;
         convexity_ = Convexity::UNCHECKED;
     }
+
+    static inline bool vsort(const Vertex& v1, const Vertex& v2)
+    {
+        Coord &&x1 = getX(v1), &&x2 = getX(v2);
+        Coord &&y1 = getY(v1), &&y2 = getY(v2);
+        auto diff = y1 - y2;
+        if(std::abs(diff) <= std::numeric_limits<Coord>::epsilon())
+            return x1 < x2;
+
+        return diff < 0;
+    }
 };
 
 /**
@@ -370,7 +428,6 @@ private:
  */
 template<class RawShape>
 class _Rectangle: public _Item<RawShape> {
-    RawShape sh_;
     using _Item<RawShape>::vertex;
     using TO = Orientation;
 public:
@@ -415,9 +472,13 @@ public:
 };
 
 template<class RawShape>
-inline bool _Item<RawShape>::isInside(const _Box<TPoint<RawShape>>& box) {
-    _Rectangle<RawShape> rect(box.width(), box.height());
-    return _Item<RawShape>::isInside(rect);
+inline bool _Item<RawShape>::isInside(const _Box<TPoint<RawShape>>& box) const {
+    return ShapeLike::isInside<RawShape>(boundingBox(), box);
+}
+
+template<class RawShape> inline bool
+_Item<RawShape>::isInside(const _Circle<TPoint<RawShape>>& circ) const {
+    return ShapeLike::isInside<RawShape>(transformedShape(), circ);
 }
 
 /**
@@ -874,9 +935,8 @@ private:
 
     Radians findBestRotation(Item& item) {
         opt::StopCriteria stopcr;
-        stopcr.stoplimit = 0.01;
+        stopcr.absolute_score_difference = 0.01;
         stopcr.max_iterations = 10000;
-        stopcr.type = opt::StopLimitType::RELATIVE;
         opt::TOptimizer<opt::Method::G_GENETIC> solver(stopcr);
 
         auto orig_rot = item.rotation();
@@ -910,7 +970,6 @@ private:
         if(min_obj_distance_ > 0) std::for_each(from, to, [](Item& item) {
             item.removeOffset();
         });
-
     }
 };
 
diff --git a/xs/src/libnest2d/libnest2d/metaloop.hpp b/xs/src/libnest2d/libnest2d/metaloop.hpp
new file mode 100644
index 000000000..18755525c
--- /dev/null
+++ b/xs/src/libnest2d/libnest2d/metaloop.hpp
@@ -0,0 +1,227 @@
+#ifndef METALOOP_HPP
+#define METALOOP_HPP
+
+#include "common.hpp"
+#include <tuple>
+#include <functional>
+
+namespace libnest2d {
+
+/* ************************************************************************** */
+/* C++14 std::index_sequence implementation:                                  */
+/* ************************************************************************** */
+
+/**
+ * \brief C++11 conformant implementation of the index_sequence type from C++14
+ */
+template<size_t...Ints> struct index_sequence {
+    using value_type = size_t;
+    BP2D_CONSTEXPR value_type size() const { return sizeof...(Ints); }
+};
+
+// A Help structure to generate the integer list
+template<size_t...Nseq> struct genSeq;
+
+// Recursive template to generate the list
+template<size_t I, size_t...Nseq> struct genSeq<I, Nseq...> {
+    // Type will contain a genSeq with Nseq appended by one element
+    using Type = typename genSeq< I - 1, I - 1, Nseq...>::Type;
+};
+
+// Terminating recursion
+template <size_t ... Nseq> struct genSeq<0, Nseq...> {
+    // If I is zero, Type will contain index_sequence with the fuly generated
+    // integer list.
+    using Type = index_sequence<Nseq...>;
+};
+
+/// Helper alias to make an index sequence from 0 to N
+template<size_t N> using make_index_sequence = typename genSeq<N>::Type;
+
+/// Helper alias to make an index sequence for a parameter pack
+template<class...Args>
+using index_sequence_for = make_index_sequence<sizeof...(Args)>;
+
+
+/* ************************************************************************** */
+
+namespace opt {
+
+using std::forward;
+using std::tuple;
+using std::get;
+using std::tuple_element;
+
+/**
+ * @brief Helper class to be able to loop over a parameter pack's elements.
+ */
+class metaloop {
+
+// The implementation is based on partial struct template specializations.
+// Basically we need a template type that is callable and takes an integer
+// non-type template parameter which can be used to implement recursive calls.
+//
+// C++11 will not allow the usage of a plain template function that is why we
+// use struct with overloaded call operator. At the same time C++11 prohibits
+// partial template specialization with a non type parameter such as int. We
+// need to wrap that in a type (see metaloop::Int).
+
+/*
+ * A helper alias to create integer values wrapped as a type. It is nessecary
+ * because a non type template parameter (such as int) would be prohibited in
+ * a partial specialization. Also for the same reason we have to use a class
+ * _Metaloop instead of a simple function as a functor. A function cannot be
+ * partially specialized in a way that is neccesary for this trick.
+ */
+template<int N> using Int = std::integral_constant<int, N>;
+
+/*
+ * Helper class to implement in-place functors.
+ *
+ * We want to be able to use inline functors like a lambda to keep the code
+ * as clear as possible.
+ */
+template<int N, class Fn> class MapFn {
+    Fn&& fn_;
+public:
+
+    // It takes the real functor that can be specified in-place but only
+    // with C++14 because the second parameter's type will depend on the
+    // type of the parameter pack element that is processed. In C++14 we can
+    // specify this second parameter type as auto in the lamda parameter list.
+    inline MapFn(Fn&& fn): fn_(forward<Fn>(fn)) {}
+
+    template<class T> void operator ()(T&& pack_element) {
+        // We provide the index as the first parameter and the pack (or tuple)
+        // element as the second parameter to the functor.
+        fn_(N, forward<T>(pack_element));
+    }
+};
+
+/*
+ * Implementation of the template loop trick.
+ * We create a mechanism for looping over a parameter pack in compile time.
+ * \tparam Idx is the loop index which will be decremented at each recursion.
+ * \tparam Args The parameter pack that will be processed.
+ *
+ */
+template <typename Idx, class...Args>
+class _MetaLoop {};
+
+// Implementation for the first element of Args...
+template <class...Args>
+class _MetaLoop<Int<0>, Args...> {
+public:
+
+    const static BP2D_CONSTEXPR int N = 0;
+    const static BP2D_CONSTEXPR int ARGNUM = sizeof...(Args)-1;
+
+    template<class Tup, class Fn>
+    void run( Tup&& valtup, Fn&& fn) {
+        MapFn<ARGNUM-N, Fn> {forward<Fn>(fn)} (get<ARGNUM-N>(valtup));
+    }
+};
+
+// Implementation for the N-th element of Args...
+template <int N, class...Args>
+class _MetaLoop<Int<N>, Args...> {
+public:
+
+    const static BP2D_CONSTEXPR int ARGNUM = sizeof...(Args)-1;
+
+    template<class Tup, class Fn>
+    void run(Tup&& valtup, Fn&& fn) {
+        MapFn<ARGNUM-N, Fn> {forward<Fn>(fn)} (std::get<ARGNUM-N>(valtup));
+
+        // Recursive call to process the next element of Args
+        _MetaLoop<Int<N-1>, Args...> ().run(forward<Tup>(valtup),
+                                            forward<Fn>(fn));
+    }
+};
+
+/*
+ * Instantiation: We must instantiate the template with the last index because
+ * the generalized version calls the decremented instantiations recursively.
+ * Once the instantiation with the first index is called, the terminating
+ * version of run is called which does not call itself anymore.
+ *
+ * If you are utterly annoyed, at least you have learned a super crazy
+ * functional metaprogramming pattern.
+ */
+template<class...Args>
+using MetaLoop = _MetaLoop<Int<sizeof...(Args)-1>, Args...>;
+
+public:
+
+/**
+ * \brief The final usable function template.
+ *
+ * This is similar to what varags was on C but in compile time C++11.
+ * You can call:
+ * apply(<the mapping function>, <arbitrary number of arguments of any type>);
+ * For example:
+ *
+ *      struct mapfunc {
+ *          template<class T> void operator()(int N, T&& element) {
+ *              std::cout << "The value of the parameter "<< N <<": "
+ *                        << element << std::endl;
+ *          }
+ *      };
+ *
+ *      apply(mapfunc(), 'a', 10, 151.545);
+ *
+ * C++14:
+ *      apply([](int N, auto&& element){
+ *          std::cout << "The value of the parameter "<< N <<": "
+ *                        << element << std::endl;
+ *      }, 'a', 10, 151.545);
+ *
+ * This yields the output:
+ * The value of the parameter 0: a
+ * The value of the parameter 1: 10
+ * The value of the parameter 2: 151.545
+ *
+ * As an addition, the function can be called with a tuple as the second
+ * parameter holding the arguments instead of a parameter pack.
+ *
+ */
+template<class...Args, class Fn>
+inline static void apply(Fn&& fn, Args&&...args) {
+    MetaLoop<Args...>().run(tuple<Args&&...>(forward<Args>(args)...),
+                            forward<Fn>(fn));
+}
+
+/// The version of apply with a tuple rvalue reference.
+template<class...Args, class Fn>
+inline static void apply(Fn&& fn, tuple<Args...>&& tup) {
+    MetaLoop<Args...>().run(std::move(tup), forward<Fn>(fn));
+}
+
+/// The version of apply with a tuple lvalue reference.
+template<class...Args, class Fn>
+inline static void apply(Fn&& fn, tuple<Args...>& tup) {
+    MetaLoop<Args...>().run(tup, forward<Fn>(fn));
+}
+
+/// The version of apply with a tuple const reference.
+template<class...Args, class Fn>
+inline static void apply(Fn&& fn, const tuple<Args...>& tup) {
+    MetaLoop<Args...>().run(tup, forward<Fn>(fn));
+}
+
+/**
+ * Call a function with its arguments encapsualted in a tuple.
+ */
+template<class Fn, class Tup, std::size_t...Is>
+inline static auto
+callFunWithTuple(Fn&& fn, Tup&& tup, index_sequence<Is...>) ->
+    decltype(fn(std::get<Is>(tup)...))
+{
+    return fn(std::get<Is>(tup)...);
+}
+
+};
+}
+}
+
+#endif // METALOOP_HPP
diff --git a/xs/src/libnest2d/libnest2d/optimizer.hpp b/xs/src/libnest2d/libnest2d/optimizer.hpp
index 52e67f7d5..c8ed2e378 100644
--- a/xs/src/libnest2d/libnest2d/optimizer.hpp
+++ b/xs/src/libnest2d/libnest2d/optimizer.hpp
@@ -10,8 +10,7 @@ namespace libnest2d { namespace opt {
 
 using std::forward;
 using std::tuple;
-using std::get;
-using std::tuple_element;
+using std::make_tuple;
 
 /// A Type trait for upper and lower limit of a numeric type.
 template<class T, class B = void >
@@ -51,176 +50,7 @@ inline Bound<T> bound(const T& min, const T& max) { return Bound<T>(min, max); }
 template<class...Args> using Input = tuple<Args...>;
 
 template<class...Args>
-inline tuple<Args...> initvals(Args...args) { return std::make_tuple(args...); }
-
-/**
- * @brief Helper class to be able to loop over a parameter pack's elements.
- */
-class metaloop {
-// The implementation is based on partial struct template specializations.
-// Basically we need a template type that is callable and takes an integer
-// non-type template parameter which can be used to implement recursive calls.
-//
-// C++11 will not allow the usage of a plain template function that is why we
-// use struct with overloaded call operator. At the same time C++11 prohibits
-// partial template specialization with a non type parameter such as int. We
-// need to wrap that in a type (see metaloop::Int).
-
-/*
- * A helper alias to create integer values wrapped as a type. It is nessecary
- * because a non type template parameter (such as int) would be prohibited in
- * a partial specialization. Also for the same reason we have to use a class
- * _Metaloop instead of a simple function as a functor. A function cannot be
- * partially specialized in a way that is neccesary for this trick.
- */
-template<int N> using Int = std::integral_constant<int, N>;
-
-/*
- * Helper class to implement in-place functors.
- *
- * We want to be able to use inline functors like a lambda to keep the code
- * as clear as possible.
- */
-template<int N, class Fn> class MapFn {
-    Fn&& fn_;
-public:
-
-    // It takes the real functor that can be specified in-place but only
-    // with C++14 because the second parameter's type will depend on the
-    // type of the parameter pack element that is processed. In C++14 we can
-    // specify this second parameter type as auto in the lamda parameter list.
-    inline MapFn(Fn&& fn): fn_(forward<Fn>(fn)) {}
-
-    template<class T> void operator ()(T&& pack_element) {
-        // We provide the index as the first parameter and the pack (or tuple)
-        // element as the second parameter to the functor.
-        fn_(N, forward<T>(pack_element));
-    }
-};
-
-/*
- * Implementation of the template loop trick.
- * We create a mechanism for looping over a parameter pack in compile time.
- * \tparam Idx is the loop index which will be decremented at each recursion.
- * \tparam Args The parameter pack that will be processed.
- *
- */
-template <typename Idx, class...Args>
-class _MetaLoop {};
-
-// Implementation for the first element of Args...
-template <class...Args>
-class _MetaLoop<Int<0>, Args...> {
-public:
-
-    const static BP2D_CONSTEXPR int N = 0;
-    const static BP2D_CONSTEXPR int ARGNUM = sizeof...(Args)-1;
-
-    template<class Tup, class Fn>
-    void run( Tup&& valtup, Fn&& fn) {
-        MapFn<ARGNUM-N, Fn> {forward<Fn>(fn)} (get<ARGNUM-N>(valtup));
-    }
-};
-
-// Implementation for the N-th element of Args...
-template <int N, class...Args>
-class _MetaLoop<Int<N>, Args...> {
-public:
-
-    const static BP2D_CONSTEXPR int ARGNUM = sizeof...(Args)-1;
-
-    template<class Tup, class Fn>
-    void run(Tup&& valtup, Fn&& fn) {
-        MapFn<ARGNUM-N, Fn> {forward<Fn>(fn)} (std::get<ARGNUM-N>(valtup));
-
-        // Recursive call to process the next element of Args
-        _MetaLoop<Int<N-1>, Args...> ().run(forward<Tup>(valtup),
-                                            forward<Fn>(fn));
-    }
-};
-
-/*
- * Instantiation: We must instantiate the template with the last index because
- * the generalized version calls the decremented instantiations recursively.
- * Once the instantiation with the first index is called, the terminating
- * version of run is called which does not call itself anymore.
- *
- * If you are utterly annoyed, at least you have learned a super crazy
- * functional metaprogramming pattern.
- */
-template<class...Args>
-using MetaLoop = _MetaLoop<Int<sizeof...(Args)-1>, Args...>;
-
-public:
-
-/**
- * \brief The final usable function template.
- *
- * This is similar to what varags was on C but in compile time C++11.
- * You can call:
- * apply(<the mapping function>, <arbitrary number of arguments of any type>);
- * For example:
- *
- *      struct mapfunc {
- *          template<class T> void operator()(int N, T&& element) {
- *              std::cout << "The value of the parameter "<< N <<": "
- *                        << element << std::endl;
- *          }
- *      };
- *
- *      apply(mapfunc(), 'a', 10, 151.545);
- *
- * C++14:
- *      apply([](int N, auto&& element){
- *          std::cout << "The value of the parameter "<< N <<": "
- *                        << element << std::endl;
- *      }, 'a', 10, 151.545);
- *
- * This yields the output:
- * The value of the parameter 0: a
- * The value of the parameter 1: 10
- * The value of the parameter 2: 151.545
- *
- * As an addition, the function can be called with a tuple as the second
- * parameter holding the arguments instead of a parameter pack.
- *
- */
-template<class...Args, class Fn>
-inline static void apply(Fn&& fn, Args&&...args) {
-    MetaLoop<Args...>().run(tuple<Args&&...>(forward<Args>(args)...),
-                            forward<Fn>(fn));
-}
-
-/// The version of apply with a tuple rvalue reference.
-template<class...Args, class Fn>
-inline static void apply(Fn&& fn, tuple<Args...>&& tup) {
-    MetaLoop<Args...>().run(std::move(tup), forward<Fn>(fn));
-}
-
-/// The version of apply with a tuple lvalue reference.
-template<class...Args, class Fn>
-inline static void apply(Fn&& fn, tuple<Args...>& tup) {
-    MetaLoop<Args...>().run(tup, forward<Fn>(fn));
-}
-
-/// The version of apply with a tuple const reference.
-template<class...Args, class Fn>
-inline static void apply(Fn&& fn, const tuple<Args...>& tup) {
-    MetaLoop<Args...>().run(tup, forward<Fn>(fn));
-}
-
-/**
- * Call a function with its arguments encapsualted in a tuple.
- */
-template<class Fn, class Tup, std::size_t...Is>
-inline static auto
-callFunWithTuple(Fn&& fn, Tup&& tup, index_sequence<Is...>) ->
-    decltype(fn(std::get<Is>(tup)...))
-{
-    return fn(std::get<Is>(tup)...);
-}
-
-};
+inline tuple<Args...> initvals(Args...args) { return make_tuple(args...); }
 
 /**
  * @brief Specific optimization methods for which a default optimizer
@@ -257,29 +87,20 @@ enum ResultCodes {
 template<class...Args>
 struct Result {
     ResultCodes resultcode;
-    std::tuple<Args...> optimum;
+    tuple<Args...> optimum;
     double score;
 };
 
-/**
- * @brief The stop limit can be specified as the absolute error or as the
- * relative error, just like in nlopt.
- */
-enum class StopLimitType {
-    ABSOLUTE,
-    RELATIVE
-};
-
 /**
  * @brief A type for specifying the stop criteria.
  */
 struct StopCriteria {
 
-    /// Relative or absolute termination error
-    StopLimitType type = StopLimitType::RELATIVE;
+    /// If the absolute value difference between two scores.
+    double absolute_score_difference = std::nan("");
 
-    /// The error value that is interpredted depending on the type property.
-    double stoplimit = 0.0001;
+    /// If the relative value difference between two scores.
+    double relative_score_difference = std::nan("");
 
     unsigned max_iterations = 0;
 };
@@ -310,11 +131,11 @@ public:
      * \return Returns a Result<Args...> structure.
      * An example call would be:
      *     auto result = opt.optimize_min(
-     *           [](std::tuple<double> x) // object function
+     *           [](tuple<double> x) // object function
      *           {
      *               return std::pow(std::get<0>(x), 2);
      *           },
-     *           std::make_tuple(-0.5),  // initial value
+     *           make_tuple(-0.5),  // initial value
      *           {-1.0, 1.0}           // search space bounds
      *       );
      */
@@ -390,10 +211,14 @@ public:
         static_assert(always_false<T>::value, "Optimizer unimplemented!");
     }
 
+    DummyOptimizer(const StopCriteria&) {
+        static_assert(always_false<T>::value, "Optimizer unimplemented!");
+    }
+
     template<class Func, class...Args>
-    Result<Args...> optimize(Func&& func,
-                             std::tuple<Args...> initvals,
-                             Bound<Args>... args)
+    Result<Args...> optimize(Func&& /*func*/,
+                             tuple<Args...> /*initvals*/,
+                             Bound<Args>...  /*args*/)
     {
         return Result<Args...>();
     }
diff --git a/xs/src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp b/xs/src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp
index 798bf9622..737ca6e3c 100644
--- a/xs/src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp
+++ b/xs/src/libnest2d/libnest2d/optimizers/nlopt_boilerplate.hpp
@@ -1,15 +1,25 @@
 #ifndef NLOPT_BOILERPLATE_HPP
 #define NLOPT_BOILERPLATE_HPP
 
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4267)
+#endif
 #include <nlopt.hpp>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
 #include <libnest2d/optimizer.hpp>
 #include <cassert>
+#include "libnest2d/metaloop.hpp"
 
 #include <utility>
 
 namespace libnest2d { namespace opt {
 
-nlopt::algorithm method2nloptAlg(Method m) {
+inline nlopt::algorithm method2nloptAlg(Method m) {
 
     switch(m) {
     case Method::L_SIMPLEX: return nlopt::LN_NELDERMEAD;
@@ -87,7 +97,7 @@ protected:
 
     template<class Fn, class...Args>
     static double optfunc(const std::vector<double>& params,
-                          std::vector<double>& grad,
+                          std::vector<double>& /*grad*/,
                           void *data)
     {
         auto fnptr = static_cast<remove_ref_t<Fn>*>(data);
@@ -132,12 +142,10 @@ protected:
         default: ;
         }
 
-        switch(this->stopcr_.type) {
-        case StopLimitType::ABSOLUTE:
-            opt_.set_ftol_abs(stopcr_.stoplimit); break;
-        case StopLimitType::RELATIVE:
-            opt_.set_ftol_rel(stopcr_.stoplimit); break;
-        }
+        auto abs_diff = stopcr_.absolute_score_difference;
+        auto rel_diff = stopcr_.relative_score_difference;
+        if(!std::isnan(abs_diff)) opt_.set_ftol_abs(abs_diff);
+        if(!std::isnan(rel_diff)) opt_.set_ftol_rel(rel_diff);
 
         if(this->stopcr_.max_iterations > 0)
             opt_.set_maxeval(this->stopcr_.max_iterations );
diff --git a/xs/src/libnest2d/libnest2d/placers/nfpplacer.hpp b/xs/src/libnest2d/libnest2d/placers/nfpplacer.hpp
index 89848eb53..5d09a61fc 100644
--- a/xs/src/libnest2d/libnest2d/placers/nfpplacer.hpp
+++ b/xs/src/libnest2d/libnest2d/placers/nfpplacer.hpp
@@ -6,6 +6,10 @@
 #endif
 #include "placer_boilerplate.hpp"
 #include "../geometry_traits_nfp.hpp"
+#include "libnest2d/optimizer.hpp"
+#include <cassert>
+
+#include "tools/svgtools.hpp"
 
 namespace libnest2d { namespace strategies {
 
@@ -20,15 +24,60 @@ struct NfpPConfig {
         TOP_RIGHT,
     };
 
-    /// Which angles to try out for better results
+    /// Which angles to try out for better results.
     std::vector<Radians> rotations;
 
-    /// Where to align the resulting packed pile
+    /// Where to align the resulting packed pile.
     Alignment alignment;
 
+    /// Where to start putting objects in the bin.
     Alignment starting_point;
 
-    std::function<double(const Nfp::Shapes<RawShape>&, double, double, double)>
+    /**
+     * @brief A function object representing the fitting function in the
+     * placement optimization process. (Optional)
+     *
+     * This is the most versatile tool to configure the placer. The fitting
+     * function is evaluated many times when a new item is being placed into the
+     * bin. The output should be a rated score of the new item's position.
+     *
+     * This is not a mandatory option as there is a default fitting function
+     * that will optimize for the best pack efficiency. With a custom fitting
+     * function you can e.g. influence the shape of the arranged pile.
+     *
+     * \param shapes The first parameter is a container with all the placed
+     * polygons excluding the current candidate. You can calculate a bounding
+     * box or convex hull on this pile of polygons without the candidate item
+     * or push back the candidate item into the container and then calculate
+     * some features.
+     *
+     * \param item The second parameter is the candidate item.
+     *
+     * \param occupied_area The third parameter is the sum of areas of the
+     * items in the first parameter so you don't have to iterate through them
+     * if you only need their area.
+     *
+     * \param norm A norming factor for physical dimensions. E.g. if your score
+     * is the distance between the item and the bin center, you should divide
+     * that distance with the norming factor. If the score is an area than
+     * divide it with the square of the norming factor. Imagine it as a unit of
+     * distance.
+     *
+     * \param penality The fifth parameter is the amount of minimum penality if
+     * the arranged pile would't fit into the bin. You can use the wouldFit()
+     * function to check this. Note that the pile can be outside the bin's
+     * boundaries while the placement algorithm is running. Your job is only to
+     * check if the pile could be translated into a position in the bin where
+     * all the items would be inside. For a box shaped bin you can use the
+     * pile's bounding box to check whether it's width and height is small
+     * enough. If the pile would not fit, you have to make sure that the
+     * resulting score will be higher then the penality value. A good solution
+     * would be to set score = 2*penality-score in case the pile wouldn't fit
+     * into the bin.
+     *
+     */
+    std::function<double(Nfp::Shapes<RawShape>&, const _Item<RawShape>&,
+                         double, double, double)>
     object_function;
 
     /**
@@ -38,11 +87,30 @@ struct NfpPConfig {
      */
     float accuracy = 1.0;
 
+    /**
+     * @brief If you want to see items inside other item's holes, you have to
+     * turn this switch on.
+     *
+     * This will only work if a suitable nfp implementation is provided.
+     * The library has no such implementation right now.
+     */
+    bool explore_holes = false;
+
     NfpPConfig(): rotations({0.0, Pi/2.0, Pi, 3*Pi/2}),
         alignment(Alignment::CENTER), starting_point(Alignment::CENTER) {}
 };
 
-// A class for getting a point on the circumference of the polygon (in log time)
+/**
+ * A class for getting a point on the circumference of the polygon (in log time)
+ *
+ * This is a transformation of the provided polygon to be able to pinpoint
+ * locations on the circumference. The optimizer will pass a floating point
+ * value e.g. within <0,1> and we have to transform this value quickly into a
+ * coordinate on the circumference. By definition 0 should yield the first
+ * vertex and 1.0 would be the last (which should coincide with first).
+ *
+ * We also have to make this work for the holes of the captured polygon.
+ */
 template<class RawShape> class EdgeCache {
     using Vertex = TPoint<RawShape>;
     using Coord = TCoord<Vertex>;
@@ -57,6 +125,8 @@ template<class RawShape> class EdgeCache {
 
     std::vector<ContourCache> holes_;
 
+    double accuracy_ = 1.0;
+
     void createCache(const RawShape& sh) {
         {   // For the contour
             auto first = ShapeLike::cbegin(sh);
@@ -90,21 +160,44 @@ template<class RawShape> class EdgeCache {
         }
     }
 
+    size_t stride(const size_t N) const {
+        using std::ceil;
+        using std::round;
+        using std::pow;
+
+        return static_cast<Coord>(
+                    std::round(N/std::pow(N, std::pow(accuracy_, 1.0/3.0)))
+                );
+    }
+
     void fetchCorners() const {
         if(!contour_.corners.empty()) return;
 
-        // TODO Accuracy
-        contour_.corners = contour_.distances;
-        for(auto& d : contour_.corners) d /= contour_.full_distance;
+        const auto N = contour_.distances.size();
+        const auto S = stride(N);
+
+        contour_.corners.reserve(N / S + 1);
+        auto N_1 = N-1;
+        contour_.corners.emplace_back(0.0);
+        for(size_t i = 0; i < N_1; i += S) {
+            contour_.corners.emplace_back(
+                    contour_.distances.at(i) / contour_.full_distance);
+        }
     }
 
     void fetchHoleCorners(unsigned hidx) const {
         auto& hc = holes_[hidx];
         if(!hc.corners.empty()) return;
 
-        // TODO Accuracy
-        hc.corners = hc.distances;
-        for(auto& d : hc.corners) d /= hc.full_distance;
+        const auto N = hc.distances.size();
+        const auto S = stride(N);
+        auto N_1 = N-1;
+        hc.corners.reserve(N / S + 1);
+        hc.corners.emplace_back(0.0);
+        for(size_t i = 0; i < N_1; i += S) {
+            hc.corners.emplace_back(
+                    hc.distances.at(i) / hc.full_distance);
+        }
     }
 
     inline Vertex coords(const ContourCache& cache, double distance) const {
@@ -150,6 +243,9 @@ public:
         createCache(sh);
     }
 
+    /// Resolution of returned corners. The stride is derived from this value.
+    void accuracy(double a /* within <0.0, 1.0>*/) { accuracy_ = a; }
+
     /**
      * @brief Get a point on the circumference of a polygon.
      * @param distance A relative distance from the starting point to the end.
@@ -176,24 +272,64 @@ public:
         return holes_[hidx].full_distance;
     }
 
+    /// Get the normalized distance values for each vertex
     inline const std::vector<double>& corners() const BP2D_NOEXCEPT {
         fetchCorners();
         return contour_.corners;
     }
 
+    /// corners for a specific hole
     inline const std::vector<double>&
     corners(unsigned holeidx) const BP2D_NOEXCEPT {
         fetchHoleCorners(holeidx);
         return holes_[holeidx].corners;
     }
 
-    inline unsigned holeCount() const BP2D_NOEXCEPT { return holes_.size(); }
+    /// The number of holes in the abstracted polygon
+    inline size_t holeCount() const BP2D_NOEXCEPT { return holes_.size(); }
 
 };
 
 template<NfpLevel lvl>
 struct Lvl { static const NfpLevel value = lvl; };
 
+template<class RawShape>
+inline void correctNfpPosition(Nfp::NfpResult<RawShape>& nfp,
+                               const _Item<RawShape>& stationary,
+                               const _Item<RawShape>& orbiter)
+{
+    // The provided nfp is somewhere in the dark. We need to get it
+    // to the right position around the stationary shape.
+    // This is done by choosing the leftmost lowest vertex of the
+    // orbiting polygon to be touched with the rightmost upper
+    // vertex of the stationary polygon. In this configuration, the
+    // reference vertex of the orbiting polygon (which can be dragged around
+    // the nfp) will be its rightmost upper vertex that coincides with the
+    // rightmost upper vertex of the nfp. No proof provided other than Jonas
+    // Lindmark's reasoning about the reference vertex of nfp in his thesis
+    // ("No fit polygon problem" - section 2.1.9)
+
+    auto touch_sh = stationary.rightmostTopVertex();
+    auto touch_other = orbiter.leftmostBottomVertex();
+    auto dtouch = touch_sh - touch_other;
+    auto top_other = orbiter.rightmostTopVertex() + dtouch;
+    auto dnfp = top_other - nfp.second; // nfp.second is the nfp reference point
+    ShapeLike::translate(nfp.first, dnfp);
+}
+
+template<class RawShape>
+inline void correctNfpPosition(Nfp::NfpResult<RawShape>& nfp,
+                               const RawShape& stationary,
+                               const _Item<RawShape>& orbiter)
+{
+    auto touch_sh = Nfp::rightmostUpVertex(stationary);
+    auto touch_other = orbiter.leftmostBottomVertex();
+    auto dtouch = touch_sh - touch_other;
+    auto top_other = orbiter.rightmostTopVertex() + dtouch;
+    auto dnfp = top_other - nfp.second;
+    ShapeLike::translate(nfp.first, dnfp);
+}
+
 template<class RawShape, class Container>
 Nfp::Shapes<RawShape> nfp( const Container& polygons,
                            const _Item<RawShape>& trsh,
@@ -203,18 +339,35 @@ Nfp::Shapes<RawShape> nfp( const Container& polygons,
 
     Nfp::Shapes<RawShape> nfps;
 
+    //int pi = 0;
     for(Item& sh : polygons) {
-        auto subnfp = Nfp::noFitPolygon<NfpLevel::CONVEX_ONLY>(
-                    sh.transformedShape(), trsh.transformedShape());
+        auto subnfp_r = Nfp::noFitPolygon<NfpLevel::CONVEX_ONLY>(
+                            sh.transformedShape(), trsh.transformedShape());
         #ifndef NDEBUG
             auto vv = ShapeLike::isValid(sh.transformedShape());
             assert(vv.first);
 
-            auto vnfp = ShapeLike::isValid(subnfp);
+            auto vnfp = ShapeLike::isValid(subnfp_r.first);
             assert(vnfp.first);
         #endif
 
-        nfps = Nfp::merge(nfps, subnfp);
+        correctNfpPosition(subnfp_r, sh, trsh);
+
+        nfps = Nfp::merge(nfps, subnfp_r.first);
+
+//        double SCALE = 1000000;
+//        using SVGWriter = svg::SVGWriter<RawShape>;
+//        SVGWriter::Config conf;
+//        conf.mm_in_coord_units = SCALE;
+//        SVGWriter svgw(conf);
+//        Box bin(250*SCALE, 210*SCALE);
+//        svgw.setSize(bin);
+//        for(int i = 0; i <= pi; i++) svgw.writeItem(polygons[i]);
+//        svgw.writeItem(trsh);
+////        svgw.writeItem(Item(subnfp_r.first));
+//        for(auto& n : nfps) svgw.writeItem(Item(n));
+//        svgw.save("nfpout");
+//        pi++;
     }
 
     return nfps;
@@ -227,50 +380,73 @@ Nfp::Shapes<RawShape> nfp( const Container& polygons,
 {
     using Item = _Item<RawShape>;
 
-    Nfp::Shapes<RawShape> nfps, stationary;
+    Nfp::Shapes<RawShape> nfps;
+
+    auto& orb = trsh.transformedShape();
+    bool orbconvex = trsh.isContourConvex();
 
     for(Item& sh : polygons) {
-        stationary = Nfp::merge(stationary, sh.transformedShape());
-    }
+        Nfp::NfpResult<RawShape> subnfp;
+        auto& stat = sh.transformedShape();
 
-    std::cout << "pile size: " << stationary.size() << std::endl;
-    for(RawShape& sh : stationary) {
+        if(sh.isContourConvex() && orbconvex)
+            subnfp = Nfp::noFitPolygon<NfpLevel::CONVEX_ONLY>(stat, orb);
+        else if(orbconvex)
+            subnfp = Nfp::noFitPolygon<NfpLevel::ONE_CONVEX>(stat, orb);
+        else
+            subnfp = Nfp::noFitPolygon<Level::value>(stat, orb);
 
-        RawShape subnfp;
-//        if(sh.isContourConvex() && trsh.isContourConvex()) {
-//            subnfp = Nfp::noFitPolygon<NfpLevel::CONVEX_ONLY>(
-//                        sh.transformedShape(), trsh.transformedShape());
-//        } else {
-            subnfp = Nfp::noFitPolygon<Level::value>( sh/*.transformedShape()*/,
-                                                      trsh.transformedShape());
-//        }
+        correctNfpPosition(subnfp, sh, trsh);
 
-//        #ifndef NDEBUG
-//            auto vv = ShapeLike::isValid(sh.transformedShape());
-//            assert(vv.first);
-
-//            auto vnfp = ShapeLike::isValid(subnfp);
-//            assert(vnfp.first);
-//        #endif
-
-//            auto vnfp = ShapeLike::isValid(subnfp);
-//            if(!vnfp.first) {
-//                std::cout << vnfp.second << std::endl;
-//                std::cout << ShapeLike::toString(subnfp) << std::endl;
-//            }
-
-        nfps = Nfp::merge(nfps, subnfp);
+        nfps = Nfp::merge(nfps, subnfp.first);
     }
 
     return nfps;
+
+
+//    using Item = _Item<RawShape>;
+//    using sl = ShapeLike;
+
+//    Nfp::Shapes<RawShape> nfps, stationary;
+
+//    for(Item& sh : polygons) {
+//        stationary = Nfp::merge(stationary, sh.transformedShape());
+//    }
+
+//    for(RawShape& sh : stationary) {
+
+////        auto vv = sl::isValid(sh);
+////        std::cout << vv.second << std::endl;
+
+
+//        Nfp::NfpResult<RawShape> subnfp;
+//        bool shconvex = sl::isConvex<RawShape>(sl::getContour(sh));
+//        if(shconvex && trsh.isContourConvex()) {
+//            subnfp = Nfp::noFitPolygon<NfpLevel::CONVEX_ONLY>(
+//                        sh, trsh.transformedShape());
+//        } else if(trsh.isContourConvex()) {
+//            subnfp = Nfp::noFitPolygon<NfpLevel::ONE_CONVEX>(
+//                        sh, trsh.transformedShape());
+//        }
+//        else {
+//            subnfp = Nfp::noFitPolygon<Level::value>( sh,
+//                                                      trsh.transformedShape());
+//        }
+
+//        correctNfpPosition(subnfp, sh, trsh);
+
+//        nfps = Nfp::merge(nfps, subnfp.first);
+//    }
+
+//    return nfps;
 }
 
-template<class RawShape>
-class _NofitPolyPlacer: public PlacerBoilerplate<_NofitPolyPlacer<RawShape>,
-        RawShape, _Box<TPoint<RawShape>>, NfpPConfig<RawShape>> {
+template<class RawShape, class TBin = _Box<TPoint<RawShape>>>
+class _NofitPolyPlacer: public PlacerBoilerplate<_NofitPolyPlacer<RawShape, TBin>,
+        RawShape, TBin, NfpPConfig<RawShape>> {
 
-    using Base = PlacerBoilerplate<_NofitPolyPlacer<RawShape>,
-    RawShape, _Box<TPoint<RawShape>>, NfpPConfig<RawShape>>;
+    using Base = PlacerBoilerplate<_NofitPolyPlacer<RawShape, TBin>,
+    RawShape, TBin, NfpPConfig<RawShape>>;
 
     DECLARE_PLACER(Base)
 
@@ -280,28 +456,45 @@ class _NofitPolyPlacer: public PlacerBoilerplate<_NofitPolyPlacer<RawShape>,
     const double penality_;
 
     using MaxNfpLevel = Nfp::MaxNfpLevel<RawShape>;
+    using sl = ShapeLike;
 
 public:
 
-    using Pile = const Nfp::Shapes<RawShape>&;
+    using Pile = Nfp::Shapes<RawShape>;
 
     inline explicit _NofitPolyPlacer(const BinType& bin):
         Base(bin),
-        norm_(std::sqrt(ShapeLike::area<RawShape>(bin))),
+        norm_(std::sqrt(sl::area<RawShape>(bin))),
         penality_(1e6*norm_) {}
 
+    _NofitPolyPlacer(const _NofitPolyPlacer&) = default;
+    _NofitPolyPlacer& operator=(const _NofitPolyPlacer&) = default;
+
+#ifndef BP2D_COMPILER_MSVC12 // MSVC2013 does not support default move ctors
+    _NofitPolyPlacer(_NofitPolyPlacer&&) BP2D_NOEXCEPT = default;
+    _NofitPolyPlacer& operator=(_NofitPolyPlacer&&) BP2D_NOEXCEPT = default;
+#endif
+
+    bool static inline wouldFit(const Box& bb, const RawShape& bin) {
+        auto bbin = sl::boundingBox<RawShape>(bin);
+        auto d = bbin.center() - bb.center();
+        _Rectangle<RawShape> rect(bb.width(), bb.height());
+        rect.translate(bb.minCorner() + d);
+        return sl::isInside<RawShape>(rect.transformedShape(), bin);
+    }
+
     bool static inline wouldFit(const RawShape& chull, const RawShape& bin) {
-        auto bbch = ShapeLike::boundingBox<RawShape>(chull);
-        auto bbin = ShapeLike::boundingBox<RawShape>(bin);
-        auto d = bbin.minCorner() - bbch.minCorner();
+        auto bbch = sl::boundingBox<RawShape>(chull);
+        auto bbin = sl::boundingBox<RawShape>(bin);
+        auto d =  bbch.center() - bbin.center();
         auto chullcpy = chull;
-        ShapeLike::translate(chullcpy, d);
-        return ShapeLike::isInside<RawShape>(chullcpy, bbin);
+        sl::translate(chullcpy, d);
+        return sl::isInside<RawShape>(chullcpy, bin);
     }
 
     bool static inline wouldFit(const RawShape& chull, const Box& bin)
     {
-        auto bbch = ShapeLike::boundingBox<RawShape>(chull);
+        auto bbch = sl::boundingBox<RawShape>(chull);
         return wouldFit(bbch, bin);
     }
 
@@ -310,6 +503,17 @@ public:
         return bb.width() <= bin.width() && bb.height() <= bin.height();
     }
 
+    bool static inline wouldFit(const Box& bb, const _Circle<Vertex>& bin)
+    {
+        return sl::isInside<RawShape>(bb, bin);
+    }
+
+    bool static inline wouldFit(const RawShape& chull,
+                                const _Circle<Vertex>& bin)
+    {
+        return sl::isInside<RawShape>(chull, bin);
+    }
+
     PackResult trypack(Item& item) {
 
         PackResult ret;
@@ -348,7 +552,10 @@ public:
                 std::vector<EdgeCache<RawShape>> ecache;
                 ecache.reserve(nfps.size());
 
-                for(auto& nfp : nfps ) ecache.emplace_back(nfp);
+                for(auto& nfp : nfps ) {
+                    ecache.emplace_back(nfp);
+                    ecache.back().accuracy(config_.accuracy);
+                }
 
                 struct Optimum {
                     double relpos;
@@ -363,7 +570,7 @@ public:
                 auto getNfpPoint = [&ecache](const Optimum& opt)
                 {
                     return opt.hidx < 0? ecache[opt.nfpidx].coords(opt.relpos) :
-                            ecache[opt.nfpidx].coords(opt.nfpidx, opt.relpos);
+                            ecache[opt.nfpidx].coords(opt.hidx, opt.relpos);
                 };
 
                 Nfp::Shapes<RawShape> pile;
@@ -374,17 +581,25 @@ public:
                     pile_area += mitem.area();
                 }
 
+                auto merged_pile = Nfp::merge(pile);
+
                 // This is the kernel part of the object function that is
                 // customizable by the library client
                 auto _objfunc = config_.object_function?
                             config_.object_function :
-                [this](const Nfp::Shapes<RawShape>& pile, double occupied_area,
-                            double /*norm*/, double penality)
+                [this, &merged_pile](
+                            Nfp::Shapes<RawShape>& /*pile*/,
+                            const Item& item,
+                            double occupied_area,
+                            double norm,
+                            double /*penality*/)
                 {
-                    auto ch = ShapeLike::convexHull(pile);
+                    merged_pile.emplace_back(item.transformedShape());
+                    auto ch = sl::convexHull(merged_pile);
+                    merged_pile.pop_back();
 
                     // The pack ratio -- how much is the convex hull occupied
-                    double pack_rate = occupied_area/ShapeLike::area(ch);
+                    double pack_rate = occupied_area/sl::area(ch);
 
                     // ratio of waste
                     double waste = 1.0 - pack_rate;
@@ -394,7 +609,7 @@ public:
                     // (larger) values.
                     auto score = std::sqrt(waste);
 
-                    if(!wouldFit(ch, bin_)) score = 2*penality - score;
+                    if(!wouldFit(ch, bin_)) score += norm;
 
                     return score;
                 };
@@ -406,23 +621,31 @@ public:
                     d += startpos;
                     item.translation(d);
 
-                    pile.emplace_back(item.transformedShape());
-
                     double occupied_area = pile_area + item.area();
 
-                    double score = _objfunc(pile, occupied_area,
+                    double score = _objfunc(pile, item, occupied_area,
                                             norm_, penality_);
 
-                    pile.pop_back();
-
                     return score;
                 };
 
+                auto boundaryCheck = [&](const Optimum& o) {
+                    auto v = getNfpPoint(o);
+                    auto d = v - iv;
+                    d += startpos;
+                    item.translation(d);
+
+                    merged_pile.emplace_back(item.transformedShape());
+                    auto chull = sl::convexHull(merged_pile);
+                    merged_pile.pop_back();
+
+                    return wouldFit(chull, bin_);
+                };
+
                 opt::StopCriteria stopcr;
-                stopcr.max_iterations = 1000;
-                stopcr.stoplimit = 0.001;
-                stopcr.type = opt::StopLimitType::RELATIVE;
-                opt::TOptimizer<opt::Method::L_SIMPLEX> solver(stopcr);
+                stopcr.max_iterations = 100;
+                stopcr.relative_score_difference = 1e-6;
+                opt::TOptimizer<opt::Method::L_SUBPLEX> solver(stopcr);
 
                 Optimum optimum(0, 0);
                 double best_score = penality_;
@@ -441,7 +664,7 @@ public:
                     std::for_each(cache.corners().begin(),
                                   cache.corners().end(),
                                   [ch, &contour_ofn, &solver, &best_score,
-                                  &optimum] (double pos)
+                                  &optimum, &boundaryCheck] (double pos)
                     {
                         try {
                             auto result = solver.optimize_min(contour_ofn,
@@ -450,10 +673,11 @@ public:
                                             );
 
                             if(result.score < best_score) {
-                                best_score = result.score;
-                                optimum.relpos = std::get<0>(result.optimum);
-                                optimum.nfpidx = ch;
-                                optimum.hidx = -1;
+                                Optimum o(std::get<0>(result.optimum), ch, -1);
+                                if(boundaryCheck(o)) {
+                                    best_score = result.score;
+                                    optimum = o;
+                                }
                             }
                         } catch(std::exception& e) {
                             derr() << "ERROR: " << e.what() << "\n";
@@ -472,7 +696,7 @@ public:
                         std::for_each(cache.corners(hidx).begin(),
                                       cache.corners(hidx).end(),
                                       [&hole_ofn, &solver, &best_score,
-                                       &optimum, ch, hidx]
+                                       &optimum, ch, hidx, &boundaryCheck]
                                       (double pos)
                         {
                             try {
@@ -482,10 +706,12 @@ public:
                                                 );
 
                                 if(result.score < best_score) {
-                                    best_score = result.score;
                                     Optimum o(std::get<0>(result.optimum),
                                               ch, hidx);
-                                    optimum = o;
+                                    if(boundaryCheck(o)) {
+                                        best_score = result.score;
+                                        optimum = o;
+                                    }
                                 }
                             } catch(std::exception& e) {
                                 derr() << "ERROR: " << e.what() << "\n";
@@ -524,34 +750,35 @@ public:
         m.reserve(items_.size());
 
         for(Item& item : items_) m.emplace_back(item.transformedShape());
-        auto&& bb = ShapeLike::boundingBox<RawShape>(m);
+        auto&& bb = sl::boundingBox<RawShape>(m);
 
         Vertex ci, cb;
+        auto bbin = sl::boundingBox<RawShape>(bin_);
 
         switch(config_.alignment) {
         case Config::Alignment::CENTER: {
             ci = bb.center();
-            cb = bin_.center();
+            cb = bbin.center();
             break;
         }
         case Config::Alignment::BOTTOM_LEFT: {
             ci = bb.minCorner();
-            cb = bin_.minCorner();
+            cb = bbin.minCorner();
             break;
         }
         case Config::Alignment::BOTTOM_RIGHT: {
             ci = {getX(bb.maxCorner()), getY(bb.minCorner())};
-            cb = {getX(bin_.maxCorner()), getY(bin_.minCorner())};
+            cb = {getX(bbin.maxCorner()), getY(bbin.minCorner())};
             break;
         }
         case Config::Alignment::TOP_LEFT: {
             ci = {getX(bb.minCorner()), getY(bb.maxCorner())};
-            cb = {getX(bin_.minCorner()), getY(bin_.maxCorner())};
+            cb = {getX(bbin.minCorner()), getY(bbin.maxCorner())};
             break;
         }
         case Config::Alignment::TOP_RIGHT: {
             ci = bb.maxCorner();
-            cb = bin_.maxCorner();
+            cb = bbin.maxCorner();
             break;
         }
         }
@@ -567,31 +794,32 @@ private:
     void setInitialPosition(Item& item) {
         Box&& bb = item.boundingBox();
         Vertex ci, cb;
+        auto bbin = sl::boundingBox<RawShape>(bin_);
 
         switch(config_.starting_point) {
         case Config::Alignment::CENTER: {
             ci = bb.center();
-            cb = bin_.center();
+            cb = bbin.center();
             break;
         }
         case Config::Alignment::BOTTOM_LEFT: {
             ci = bb.minCorner();
-            cb = bin_.minCorner();
+            cb = bbin.minCorner();
             break;
         }
         case Config::Alignment::BOTTOM_RIGHT: {
             ci = {getX(bb.maxCorner()), getY(bb.minCorner())};
-            cb = {getX(bin_.maxCorner()), getY(bin_.minCorner())};
+            cb = {getX(bbin.maxCorner()), getY(bbin.minCorner())};
             break;
         }
         case Config::Alignment::TOP_LEFT: {
             ci = {getX(bb.minCorner()), getY(bb.maxCorner())};
-            cb = {getX(bin_.minCorner()), getY(bin_.maxCorner())};
+            cb = {getX(bbin.minCorner()), getY(bbin.maxCorner())};
             break;
         }
         case Config::Alignment::TOP_RIGHT: {
             ci = bb.maxCorner();
-            cb = bin_.maxCorner();
+            cb = bbin.maxCorner();
             break;
         }
         }
@@ -602,7 +830,7 @@ private:
 
     void placeOutsideOfBin(Item& item) {
         auto&& bb = item.boundingBox();
-        Box binbb = ShapeLike::boundingBox<RawShape>(bin_);
+        Box binbb = sl::boundingBox<RawShape>(bin_);
 
         Vertex v = { getX(bb.maxCorner()), getY(bb.minCorner()) };
 
diff --git a/xs/src/libnest2d/libnest2d/selections/djd_heuristic.hpp b/xs/src/libnest2d/libnest2d/selections/djd_heuristic.hpp
index 1d233cf35..e3ad97c10 100644
--- a/xs/src/libnest2d/libnest2d/selections/djd_heuristic.hpp
+++ b/xs/src/libnest2d/libnest2d/selections/djd_heuristic.hpp
@@ -256,14 +256,14 @@ public:
 
             if(not_packed.size() < 2)
                 return false; // No group of two items
-            else {
-                double largest_area = not_packed.front().get().area();
-                auto itmp = not_packed.begin(); itmp++;
-                double second_largest = itmp->get().area();
-                if( free_area - second_largest - largest_area > waste)
-                    return false; // If even the largest two items do not fill
-                    // the bin to the desired waste than we can end here.
-            }
+
+            double largest_area = not_packed.front().get().area();
+            auto itmp = not_packed.begin(); itmp++;
+            double second_largest = itmp->get().area();
+            if( free_area - second_largest - largest_area > waste)
+                return false; // If even the largest two items do not fill
+                // the bin to the desired waste than we can end here.
+
 
             bool ret = false;
             auto it = not_packed.begin();
@@ -481,7 +481,7 @@ public:
                             {
                                 std::array<bool, 3> packed = {false};
 
-                                for(auto id : idx) packed[id] =
+                                for(auto id : idx) packed.at(id) =
                                         placer.pack(candidates[id]);
 
                                 bool check =
@@ -535,10 +535,9 @@ public:
         // then it should be removed from the not_packed list
         { auto it = store_.begin();
             while (it != store_.end()) {
-                Placer p(bin);
+                Placer p(bin); p.configure(pconfig);
                 if(!p.pack(*it)) {
-                    auto itmp = it++;
-                    store_.erase(itmp);
+                    it = store_.erase(it);
                 } else it++;
             }
         }
@@ -605,8 +604,7 @@ public:
                         if(placer.pack(*it)) {
                             filled_area += it->get().area();
                             free_area = bin_area - filled_area;
-                            auto itmp = it++;
-                            not_packed.erase(itmp);
+                            it = not_packed.erase(it);
                             makeProgress(placer, idx, 1);
                         } else it++;
                     }
diff --git a/xs/src/libnest2d/libnest2d/selections/firstfit.hpp b/xs/src/libnest2d/libnest2d/selections/firstfit.hpp
index b6e80520c..665b9da9f 100644
--- a/xs/src/libnest2d/libnest2d/selections/firstfit.hpp
+++ b/xs/src/libnest2d/libnest2d/selections/firstfit.hpp
@@ -52,17 +52,16 @@ public:
         auto total = last-first;
         auto makeProgress = [this, &total](Placer& placer, size_t idx) {
             packed_bins_[idx] = placer.getItems();
-            this->progress_(--total);
+            this->progress_(static_cast<unsigned>(--total));
         };
 
         // Safety test: try to pack each item into an empty bin. If it fails
         // then it should be removed from the list
         { auto it = store_.begin();
             while (it != store_.end()) {
-                Placer p(bin);
+                Placer p(bin); p.configure(pconfig);
                 if(!p.pack(*it)) {
-                    auto itmp = it++;
-                    store_.erase(itmp);
+                    it = store_.erase(it);
                 } else it++;
             }
         }
diff --git a/xs/src/libnest2d/tests/test.cpp b/xs/src/libnest2d/tests/test.cpp
index b37274f84..39315ff1a 100644
--- a/xs/src/libnest2d/tests/test.cpp
+++ b/xs/src/libnest2d/tests/test.cpp
@@ -682,7 +682,9 @@ void testNfp(const std::vector<ItemPair>& testdata) {
         auto&& nfp = Nfp::noFitPolygon<lvl>(stationary.rawShape(),
                                             orbiter.transformedShape());
 
-        auto v = ShapeLike::isValid(nfp);
+        strategies::correctNfpPosition(nfp, stationary, orbiter);
+
+        auto v = ShapeLike::isValid(nfp.first);
 
         if(!v.first) {
             std::cout << v.second << std::endl;
@@ -690,7 +692,7 @@ void testNfp(const std::vector<ItemPair>& testdata) {
 
         ASSERT_TRUE(v.first);
 
-        Item infp(nfp);
+        Item infp(nfp.first);
 
         int i = 0;
         auto rorbiter = orbiter.transformedShape();
@@ -742,6 +744,15 @@ TEST(GeometryAlgorithms, nfpConvexConvex) {
 //    testNfp<NfpLevel::BOTH_CONCAVE, 1000>(nfp_concave_testdata);
 //}
 
+TEST(GeometryAlgorithms, nfpConcaveConcave) {
+    using namespace libnest2d;
+
+//    Rectangle r1(10, 10);
+//    Rectangle r2(20, 20);
+//    auto result = Nfp::nfpSimpleSimple(r1.transformedShape(),
+//                                       r2.transformedShape());
+}
+
 TEST(GeometryAlgorithms, pointOnPolygonContour) {
     using namespace libnest2d;
 
diff --git a/xs/src/libnest2d/tools/libnfpglue.cpp b/xs/src/libnest2d/tools/libnfpglue.cpp
index 4cbdb5442..18656fd40 100644
--- a/xs/src/libnest2d/tools/libnfpglue.cpp
+++ b/xs/src/libnest2d/tools/libnfpglue.cpp
@@ -49,18 +49,18 @@ libnfporb::point_t scale(const libnfporb::point_t& p, long double factor) {
     long double px = p.x_.val();
     long double py = p.y_.val();
 #endif
-    return libnfporb::point_t(px*factor, py*factor);
+    return {px*factor, py*factor};
 }
 
 }
 
-PolygonImpl _nfp(const PolygonImpl &sh, const PolygonImpl &cother)
+NfpR _nfp(const PolygonImpl &sh, const PolygonImpl &cother)
 {
     using Vertex = PointImpl;
 
-    PolygonImpl ret;
+    NfpR ret;
 
-//    try {
+    try {
         libnfporb::polygon_t pstat, porb;
 
         boost::geometry::convert(sh, pstat);
@@ -85,7 +85,7 @@ PolygonImpl _nfp(const PolygonImpl &sh, const PolygonImpl &cother)
         // this can throw
         auto nfp = libnfporb::generateNFP(pstat, porb, true);
 
-        auto &ct = ShapeLike::getContour(ret);
+        auto &ct = ShapeLike::getContour(ret.first);
         ct.reserve(nfp.front().size()+1);
         for(auto v : nfp.front()) {
             v = scale(v, refactor);
@@ -94,10 +94,10 @@ PolygonImpl _nfp(const PolygonImpl &sh, const PolygonImpl &cother)
         ct.push_back(ct.front());
         std::reverse(ct.begin(), ct.end());
 
-        auto &rholes = ShapeLike::holes(ret);
+        auto &rholes = ShapeLike::holes(ret.first);
         for(size_t hidx = 1; hidx < nfp.size(); ++hidx) {
             if(nfp[hidx].size() >= 3) {
-                rholes.push_back({});
+                rholes.emplace_back();
                 auto& h = rholes.back();
                 h.reserve(nfp[hidx].size()+1);
 
@@ -110,73 +110,48 @@ PolygonImpl _nfp(const PolygonImpl &sh, const PolygonImpl &cother)
             }
         }
 
-        auto& cmp = vsort;
-        std::sort(pstat.outer().begin(), pstat.outer().end(), cmp);
-        std::sort(porb.outer().begin(), porb.outer().end(), cmp);
+        ret.second = Nfp::referenceVertex(ret.first);
 
-        // leftmost lower vertex of the stationary polygon
-        auto& touch_sh = scale(pstat.outer().back(), refactor);
-        // rightmost upper vertex of the orbiting polygon
-        auto& touch_other = scale(porb.outer().front(), refactor);
-
-        // Calculate the difference and move the orbiter to the touch position.
-        auto dtouch = touch_sh - touch_other;
-        auto _top_other = scale(porb.outer().back(), refactor) + dtouch;
-
-        Vertex top_other(getX(_top_other), getY(_top_other));
-
-        // Get the righmost upper vertex of the nfp and move it to the RMU of
-        // the orbiter because they should coincide.
-        auto&& top_nfp = Nfp::rightmostUpVertex(ret);
-        auto dnfp = top_other - top_nfp;
-
-        std::for_each(ShapeLike::begin(ret), ShapeLike::end(ret),
-                      [&dnfp](Vertex& v) { v+= dnfp; } );
-
-        for(auto& h : ShapeLike::holes(ret))
-            std::for_each( h.begin(), h.end(),
-                           [&dnfp](Vertex& v) { v += dnfp; } );
-
-//    } catch(std::exception& e) {
-//        std::cout << "Error: " << e.what() << "\nTrying with convex hull..." << std::endl;
+    } catch(std::exception& e) {
+        std::cout << "Error: " << e.what() << "\nTrying with convex hull..." << std::endl;
 //        auto ch_stat = ShapeLike::convexHull(sh);
 //        auto ch_orb = ShapeLike::convexHull(cother);
-//        ret = Nfp::nfpConvexOnly(ch_stat, ch_orb);
-//    }
+        ret = Nfp::nfpConvexOnly(sh, cother);
+    }
 
     return ret;
 }
 
-PolygonImpl Nfp::NfpImpl<PolygonImpl, NfpLevel::CONVEX_ONLY>::operator()(
+NfpR Nfp::NfpImpl<PolygonImpl, NfpLevel::CONVEX_ONLY>::operator()(
         const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
 {
     return _nfp(sh, cother);//nfpConvexOnly(sh, cother);
 }
 
-PolygonImpl Nfp::NfpImpl<PolygonImpl, NfpLevel::ONE_CONVEX>::operator()(
+NfpR Nfp::NfpImpl<PolygonImpl, NfpLevel::ONE_CONVEX>::operator()(
         const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
 {
     return _nfp(sh, cother);
 }
 
-PolygonImpl Nfp::NfpImpl<PolygonImpl, NfpLevel::BOTH_CONCAVE>::operator()(
+NfpR Nfp::NfpImpl<PolygonImpl, NfpLevel::BOTH_CONCAVE>::operator()(
         const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
 {
     return _nfp(sh, cother);
 }
 
-PolygonImpl
-Nfp::NfpImpl<PolygonImpl, NfpLevel::ONE_CONVEX_WITH_HOLES>::operator()(
-        const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
-{
-    return _nfp(sh, cother);
-}
+//PolygonImpl
+//Nfp::NfpImpl<PolygonImpl, NfpLevel::ONE_CONVEX_WITH_HOLES>::operator()(
+//        const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
+//{
+//    return _nfp(sh, cother);
+//}
 
-PolygonImpl
-Nfp::NfpImpl<PolygonImpl, NfpLevel::BOTH_CONCAVE_WITH_HOLES>::operator()(
-        const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
-{
-    return _nfp(sh, cother);
-}
+//PolygonImpl
+//Nfp::NfpImpl<PolygonImpl, NfpLevel::BOTH_CONCAVE_WITH_HOLES>::operator()(
+//        const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
+//{
+//    return _nfp(sh, cother);
+//}
 
 }
diff --git a/xs/src/libnest2d/tools/libnfpglue.hpp b/xs/src/libnest2d/tools/libnfpglue.hpp
index 87b0e0833..75f639445 100644
--- a/xs/src/libnest2d/tools/libnfpglue.hpp
+++ b/xs/src/libnest2d/tools/libnfpglue.hpp
@@ -5,37 +5,39 @@
 
 namespace libnest2d {
 
-PolygonImpl _nfp(const PolygonImpl& sh, const PolygonImpl& cother);
+using NfpR = Nfp::NfpResult<PolygonImpl>;
+
+NfpR _nfp(const PolygonImpl& sh, const PolygonImpl& cother);
 
 template<>
 struct Nfp::NfpImpl<PolygonImpl, NfpLevel::CONVEX_ONLY> {
-    PolygonImpl operator()(const PolygonImpl& sh, const PolygonImpl& cother);
+    NfpR operator()(const PolygonImpl& sh, const PolygonImpl& cother);
 };
 
 template<>
 struct Nfp::NfpImpl<PolygonImpl, NfpLevel::ONE_CONVEX> {
-    PolygonImpl operator()(const PolygonImpl& sh, const PolygonImpl& cother);
+    NfpR operator()(const PolygonImpl& sh, const PolygonImpl& cother);
 };
 
 template<>
 struct Nfp::NfpImpl<PolygonImpl, NfpLevel::BOTH_CONCAVE> {
-    PolygonImpl operator()(const PolygonImpl& sh, const PolygonImpl& cother);
+    NfpR operator()(const PolygonImpl& sh, const PolygonImpl& cother);
 };
 
-template<>
-struct Nfp::NfpImpl<PolygonImpl, NfpLevel::ONE_CONVEX_WITH_HOLES> {
-    PolygonImpl operator()(const PolygonImpl& sh, const PolygonImpl& cother);
-};
+//template<>
+//struct Nfp::NfpImpl<PolygonImpl, NfpLevel::ONE_CONVEX_WITH_HOLES> {
+//    NfpResult operator()(const PolygonImpl& sh, const PolygonImpl& cother);
+//};
 
-template<>
-struct Nfp::NfpImpl<PolygonImpl, NfpLevel::BOTH_CONCAVE_WITH_HOLES> {
-    PolygonImpl operator()(const PolygonImpl& sh, const PolygonImpl& cother);
-};
+//template<>
+//struct Nfp::NfpImpl<PolygonImpl, NfpLevel::BOTH_CONCAVE_WITH_HOLES> {
+//    NfpResult operator()(const PolygonImpl& sh, const PolygonImpl& cother);
+//};
 
 template<> struct Nfp::MaxNfpLevel<PolygonImpl> {
     static const BP2D_CONSTEXPR NfpLevel value =
 //            NfpLevel::CONVEX_ONLY;
-            NfpLevel::BOTH_CONCAVE_WITH_HOLES;
+            NfpLevel::BOTH_CONCAVE;
 };
 
 }
diff --git a/xs/src/libnest2d/tools/svgtools.hpp b/xs/src/libnest2d/tools/svgtools.hpp
index 273ecabac..3a83caa70 100644
--- a/xs/src/libnest2d/tools/svgtools.hpp
+++ b/xs/src/libnest2d/tools/svgtools.hpp
@@ -5,11 +5,17 @@
 #include <fstream>
 #include <string>
 
-#include <libnest2d.h>
+#include <libnest2d/libnest2d.hpp>
 
 namespace libnest2d { namespace svg {
 
+template<class RawShape>
 class SVGWriter {
+    using Item = _Item<RawShape>;
+    using Coord = TCoord<TPoint<RawShape>>;
+    using Box = _Box<TPoint<RawShape>>;
+    using PackGroup = _PackGroup<RawShape>;
+
 public:
 
     enum OrigoLocation {
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index 94634f4e4..b34ba5441 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -167,6 +167,18 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
 {
     std::string gcode;
 
+    // Toolchangeresult.gcode assumes the wipe tower corner is at the origin
+    // We want to rotate and shift all extrusions (gcode postprocessing) and starting and ending position
+    float alpha = m_wipe_tower_rotation/180.f * M_PI;
+    WipeTower::xy start_pos = tcr.start_pos;
+    WipeTower::xy end_pos = tcr.end_pos;
+    start_pos.rotate(alpha);
+    start_pos.translate(m_wipe_tower_pos);
+    end_pos.rotate(alpha);
+    end_pos.translate(m_wipe_tower_pos);
+    std::string tcr_rotated_gcode = rotate_wipe_tower_moves(tcr.gcode, tcr.start_pos, m_wipe_tower_pos, alpha);
+    
+
     // Disable linear advance for the wipe tower operations.
     gcode += "M900 K0\n";
     // Move over the wipe tower.
@@ -174,14 +186,14 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
     gcode += gcodegen.retract(true);
     gcodegen.m_avoid_crossing_perimeters.use_external_mp_once = true;
     gcode += gcodegen.travel_to(
-        wipe_tower_point_to_object_point(gcodegen, tcr.start_pos),
+        wipe_tower_point_to_object_point(gcodegen, start_pos),
         erMixed,
         "Travel to a Wipe Tower");
     gcode += gcodegen.unretract();
 
     // Let the tool change be executed by the wipe tower class.
     // Inform the G-code writer about the changes done behind its back.
-    gcode += tcr.gcode;
+    gcode += tcr_rotated_gcode;
     // Let the m_writer know the current extruder_id, but ignore the generated G-code.
 	if (new_extruder_id >= 0 && gcodegen.writer().need_toolchange(new_extruder_id))
         gcodegen.writer().toolchange(new_extruder_id);
@@ -195,18 +207,18 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
         check_add_eol(gcode);
     }
     // A phony move to the end position at the wipe tower.
-    gcodegen.writer().travel_to_xy(Pointf(tcr.end_pos.x, tcr.end_pos.y));
-    gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, tcr.end_pos));
+    gcodegen.writer().travel_to_xy(Pointf(end_pos.x, end_pos.y));
+    gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, end_pos));
 
     // Prepare a future wipe.
     gcodegen.m_wipe.path.points.clear();
     if (new_extruder_id >= 0) {
         // Start the wipe at the current position.
-        gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, tcr.end_pos));
+        gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, end_pos));
         // Wipe end point: Wipe direction away from the closer tower edge to the further tower edge.
         gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, 
-            WipeTower::xy((std::abs(m_left - tcr.end_pos.x) < std::abs(m_right - tcr.end_pos.x)) ? m_right : m_left,
-            tcr.end_pos.y)));
+            WipeTower::xy((std::abs(m_left - end_pos.x) < std::abs(m_right - end_pos.x)) ? m_right : m_left,
+            end_pos.y)));
     }
 
     // Let the planner know we are traveling between objects.
@@ -214,6 +226,57 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
     return gcode;
 }
 
+// This function postprocesses gcode_original, rotates and moves all G1 extrusions and returns resulting gcode
+// Starting position has to be supplied explicitely (otherwise it would fail in case first G1 command only contained one coordinate)
+std::string WipeTowerIntegration::rotate_wipe_tower_moves(const std::string& gcode_original, const WipeTower::xy& start_pos, const WipeTower::xy& translation, float angle) const
+{
+    std::istringstream gcode_str(gcode_original);
+    std::string gcode_out;
+    std::string line;
+    WipeTower::xy pos = start_pos;
+    WipeTower::xy transformed_pos;
+    WipeTower::xy old_pos(-1000.1f, -1000.1f);
+
+    while (gcode_str) {
+        std::getline(gcode_str, line);  // we read the gcode line by line
+        if (line.find("G1 ") == 0) {
+            std::ostringstream line_out;
+            std::istringstream line_str(line);
+            line_str >> std::noskipws;  // don't skip whitespace
+            char ch = 0;
+            while (line_str >> ch) {
+                if (ch == 'X')
+                    line_str >> pos.x;
+                else
+                    if (ch == 'Y')
+                        line_str >> pos.y;
+                    else
+                        line_out << ch;
+            }
+
+            transformed_pos = pos;
+            transformed_pos.rotate(angle);
+            transformed_pos.translate(translation);
+
+            if (transformed_pos != old_pos) {
+                line = line_out.str();
+                char buf[2048] = "G1";
+                if (transformed_pos.x != old_pos.x)
+                    sprintf(buf + strlen(buf), " X%.3f", transformed_pos.x);
+                if (transformed_pos.y != old_pos.y)
+                    sprintf(buf + strlen(buf), " Y%.3f", transformed_pos.y);
+
+                line.replace(line.find("G1 "), 3, buf);
+                old_pos = transformed_pos;
+            }
+        }
+        gcode_out += line + "\n";
+    }
+    return gcode_out;
+}
+
+
+
 std::string WipeTowerIntegration::prime(GCode &gcodegen)
 {
     assert(m_layer_idx == 0);
@@ -377,10 +440,9 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
     }
     fclose(file);
 
-    if (print->config.gcode_flavor.value == gcfMarlin)
+    if (print->config.remaining_times.value)
     {
         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);
     }
@@ -462,8 +524,21 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
             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]);
+            if (print.config.single_extruder_multi_material) {
+                // As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they
+                // are considered to be active for the single extruder multi-material printers only.
+                m_silent_time_estimator.set_filament_load_times(print.config.filament_load_time.values);
+                m_silent_time_estimator.set_filament_unload_times(print.config.filament_unload_time.values);
+            }
         }
     }
+    // Filament load / unload times are not specific to a firmware flavor. Let anybody use it if they find it useful.
+    if (print.config.single_extruder_multi_material) {
+        // As of now the fields are shown at the UI dialog in the same combo box as the ramming values, so they
+        // are considered to be active for the single extruder multi-material printers only.
+        m_normal_time_estimator.set_filament_load_times(print.config.filament_load_time.values);
+        m_normal_time_estimator.set_filament_unload_times(print.config.filament_unload_time.values);
+    }
 
     // resets analyzer
     m_analyzer.reset();
@@ -608,15 +683,18 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
             if ((initial_extruder_id = tool_ordering.first_extruder()) != (unsigned int)-1)
                 break;
         }
-    }
-    else {
+    } else {
 		// Find tool ordering for all the objects at once, and the initial extruder ID.
         // If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it.
 		tool_ordering = print.m_tool_ordering.empty() ?
             ToolOrdering(print, initial_extruder_id) :
             print.m_tool_ordering;
-		initial_extruder_id = tool_ordering.first_extruder();
         has_wipe_tower = print.has_wipe_tower() && tool_ordering.has_wipe_tower();
+        initial_extruder_id = (has_wipe_tower && ! print.config.single_extruder_multi_material_priming) ? 
+            // The priming towers will be skipped.
+            tool_ordering.all_extruders().back() :
+            // Don't skip the priming towers. 
+            tool_ordering.first_extruder();
     }
     if (initial_extruder_id == (unsigned int)-1) {
         // Nothing to print!
@@ -644,6 +722,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
     m_placeholder_parser.set("current_object_idx", 0);
     // For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided.
     m_placeholder_parser.set("has_wipe_tower", has_wipe_tower);
+    m_placeholder_parser.set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config.single_extruder_multi_material_priming);
     std::string start_gcode = this->placeholder_parser_process("start_gcode", print.config.start_gcode.value, initial_extruder_id);
     
     // Set bed temperature if the start G-code does not contain any bed temp control G-codes.
@@ -724,8 +803,11 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
         }
     }
     
-    // Set initial extruder only after custom start G-code.
-    _write(file, this->set_extruder(initial_extruder_id));
+    if (! (has_wipe_tower && print.config.single_extruder_multi_material_priming)) {
+        // Set initial extruder only after custom start G-code.
+        // Ugly hack: Do not set the initial extruder if the extruder is primed using the MMU priming towers at the edge of the print bed.
+        _write(file, this->set_extruder(initial_extruder_id));
+    }
 
     // Do all objects for each layer.
     if (print.config.complete_objects.value) {
@@ -803,27 +885,29 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
         if (has_wipe_tower && ! layers_to_print.empty()) {
             m_wipe_tower.reset(new WipeTowerIntegration(print.config, *print.m_wipe_tower_priming.get(), print.m_wipe_tower_tool_changes, *print.m_wipe_tower_final_purge.get()));
             _write(file, m_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height"));
-		    _write(file, m_wipe_tower->prime(*this));
-            // Verify, whether the print overaps the priming extrusions.
-            BoundingBoxf bbox_print(get_print_extrusions_extents(print));
-            coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON;
-            for (const PrintObject *print_object : printable_objects)
-                bbox_print.merge(get_print_object_extrusions_extents(*print_object, twolayers_printz));
-            bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz));
-            BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print));
-            bbox_prime.offset(0.5f);
-            // Beep for 500ms, tone 800Hz. Yet better, play some Morse.
-            _write(file, this->retract());
-            _write(file, "M300 S800 P500\n");
-            if (bbox_prime.overlap(bbox_print)) {
-                // Wait for the user to remove the priming extrusions, otherwise they would
-                // get covered by the print.
-                _write(file, "M1 Remove priming towers and click button.\n");
-            }
-            else {
-                // Just wait for a bit to let the user check, that the priming succeeded.
-                //TODO Add a message explaining what the printer is waiting for. This needs a firmware fix.
-                _write(file, "M1 S10\n");
+            if (print.config.single_extruder_multi_material_priming) {
+    		    _write(file, m_wipe_tower->prime(*this));
+                // Verify, whether the print overaps the priming extrusions.
+                BoundingBoxf bbox_print(get_print_extrusions_extents(print));
+                coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON;
+                for (const PrintObject *print_object : printable_objects)
+                    bbox_print.merge(get_print_object_extrusions_extents(*print_object, twolayers_printz));
+                bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz));
+                BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print));
+                bbox_prime.offset(0.5f);
+                // Beep for 500ms, tone 800Hz. Yet better, play some Morse.
+                _write(file, this->retract());
+                _write(file, "M300 S800 P500\n");
+                if (bbox_prime.overlap(bbox_print)) {
+                    // Wait for the user to remove the priming extrusions, otherwise they would
+                    // get covered by the print.
+                    _write(file, "M1 Remove priming towers and click button.\n");
+                }
+                else {
+                    // Just wait for a bit to let the user check, that the priming succeeded.
+                    //TODO Add a message explaining what the printer is waiting for. This needs a firmware fix.
+                    _write(file, "M1 S10\n");
+                }
             }
         }
         // Extrude the layers.
@@ -1003,9 +1087,10 @@ void GCode::print_machine_envelope(FILE *file, Print &print)
             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",
+        fprintf(file, "M204 P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), 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));
+            int(print.config.machine_max_acceleration_retracting.values.front() + 0.5),
+            int(print.config.machine_max_acceleration_extruding.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(),
diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp
index 8b40385e6..4953c39fe 100644
--- a/xs/src/libslic3r/GCode.hpp
+++ b/xs/src/libslic3r/GCode.hpp
@@ -83,8 +83,10 @@ public:
         const WipeTower::ToolChangeResult                           &priming,
         const std::vector<std::vector<WipeTower::ToolChangeResult>> &tool_changes,
         const WipeTower::ToolChangeResult                           &final_purge) :
-        m_left(float(print_config.wipe_tower_x.value)),
-        m_right(float(print_config.wipe_tower_x.value + print_config.wipe_tower_width.value)),
+        m_left(/*float(print_config.wipe_tower_x.value)*/ 0.f),
+        m_right(float(/*print_config.wipe_tower_x.value +*/ print_config.wipe_tower_width.value)),
+        m_wipe_tower_pos(float(print_config.wipe_tower_x.value), float(print_config.wipe_tower_y.value)),
+        m_wipe_tower_rotation(float(print_config.wipe_tower_rotation_angle)),
         m_priming(priming),
         m_tool_changes(tool_changes),
         m_final_purge(final_purge),
@@ -101,9 +103,14 @@ private:
     WipeTowerIntegration& operator=(const WipeTowerIntegration&);
     std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id) const;
 
+    // Postprocesses gcode: rotates and moves all G1 extrusions and returns result
+    std::string rotate_wipe_tower_moves(const std::string& gcode_original, const WipeTower::xy& start_pos, const WipeTower::xy& translation, float angle) const;
+
     // Left / right edges of the wipe tower, for the planning of wipe moves.
     const float                                                  m_left;
     const float                                                  m_right;
+    const WipeTower::xy                                          m_wipe_tower_pos;
+    const float                                                  m_wipe_tower_rotation;
     // Reference to cached values at the Printer class.
     const WipeTower::ToolChangeResult                           &m_priming;
     const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes;
@@ -112,6 +119,7 @@ private:
     int                                                          m_layer_idx;
     int                                                          m_tool_change_idx;
     bool                                                         m_brim_done;
+    bool                                                         i_have_brim = false;
 };
 
 class GCode {
diff --git a/xs/src/libslic3r/GCode/PrintExtents.cpp b/xs/src/libslic3r/GCode/PrintExtents.cpp
index 3c3f0f8d5..37b79f343 100644
--- a/xs/src/libslic3r/GCode/PrintExtents.cpp
+++ b/xs/src/libslic3r/GCode/PrintExtents.cpp
@@ -134,6 +134,11 @@ BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object
 // The projection does not contain the priming regions.
 BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_t max_print_z)
 {
+    // Wipe tower extrusions are saved as if the tower was at the origin with no rotation
+    // We need to get position and angle of the wipe tower to transform them to actual position.
+    Pointf wipe_tower_pos(print.config.wipe_tower_x.value, print.config.wipe_tower_y.value);
+    float wipe_tower_angle = print.config.wipe_tower_rotation_angle.value;
+
     BoundingBoxf bbox;
     for (const std::vector<WipeTower::ToolChangeResult> &tool_changes : print.m_wipe_tower_tool_changes) {
         if (! tool_changes.empty() && tool_changes.front().print_z > max_print_z)
@@ -144,6 +149,11 @@ BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_
                 if (e.width > 0) {
                     Pointf  p1((&e - 1)->pos.x, (&e - 1)->pos.y);
                     Pointf  p2(e.pos.x, e.pos.y);
+                    p1.rotate(wipe_tower_angle);
+                    p1.translate(wipe_tower_pos);
+                    p2.rotate(wipe_tower_angle);
+                    p2.translate(wipe_tower_pos);
+
                     bbox.merge(p1);
                     coordf_t radius = 0.5 * e.width;
                     bbox.min.x = std::min(bbox.min.x, std::min(p1.x, p2.x) - radius);
diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp
index 36cebeb84..9bf350328 100644
--- a/xs/src/libslic3r/GCode/WipeTower.hpp
+++ b/xs/src/libslic3r/GCode/WipeTower.hpp
@@ -25,18 +25,30 @@ public:
 		bool operator==(const xy &rhs) const { return x == rhs.x && y == rhs.y; }
 		bool operator!=(const xy &rhs) const { return x != rhs.x || y != rhs.y; }
 		
-		// Rotate the point around given point about given angle (in degrees)
-		// shifts the result so that point of rotation is in the middle of the tower
-		xy rotate(const xy& origin, float width, float depth, float angle) const {
+		// Rotate the point around center of the wipe tower about given angle (in degrees)
+		xy rotate(float width, float depth, float angle) const {
 			xy out(0,0);
 			float temp_x = x - width / 2.f;
 			float temp_y = y - depth / 2.f;
 			angle *= M_PI/180.;
-			out.x += (temp_x - origin.x) * cos(angle)  -  (temp_y - origin.y) * sin(angle);
-			out.y += (temp_x - origin.x) * sin(angle)  +  (temp_y - origin.y) * cos(angle);
-			return out + origin;
+			out.x += temp_x * cos(angle)  -  temp_y * sin(angle) + width / 2.f;
+			out.y += temp_x * sin(angle)  +  temp_y * cos(angle) + depth / 2.f;
+
+			return out;
 		}
-		
+        
+        // Rotate the point around origin about given angle in degrees
+        void rotate(float angle) {
+            float temp_x = x * cos(angle)  -  y * sin(angle);
+			y = x * sin(angle)  +  y * cos(angle);
+            x = temp_x;
+		}
+
+        void translate(const xy& vect) {
+            x += vect.x;
+            y += vect.y;
+        }
+
 		float x;
 		float y;
 	};
@@ -104,6 +116,9 @@ public:
 		// This is useful not only for the print time estimation, but also for the control of layer cooling.
 		float  				    elapsed_time;
 
+        // Is this a priming extrusion? (If so, the wipe tower rotation & translation will not be applied later)
+        bool                    priming;
+
 		// Sum the total length of the extrusion.
 		float total_extrusion_length_in_plane() {
 			float e_length = 0.f;
diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
index f466fc4f6..3d0dba07a 100644
--- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
+++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
@@ -5,7 +5,7 @@ TODO LIST
 
 1. cooling moves - DONE
 2. account for perimeter and finish_layer extrusions and subtract it from last wipe - DONE
-3. priming extrusions (last wipe must clear the color)
+3. priming extrusions (last wipe must clear the color) - DONE
 4. Peter's wipe tower - layer's are not exactly square
 5. Peter's wipe tower - variable width for higher levels
 6. Peter's wipe tower - make sure it is not too sparse (apply max_bridge_distance and make last wipe longer)
@@ -17,7 +17,6 @@ TODO LIST
 
 #include <assert.h>
 #include <math.h>
-#include <fstream>
 #include <iostream>
 #include <vector>
 #include <numeric>
@@ -68,8 +67,11 @@ public:
             return *this;
     }
 
-	Writer& 			 set_initial_position(const WipeTower::xy &pos) { 
-		m_start_pos = WipeTower::xy(pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg);
+	Writer& 			 set_initial_position(const WipeTower::xy &pos, float width = 0.f, float depth = 0.f, float internal_angle = 0.f) {
+        m_wipe_tower_width = width;
+        m_wipe_tower_depth = depth;
+        m_internal_angle = internal_angle;
+		m_start_pos = WipeTower::xy(pos,0.f,m_y_shift).rotate(m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle);
 		m_current_pos = pos;
 		return *this;
 	}
@@ -81,9 +83,6 @@ public:
 
 	Writer& 			 set_extrusion_flow(float flow)
 		{ m_extrusion_flow = flow; return *this; }
-		
-	Writer&				 set_rotation(WipeTower::xy& pos, float width, float depth, float angle)
-		{ m_wipe_tower_pos = pos; m_wipe_tower_width = width; m_wipe_tower_depth=depth; m_angle_deg = angle; return (*this); }
 
 	Writer&				 set_y_shift(float shift) {
         m_current_pos.y -= shift-m_y_shift;
@@ -110,7 +109,7 @@ public:
 	float                y()     const { return m_current_pos.y; }
 	const WipeTower::xy& pos()   const { return m_current_pos; }
 	const WipeTower::xy	 start_pos_rotated() const { return m_start_pos; }
-	const WipeTower::xy  pos_rotated() const { return WipeTower::xy(m_current_pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg); }
+	const WipeTower::xy  pos_rotated() const { return WipeTower::xy(m_current_pos, 0.f, m_y_shift).rotate(m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle); }
 	float 				 elapsed_time() const { return m_elapsed_time; }
 
 	// Extrude with an explicitely provided amount of extrusion.
@@ -125,9 +124,9 @@ public:
 		double len = sqrt(dx*dx+dy*dy);
 
 
-		// For rotated wipe tower, transform position to printer coordinates
-		WipeTower::xy rotated_current_pos(WipeTower::xy(m_current_pos,0.f,m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg)); // this is where we are
-		WipeTower::xy rot(WipeTower::xy(x,y+m_y_shift).rotate(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_angle_deg));                               // this is where we want to go
+		// Now do the "internal rotation" with respect to the wipe tower center
+		WipeTower::xy rotated_current_pos(WipeTower::xy(m_current_pos,0.f,m_y_shift).rotate(m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle)); // this is where we are
+		WipeTower::xy rot(WipeTower::xy(x,y+m_y_shift).rotate(m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle));                               // this is where we want to go
 
 		if (! m_preview_suppressed && e > 0.f && len > 0.) {
 			// Width of a squished extrusion, corrected for the roundings of the squished extrusions.
@@ -147,6 +146,7 @@ public:
 		if (std::abs(rot.y - rotated_current_pos.y) > EPSILON)
 			m_gcode += set_format_Y(rot.y);
 
+
 		if (e != 0.f)
 			m_gcode += set_format_E(e);
 
@@ -397,9 +397,8 @@ private:
 	std::string   m_gcode;
 	std::vector<WipeTower::Extrusion> m_extrusions;
 	float         m_elapsed_time;
-	float   	  m_angle_deg = 0.f;
+	float   	  m_internal_angle = 0.f;
 	float		  m_y_shift = 0.f;
-	WipeTower::xy m_wipe_tower_pos;
 	float 		  m_wipe_tower_width = 0.f;
 	float		  m_wipe_tower_depth = 0.f;
 	float		  m_last_fan_speed = 0.f;
@@ -539,6 +538,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
 	m_print_brim = true;
 
 	ToolChangeResult result;
+    result.priming      = true;
 	result.print_z 	  	= this->m_z_pos;
 	result.layer_height = this->m_layer_height;
 	result.gcode   	  	= writer.gcode();
@@ -575,7 +575,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
 	}
 
 	box_coordinates cleaning_box(
-		m_wipe_tower_pos + xy(m_perimeter_width / 2.f, m_perimeter_width / 2.f),
+		xy(m_perimeter_width / 2.f, m_perimeter_width / 2.f),
 		m_wipe_tower_width - m_perimeter_width,
 		(tool != (unsigned int)(-1) ? /*m_layer_info->depth*/wipe_area+m_depth_traversed-0.5*m_perimeter_width
                                     : m_wipe_tower_depth-m_perimeter_width));
@@ -584,7 +584,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
 	writer.set_extrusion_flow(m_extrusion_flow)
 		.set_z(m_z_pos)
 		.set_initial_tool(m_current_tool)
-		.set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle)
 		.set_y_shift(m_y_shift + (tool!=(unsigned int)(-1) && (m_current_shape == SHAPE_REVERSED && !m_peters_wipe_tower) ? m_layer_info->depth - m_layer_info->toolchanges_depth(): 0.f))
 		.append(";--------------------\n"
 				"; CP TOOLCHANGE START\n")
@@ -594,7 +593,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
 		.speed_override(100);
 
 	xy initial_position = cleaning_box.ld + WipeTower::xy(0.f,m_depth_traversed);
-    writer.set_initial_position(initial_position);
+    writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
 
     // Increase the extruder driver current to allow fast ramming.
     writer.set_extruder_trimpot(750);
@@ -616,11 +615,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
     if (last_change_in_layer) {// draw perimeter line
         writer.set_y_shift(m_y_shift);
         if (m_peters_wipe_tower)
-            writer.rectangle(m_wipe_tower_pos,m_layer_info->depth + 3*m_perimeter_width,m_wipe_tower_depth);
+            writer.rectangle(WipeTower::xy(0.f, 0.f),m_layer_info->depth + 3*m_perimeter_width,m_wipe_tower_depth);
         else {
-            writer.rectangle(m_wipe_tower_pos,m_wipe_tower_width, m_layer_info->depth + m_perimeter_width);
+            writer.rectangle(WipeTower::xy(0.f, 0.f),m_wipe_tower_width, m_layer_info->depth + m_perimeter_width);
             if (layer_finished()) { // no finish_layer will be called, we must wipe the nozzle
-                writer.travel(m_wipe_tower_pos.x + (writer.x()> (m_wipe_tower_pos.x + m_wipe_tower_width) / 2.f ? 0.f : m_wipe_tower_width), writer.y());
+                writer.travel(writer.x()> m_wipe_tower_width / 2.f ? 0.f : m_wipe_tower_width, writer.y());
             }
         }
     }
@@ -634,6 +633,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
                   "\n\n");
 
 	ToolChangeResult result;
+    result.priming      = false;
 	result.print_z 	  	= this->m_z_pos;
 	result.layer_height = this->m_layer_height;
 	result.gcode   	  	= writer.gcode();
@@ -647,7 +647,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
 WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, float y_offset)
 {
 	const box_coordinates wipeTower_box(
-		m_wipe_tower_pos,
+		WipeTower::xy(0.f, 0.f),
 		m_wipe_tower_width,
 		m_wipe_tower_depth);
 
@@ -655,12 +655,11 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, flo
 	writer.set_extrusion_flow(m_extrusion_flow * 1.1f)
 		  .set_z(m_z_pos) // Let the writer know the current Z position as a base for Z-hop.
 		  .set_initial_tool(m_current_tool)
-  		  .set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle)
 		  .append(";-------------------------------------\n"
 				  "; CP WIPE TOWER FIRST LAYER BRIM START\n");
 
 	xy initial_position = wipeTower_box.lu - xy(m_perimeter_width * 6.f, 0);
-	writer.set_initial_position(initial_position);
+	writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
 
     writer.extrude_explicit(wipeTower_box.ld - xy(m_perimeter_width * 6.f, 0), // Prime the extruder left of the wipe tower.
         1.5f * m_extrusion_flow * (wipeTower_box.lu.y - wipeTower_box.ld.y), 2400);
@@ -685,6 +684,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, flo
     m_print_brim = false;  // Mark the brim as extruded
 
 	ToolChangeResult result;
+    result.priming      = false;
 	result.print_z 	  	= this->m_z_pos;
 	result.layer_height = this->m_layer_height;
 	result.gcode   	  	= writer.gcode();
@@ -724,7 +724,7 @@ void WipeTowerPrusaMM::toolchange_Unload(
     if (m_layer_info > m_plan.begin() && m_layer_info < m_plan.end() && (m_layer_info-1!=m_plan.begin() || !m_adhesion )) {
 
         // this is y of the center of previous sparse infill border
-        float sparse_beginning_y = m_wipe_tower_pos.y;
+        float sparse_beginning_y = 0.f;
         if (m_current_shape == SHAPE_REVERSED)
             sparse_beginning_y += ((m_layer_info-1)->depth - (m_layer_info-1)->toolchanges_depth())
                                       - ((m_layer_info)->depth-(m_layer_info)->toolchanges_depth()) ;
@@ -742,7 +742,7 @@ void WipeTowerPrusaMM::toolchange_Unload(
         for (const auto& tch : m_layer_info->tool_changes) {  // let's find this toolchange
             if (tch.old_tool == m_current_tool) {
                 sum_of_depths += tch.ramming_depth;
-                float ramming_end_y = m_wipe_tower_pos.y + sum_of_depths;
+                float ramming_end_y = sum_of_depths;
                 ramming_end_y -= (y_step/m_extra_spacing-m_perimeter_width) / 2.f;   // center of final ramming line
 
                 // debugging:
@@ -950,7 +950,7 @@ void WipeTowerPrusaMM::toolchange_Wipe(
     if (m_layer_info != m_plan.end() && m_current_tool != m_layer_info->tool_changes.back().new_tool) {
         m_left_to_right = !m_left_to_right;
         writer.travel(writer.x(), writer.y() - dy)
-        .travel(m_wipe_tower_pos.x + (m_left_to_right ? m_wipe_tower_width : 0.f), writer.y());
+        .travel(m_left_to_right ? m_wipe_tower_width : 0.f, writer.y());
     }
 
 	writer.set_extrusion_flow(m_extrusion_flow); // Reset the extrusion flow.
@@ -969,7 +969,6 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer()
 	writer.set_extrusion_flow(m_extrusion_flow)
 		.set_z(m_z_pos)
 		.set_initial_tool(m_current_tool)
-		.set_rotation(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_tower_depth, m_wipe_tower_rotation_angle)
 		.set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED && !m_peters_wipe_tower ? m_layer_info->toolchanges_depth() : 0.f))
 		.append(";--------------------\n"
 				"; CP EMPTY GRID START\n")
@@ -978,14 +977,12 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer()
 	// Slow down on the 1st layer.
 	float speed_factor = m_is_first_layer ? 0.5f : 1.f;
 	float current_depth = m_layer_info->depth - m_layer_info->toolchanges_depth();
-	box_coordinates fill_box(m_wipe_tower_pos + xy(m_perimeter_width, m_depth_traversed + m_perimeter_width),
+	box_coordinates fill_box(xy(m_perimeter_width, m_depth_traversed + m_perimeter_width),
 							 m_wipe_tower_width - 2 * m_perimeter_width, current_depth-m_perimeter_width);
 
-    if (m_left_to_right) // so there is never a diagonal travel
-        writer.set_initial_position(fill_box.ru);
-    else
-        writer.set_initial_position(fill_box.lu);
 
+    writer.set_initial_position((m_left_to_right ? fill_box.ru : fill_box.lu), // so there is never a diagonal travel
+                                 m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation);
 
 	box_coordinates box = fill_box;
     for (int i=0;i<2;++i) {
@@ -1044,6 +1041,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer()
     m_depth_traversed = m_wipe_tower_depth-m_perimeter_width;
 
 	ToolChangeResult result;
+    result.priming      = false;
 	result.print_z 	  	= this->m_z_pos;
 	result.layer_height = this->m_layer_height;
 	result.gcode   	  	= writer.gcode();
@@ -1165,9 +1163,9 @@ void WipeTowerPrusaMM::generate(std::vector<std::vector<WipeTower::ToolChangeRes
 	{
 		set_layer(layer.z,layer.height,0,layer.z == m_plan.front().z,layer.z == m_plan.back().z);
 		if (m_peters_wipe_tower)
-			m_wipe_tower_rotation_angle += 90.f;
+			m_internal_rotation += 90.f;
 		else
-            m_wipe_tower_rotation_angle += 180.f;
+            m_internal_rotation += 180.f;
 
 		if (!m_peters_wipe_tower && m_layer_info->depth < m_wipe_tower_depth - m_perimeter_width)
 			m_y_shift = (m_wipe_tower_depth-m_layer_info->depth-m_perimeter_width)/2.f;
@@ -1188,7 +1186,7 @@ void WipeTowerPrusaMM::generate(std::vector<std::vector<WipeTower::ToolChangeRes
 					last_toolchange.gcode += buf;
 				}
                 last_toolchange.gcode += finish_layer_toolchange.gcode;
-                last_toolchange.extrusions.insert(last_toolchange.extrusions.end(),finish_layer_toolchange.extrusions.begin(),finish_layer_toolchange.extrusions.end());
+                last_toolchange.extrusions.insert(last_toolchange.extrusions.end(), finish_layer_toolchange.extrusions.begin(), finish_layer_toolchange.extrusions.end());
                 last_toolchange.end_pos = finish_layer_toolchange.end_pos;
             }
             else
diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
index 1ae4616d8..e1529bcf4 100644
--- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
+++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
@@ -102,6 +102,8 @@ public:
 	// Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result"
 	void generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &result);
 
+    float get_depth() const { return m_wipe_tower_depth; }
+
 
 
 	// Switch to a next layer.
@@ -189,6 +191,7 @@ private:
 	float  m_wipe_tower_width; 			// Width of the wipe tower.
 	float  m_wipe_tower_depth 	= 0.f; 	// Depth of the wipe tower
 	float  m_wipe_tower_rotation_angle = 0.f; // Wipe tower rotation angle in degrees (with respect to x axis)
+    float  m_internal_rotation  = 0.f;
 	float  m_y_shift			= 0.f;  // y shift passed to writer
 	float  m_z_pos 				= 0.f;  // Current Z position.
 	float  m_layer_height 		= 0.f; 	// Current layer height.
diff --git a/xs/src/libslic3r/GCodeReader.cpp b/xs/src/libslic3r/GCodeReader.cpp
index 965b7ef8e..79b6ed970 100644
--- a/xs/src/libslic3r/GCodeReader.cpp
+++ b/xs/src/libslic3r/GCodeReader.cpp
@@ -114,6 +114,28 @@ void GCodeReader::parse_file(const std::string &file, callback_t callback)
         this->parse_line(line, callback);
 }
 
+bool GCodeReader::GCodeLine::has(char axis) const
+{
+    const char *c = m_raw.c_str();
+    // Skip the whitespaces.
+    c = skip_whitespaces(c);
+    // Skip the command.
+    c = skip_word(c);
+    // Up to the end of line or comment.
+    while (! is_end_of_gcode_line(*c)) {
+        // Skip whitespaces.
+        c = skip_whitespaces(c);
+        if (is_end_of_gcode_line(*c))
+            break;
+        // Check the name of the axis.
+        if (*c == axis)
+            return true;
+        // Skip the rest of the word.
+        c = skip_word(c);
+    }
+    return false;
+}
+
 bool GCodeReader::GCodeLine::has_value(char axis, float &value) const
 {
     const char *c = m_raw.c_str();
diff --git a/xs/src/libslic3r/GCodeReader.hpp b/xs/src/libslic3r/GCodeReader.hpp
index 102cbd27a..84ed89a7c 100644
--- a/xs/src/libslic3r/GCodeReader.hpp
+++ b/xs/src/libslic3r/GCodeReader.hpp
@@ -27,6 +27,7 @@ public:
 
         bool  has(Axis axis) const { return (m_mask & (1 << int(axis))) != 0; }
         float value(Axis axis) const { return m_axis[axis]; }
+        bool  has(char axis) const;
         bool  has_value(char axis, float &value) const;
         float new_Z(const GCodeReader &reader) const { return this->has(Z) ? this->z() : reader.z(); }
         float new_E(const GCodeReader &reader) const { return this->has(E) ? this->e() : reader.e(); }
diff --git a/xs/src/libslic3r/GCodeSender.cpp b/xs/src/libslic3r/GCodeSender.cpp
index c3530e00f..0988091ce 100644
--- a/xs/src/libslic3r/GCodeSender.cpp
+++ b/xs/src/libslic3r/GCodeSender.cpp
@@ -2,6 +2,7 @@
 #include <iostream>
 #include <istream>
 #include <string>
+#include <thread>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/algorithm/string/trim.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
@@ -568,16 +569,12 @@ GCodeSender::set_DTR(bool on)
 void
 GCodeSender::reset()
 {
-    this->set_DTR(false);
-    boost::this_thread::sleep(boost::posix_time::milliseconds(200));
-    this->set_DTR(true);
-    boost::this_thread::sleep(boost::posix_time::milliseconds(200));
-    this->set_DTR(false);
-    boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
-    {
-        boost::lock_guard<boost::mutex> l(this->queue_mutex);
-        this->can_send = true;
-    }
+    set_DTR(false);
+    std::this_thread::sleep_for(std::chrono::milliseconds(200));
+    set_DTR(true);
+    std::this_thread::sleep_for(std::chrono::milliseconds(200));
+    set_DTR(false);
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
 }
 
 } // namespace Slic3r
diff --git a/xs/src/libslic3r/GCodeTimeEstimator.cpp b/xs/src/libslic3r/GCodeTimeEstimator.cpp
index 5543b5cc9..c4ffb572a 100644
--- a/xs/src/libslic3r/GCodeTimeEstimator.cpp
+++ b/xs/src/libslic3r/GCodeTimeEstimator.cpp
@@ -469,6 +469,40 @@ namespace Slic3r {
         return _state.minimum_travel_feedrate;
     }
 
+    void GCodeTimeEstimator::set_filament_load_times(const std::vector<double> &filament_load_times)
+    {
+        _state.filament_load_times.clear();
+        for (double t : filament_load_times)
+            _state.filament_load_times.push_back(t);
+    }
+
+    void GCodeTimeEstimator::set_filament_unload_times(const std::vector<double> &filament_unload_times)
+    {
+        _state.filament_unload_times.clear();
+        for (double t : filament_unload_times)
+            _state.filament_unload_times.push_back(t);
+    }
+
+    float GCodeTimeEstimator::get_filament_load_time(unsigned int id_extruder)
+    {
+        return
+            (_state.filament_load_times.empty() || id_extruder == _state.extruder_id_unloaded) ? 
+                0 :
+                (_state.filament_load_times.size() <= id_extruder) ?
+                    _state.filament_load_times.front() : 
+                    _state.filament_load_times[id_extruder];
+    }
+
+    float GCodeTimeEstimator::get_filament_unload_time(unsigned int id_extruder)
+    {
+        return
+            (_state.filament_unload_times.empty() || id_extruder == _state.extruder_id_unloaded) ? 
+                0 :
+                (_state.filament_unload_times.size() <= id_extruder) ?
+                    _state.filament_unload_times.front() : 
+                    _state.filament_unload_times[id_extruder];
+    }
+
     void GCodeTimeEstimator::set_extrude_factor_override_percentage(float percentage)
     {
         _state.extrude_factor_override_percentage = percentage;
@@ -535,6 +569,23 @@ namespace Slic3r {
         _state.g1_line_id = 0;
     }
 
+    void GCodeTimeEstimator::set_extruder_id(unsigned int id)
+    {
+        _state.extruder_id = id;
+    }
+
+    unsigned int GCodeTimeEstimator::get_extruder_id() const
+    {
+        return _state.extruder_id;
+    }
+
+    void GCodeTimeEstimator::reset_extruder_id()
+    {
+        // Set the initial extruder ID to unknown. For the multi-material setup it means
+        // that all the filaments are parked in the MMU and no filament is loaded yet.
+        _state.extruder_id = _state.extruder_id_unloaded;
+    }
+
     void GCodeTimeEstimator::add_additional_time(float timeSec)
     {
         PROFILE_FUNC();
@@ -575,6 +626,9 @@ namespace Slic3r {
             set_axis_max_acceleration(axis, DEFAULT_AXIS_MAX_ACCELERATION[a]);
             set_axis_max_jerk(axis, DEFAULT_AXIS_MAX_JERK[a]);
         }
+
+        _state.filament_load_times.clear();
+        _state.filament_unload_times.clear();
     }
 
     void GCodeTimeEstimator::reset()
@@ -613,6 +667,7 @@ namespace Slic3r {
 
         set_additional_time(0.0f);
 
+        reset_extruder_id();
         reset_g1_line_id();
         _g1_line_ids.clear();
 
@@ -666,6 +721,8 @@ namespace Slic3r {
         }
 
         _last_st_synchronized_block_id = _blocks.size() - 1;
+        // The additional time has been consumed (added to the total time), reset it to zero.
+        set_additional_time(0.);
     }
 
     void GCodeTimeEstimator::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line)
@@ -778,8 +835,18 @@ namespace Slic3r {
                             _processM566(line);
                             break;
                         }
+                    case 702: // MK3 MMU2: Process the final filament unload.
+                        {
+                            _processM702(line);
+                            break;
+                        }
                     }
 
+                    break;
+                }
+            case 'T': // Select Tools
+                {
+                    _processT(line);
                     break;
                 }
             }
@@ -1164,11 +1231,25 @@ namespace Slic3r {
     {
         PROFILE_FUNC();
         float value;
-        if (line.has_value('S', value))
+        if (line.has_value('S', value)) {
+            // Legacy acceleration format. This format is used by the legacy Marlin, MK2 or MK3 firmware,
+            // and it is also generated by Slic3r to control acceleration per extrusion type
+            // (there is a separate acceleration settings in Slicer for perimeter, first layer etc).
             set_acceleration(value);
-
-        if (line.has_value('T', value))
-            set_retract_acceleration(value);
+            if (line.has_value('T', value))
+                set_retract_acceleration(value);
+        } else {
+            // New acceleration format, compatible with the upstream Marlin.
+            if (line.has_value('P', value))
+                set_acceleration(value);
+            if (line.has_value('R', value))
+                set_retract_acceleration(value);
+            if (line.has_value('T', value)) {
+                // Interpret the T value as the travel acceleration in the new Marlin format.
+                //FIXME Prusa3D firmware currently does not support travel acceleration value independent from the extruding acceleration value.
+                // set_travel_acceleration(value);
+            }
+        }
     }
 
     void GCodeTimeEstimator::_processM205(const GCodeReader::GCodeLine& line)
@@ -1223,6 +1304,37 @@ namespace Slic3r {
             set_axis_max_jerk(E, line.e() * MMMIN_TO_MMSEC);
     }
 
+    void GCodeTimeEstimator::_processM702(const GCodeReader::GCodeLine& line)
+    {
+        PROFILE_FUNC();
+        if (line.has('C')) {
+            // MK3 MMU2 specific M code:
+            // M702 C is expected to be sent by the custom end G-code when finalizing a print.
+            // The MK3 unit shall unload and park the active filament into the MMU2 unit.
+            add_additional_time(get_filament_unload_time(get_extruder_id()));
+            reset_extruder_id();
+            _simulate_st_synchronize();
+        }
+    }
+
+    void GCodeTimeEstimator::_processT(const GCodeReader::GCodeLine& line)
+    {
+        std::string cmd = line.cmd();
+        if (cmd.length() > 1)
+        {
+            unsigned int id = (unsigned int)::strtol(cmd.substr(1).c_str(), nullptr, 10);
+            if (get_extruder_id() != id)
+            {
+                // Specific to the MK3 MMU2: The initial extruder ID is set to -1 indicating
+                // that the filament is parked in the MMU2 unit and there is nothing to be unloaded yet.
+                add_additional_time(get_filament_unload_time(get_extruder_id()));
+                set_extruder_id(id);
+                add_additional_time(get_filament_load_time(get_extruder_id()));
+                _simulate_st_synchronize();
+            }
+        }
+    }
+
     void GCodeTimeEstimator::_simulate_st_synchronize()
     {
         PROFILE_FUNC();
diff --git a/xs/src/libslic3r/GCodeTimeEstimator.hpp b/xs/src/libslic3r/GCodeTimeEstimator.hpp
index 2dfefda0b..1fa74e304 100644
--- a/xs/src/libslic3r/GCodeTimeEstimator.hpp
+++ b/xs/src/libslic3r/GCodeTimeEstimator.hpp
@@ -79,7 +79,15 @@ namespace Slic3r {
             float minimum_feedrate;             // mm/s
             float minimum_travel_feedrate;      // mm/s
             float extrude_factor_override_percentage;
+            // Additional load / unload times for a filament exchange sequence.
+            std::vector<float> filament_load_times;
+            std::vector<float> filament_unload_times;
             unsigned int g1_line_id;
+            // extruder_id is currently used to correctly calculate filament load / unload times 
+            // into the total print time. This is currently only really used by the MK3 MMU2:
+            // Extruder id (-1) means no filament is loaded yet, all the filaments are parked in the MK3 MMU2 unit.
+            static const unsigned int extruder_id_unloaded = (unsigned int)-1;
+            unsigned int extruder_id;
         };
 
     public:
@@ -281,6 +289,11 @@ namespace Slic3r {
         void set_minimum_travel_feedrate(float feedrate_mm_sec);
         float get_minimum_travel_feedrate() const;
 
+        void set_filament_load_times(const std::vector<double> &filament_load_times);
+        void set_filament_unload_times(const std::vector<double> &filament_unload_times);
+        float get_filament_load_time(unsigned int id_extruder);
+        float get_filament_unload_time(unsigned int id_extruder);
+
         void set_extrude_factor_override_percentage(float percentage);
         float get_extrude_factor_override_percentage() const;
 
@@ -300,6 +313,10 @@ namespace Slic3r {
         void increment_g1_line_id();
         void reset_g1_line_id();
 
+        void set_extruder_id(unsigned int id);
+        unsigned int get_extruder_id() const;
+        void reset_extruder_id();
+
         void add_additional_time(float timeSec);
         void set_additional_time(float timeSec);
         float get_additional_time() const;
@@ -383,6 +400,12 @@ namespace Slic3r {
         // Set allowable instantaneous speed change
         void _processM566(const GCodeReader::GCodeLine& line);
 
+        // Unload the current filament into the MK3 MMU2 unit at the end of print.
+        void _processM702(const GCodeReader::GCodeLine& line);
+
+        // Processes T line (Select Tool)
+        void _processT(const GCodeReader::GCodeLine& line);
+
         // Simulates firmware st_synchronize() call
         void _simulate_st_synchronize();
 
diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp
index d6f1f05c9..bceeea258 100644
--- a/xs/src/libslic3r/Model.cpp
+++ b/xs/src/libslic3r/Model.cpp
@@ -7,11 +7,6 @@
 #include "Format/STL.hpp"
 #include "Format/3mf.hpp"
 
-#include <numeric>
-#include <libnest2d.h>
-#include <ClipperUtils.hpp>
-#include "slic3r/GUI/GUI.hpp"
-
 #include <float.h>
 
 #include <boost/algorithm/string/predicate.hpp>
@@ -304,369 +299,36 @@ static bool _arrange(const Pointfs &sizes, coordf_t dist, const BoundingBoxf* bb
     return result;
 }
 
-namespace arr {
-
-using namespace libnest2d;
-
-std::string toString(const Model& model, bool holes = true) {
-    std::stringstream  ss;
-
-    ss << "{\n";
-
-    for(auto objptr : model.objects) {
-        if(!objptr) continue;
-
-        auto rmesh = objptr->raw_mesh();
-
-        for(auto objinst : objptr->instances) {
-            if(!objinst) continue;
-
-            Slic3r::TriangleMesh tmpmesh = rmesh;
-            tmpmesh.scale(objinst->scaling_factor);
-            objinst->transform_mesh(&tmpmesh);
-            ExPolygons expolys = tmpmesh.horizontal_projection();
-            for(auto& expoly_complex : expolys) {
-
-                auto tmp = expoly_complex.simplify(1.0/SCALING_FACTOR);
-                if(tmp.empty()) continue;
-                auto expoly = tmp.front();
-                expoly.contour.make_clockwise();
-                for(auto& h : expoly.holes) h.make_counter_clockwise();
-
-                ss << "\t{\n";
-                ss << "\t\t{\n";
-
-                for(auto v : expoly.contour.points) ss << "\t\t\t{"
-                                                    << v.x << ", "
-                                                    << v.y << "},\n";
-                {
-                    auto v = expoly.contour.points.front();
-                    ss << "\t\t\t{" << v.x << ", " << v.y << "},\n";
-                }
-                ss << "\t\t},\n";
-
-                // Holes:
-                ss << "\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";
-            }
-        }
-    }
-
-    ss << "}\n";
-
-    return ss.str();
-}
-
-void toSVG(SVG& svg, const Model& model) {
-    for(auto objptr : model.objects) {
-        if(!objptr) continue;
-
-        auto rmesh = objptr->raw_mesh();
-
-        for(auto objinst : objptr->instances) {
-            if(!objinst) continue;
-
-            Slic3r::TriangleMesh tmpmesh = rmesh;
-            tmpmesh.scale(objinst->scaling_factor);
-            objinst->transform_mesh(&tmpmesh);
-            ExPolygons expolys = tmpmesh.horizontal_projection();
-            svg.draw(expolys);
-        }
-    }
-}
-
-// A container which stores a pointer to the 3D object and its projected
-// 2D shape from top view.
-using ShapeData2D =
-    std::vector<std::pair<Slic3r::ModelInstance*, Item>>;
-
-ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
-    ShapeData2D ret;
-
-    auto s = std::accumulate(model.objects.begin(), model.objects.end(), 0,
-                    [](size_t s, ModelObject* o){
-        return s + o->instances.size();
-    });
-
-    ret.reserve(s);
-
-    for(auto objptr : model.objects) {
-        if(objptr) {
-
-            auto rmesh = objptr->raw_mesh();
-
-            for(auto objinst : objptr->instances) {
-                if(objinst) {
-                    Slic3r::TriangleMesh tmpmesh = rmesh;
-                    ClipperLib::PolygonImpl pn;
-
-                    tmpmesh.scale(objinst->scaling_factor);
-
-                    // TODO export the exact 2D projection
-                    auto p = tmpmesh.convex_hull();
-
-                    p.make_clockwise();
-                    p.append(p.first_point());
-                    pn.Contour = Slic3rMultiPoint_to_ClipperPath( p );
-
-                    // Efficient conversion to item.
-                    Item item(std::move(pn));
-
-                    // Invalid geometries would throw exceptions when arranging
-                    if(item.vertexCount() > 3) {
-                        item.rotation(objinst->rotation);
-                        item.translation( {
-                            ClipperLib::cInt(objinst->offset.x/SCALING_FACTOR),
-                            ClipperLib::cInt(objinst->offset.y/SCALING_FACTOR)
-                        });
-                        ret.emplace_back(objinst, item);
-                    }
-                }
-            }
-        }
-    }
-
-    return ret;
-}
-
-/**
- * \brief Arranges the model objects on the screen.
- *
- * The arrangement considers multiple bins (aka. print beds) for placing all
- * the items provided in the model argument. If the items don't fit on one
- * print bed, the remaining will be placed onto newly created print beds.
- * The first_bin_only parameter, if set to true, disables this behaviour and
- * makes sure that only one print bed is filled and the remaining items will be
- * untouched. When set to false, the items which could not fit onto the
- * print bed will be placed next to the print bed so the user should see a
- * pile of items on the print bed and some other piles outside the print
- * area that can be dragged later onto the print bed as a group.
- *
- * \param model The model object with the 3D content.
- * \param dist The minimum distance which is allowed for any pair of items
- * on the print bed  in any direction.
- * \param bb The bounding box of the print bed. It corresponds to the 'bin'
- * for bin packing.
- * \param first_bin_only This parameter controls whether to place the
- * remaining items which do not fit onto the print area next to the print
- * bed or leave them untouched (let the user arrange them by hand or remove
- * them).
- */
-bool arrange(Model &model, coordf_t dist, const Slic3r::BoundingBoxf* bb,
-             bool first_bin_only,
-             std::function<void(unsigned)> progressind)
-{
-    using ArrangeResult = _IndexedPackGroup<PolygonImpl>;
-
-    bool ret = true;
-
-    // Create the arranger config
-    auto min_obj_distance = static_cast<Coord>(dist/SCALING_FACTOR);
-
-    // Get the 2D projected shapes with their 3D model instance pointers
-    auto shapemap = arr::projectModelFromTop(model);
-
-    bool hasbin = bb != nullptr && bb->defined;
-    double area_max = 0;
-
-    // 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, hasbin]
-                  (ShapeData2D::value_type& it)
-    {
-        shapes.push_back(std::ref(it.second));
-    });
-
-    Box bin;
-
-    if(hasbin) {
-        // Scale up the bounding box to clipper scale.
-        BoundingBoxf bbb = *bb;
-        bbb.scale(1.0/SCALING_FACTOR);
-
-        bin = Box({
-                    static_cast<libnest2d::Coord>(bbb.min.x),
-                    static_cast<libnest2d::Coord>(bbb.min.y)
-                },
-                {
-                    static_cast<libnest2d::Coord>(bbb.max.x),
-                    static_cast<libnest2d::Coord>(bbb.max.y)
-                });
-    }
-
-    // Will use the DJD selection heuristic with the BottomLeft placement
-    // strategy
-    using Arranger = Arranger<NfpPlacer, FirstFitSelection>;
-    using PConf = Arranger::PlacementConfig;
-    using SConf = Arranger::SelectionConfig;
-
-    PConf pcfg;     // Placement configuration
-    SConf scfg;     // Selection configuration
-
-    // 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 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
-            double penality)        // Min penality in case of bad arrangement
-    {
-        auto bb = ShapeLike::boundingBox(pile);
-
-        // 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 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;
-    };
-
-    // Create the arranger object
-    Arranger arranger(bin, min_obj_distance, pcfg, scfg);
-
-    // Set the progress indicator for the arranger.
-    arranger.progressIndicator(progressind);
-
-    // Arrange and return the items with their respective indices within the
-    // input sequence.
-    auto result = arranger.arrangeIndexed(shapes.begin(), shapes.end());
-
-    auto applyResult = [&shapemap](ArrangeResult::value_type& group,
-            Coord batch_offset)
-    {
-        for(auto& r : group) {
-            auto idx = r.first;     // get the original item index
-            Item& item = r.second;  // get the item itself
-
-            // Get the model instance from the shapemap using the index
-            ModelInstance *inst_ptr = shapemap[idx].first;
-
-            // Get the tranformation data from the item object and scale it
-            // appropriately
-            auto off = item.translation();
-            Radians rot = item.rotation();
-            Pointf foff(off.X*SCALING_FACTOR + batch_offset,
-                        off.Y*SCALING_FACTOR);
-
-            // write the tranformation data into the model instance
-            inst_ptr->rotation = rot;
-            inst_ptr->offset = foff;
-        }
-    };
-
-    if(first_bin_only) {
-        applyResult(result.front(), 0);
-    } else {
-
-        const auto STRIDE_PADDING = 1.2;
-
-        Coord stride = static_cast<Coord>(STRIDE_PADDING*
-                                          bin.width()*SCALING_FACTOR);
-        Coord batch_offset = 0;
-
-        for(auto& group : result) {
-            applyResult(group, batch_offset);
-
-            // Only the first pack group can be placed onto the print bed. The
-            // other objects which could not fit will be placed next to the
-            // print bed
-            batch_offset += stride;
-        }
-    }
-
-    for(auto objptr : model.objects) objptr->invalidate_bounding_box();
-
-    return ret && result.size() == 1;
-}
-}
-
 /*  arrange objects preserving their instance count
     but altering their instance positions */
-bool Model::arrange_objects(coordf_t dist, const BoundingBoxf* bb,
-                            std::function<void(unsigned)> progressind)
+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);
-    } else {
-        // get the (transformed) size of each instance so that we take
-        // into account their different transformations when packing
-        Pointfs instance_sizes;
-        Pointfs instance_centers;
-        for (const ModelObject *o : this->objects)
-            for (size_t i = 0; i < o->instances.size(); ++ i) {
-                // an accurate snug bounding box around the transformed mesh.
-                BoundingBoxf3 bbox(o->instance_bounding_box(i, true));
-                instance_sizes.push_back(bbox.size());
-                instance_centers.push_back(bbox.center());
-            }
-
-        Pointfs positions;
-        if (! _arrange(instance_sizes, dist, bb, positions))
-            return false;
-
-        size_t idx = 0;
-        for (ModelObject *o : this->objects) {
-            for (ModelInstance *i : o->instances) {
-                i->offset = positions[idx] - instance_centers[idx];
-                ++ idx;
-            }
-            o->invalidate_bounding_box();
+    // get the (transformed) size of each instance so that we take
+    // into account their different transformations when packing
+    Pointfs instance_sizes;
+    Pointfs instance_centers;
+    for (const ModelObject *o : this->objects)
+        for (size_t i = 0; i < o->instances.size(); ++ i) {
+            // an accurate snug bounding box around the transformed mesh.
+            BoundingBoxf3 bbox(o->instance_bounding_box(i, true));
+            instance_sizes.push_back(bbox.size());
+            instance_centers.push_back(bbox.center());
         }
+
+    Pointfs positions;
+    if (! _arrange(instance_sizes, dist, bb, positions))
+        return false;
+
+    size_t idx = 0;
+    for (ModelObject *o : this->objects) {
+        for (ModelInstance *i : o->instances) {
+            i->offset = positions[idx] - instance_centers[idx];
+            ++ idx;
+        }
+        o->invalidate_bounding_box();
     }
 
-    return ret;
+    return true;
 }
 
 // Duplicate the entire model preserving instance relative positions.
@@ -1109,9 +771,23 @@ void ModelObject::scale(const Pointf3 &versor)
 
 void ModelObject::rotate(float angle, const Axis &axis)
 {
+    float min_z = FLT_MAX;
     for (ModelVolume *v : this->volumes)
+    {
         v->mesh.rotate(angle, axis);
-    this->origin_translation = Pointf3(0,0,0);
+        min_z = std::min(min_z, v->mesh.stl.stats.min.z);
+    }
+
+    if (min_z != 0.0f)
+    {
+        // translate the object so that its minimum z lays on the bed
+        for (ModelVolume *v : this->volumes)
+        {
+            v->mesh.translate(0.0f, 0.0f, -min_z);
+        }
+    }
+
+    this->origin_translation = Pointf3(0, 0, 0);
     this->invalidate_bounding_box();
 }
 
diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp
index f5e97fb6a..4c650f0de 100644
--- a/xs/src/libslic3r/Model.hpp
+++ b/xs/src/libslic3r/Model.hpp
@@ -290,8 +290,7 @@ public:
     void center_instances_around_point(const Pointf &point);
     void translate(coordf_t x, coordf_t y, coordf_t z) { for (ModelObject *o : this->objects) o->translate(x, y, z); }
     TriangleMesh mesh() const;
-    bool arrange_objects(coordf_t dist, const BoundingBoxf* bb = NULL,
-                         std::function<void(unsigned)> progressind = [](unsigned){});
+    bool arrange_objects(coordf_t dist, const BoundingBoxf* bb = NULL);
     // Croaks if the duplicated objects do not fit the print bed.
     void duplicate(size_t copies_num, coordf_t dist, const BoundingBoxf* bb = NULL);
     void duplicate_objects(size_t copies_num, coordf_t dist, const BoundingBoxf* bb = NULL);
diff --git a/xs/src/libslic3r/ModelArrange.hpp b/xs/src/libslic3r/ModelArrange.hpp
new file mode 100644
index 000000000..f2d399ac6
--- /dev/null
+++ b/xs/src/libslic3r/ModelArrange.hpp
@@ -0,0 +1,597 @@
+#ifndef MODELARRANGE_HPP
+#define MODELARRANGE_HPP
+
+#include "Model.hpp"
+#include "SVG.hpp"
+#include <libnest2d.h>
+
+#include <numeric>
+#include <ClipperUtils.hpp>
+
+#include <boost/geometry/index/rtree.hpp>
+
+namespace Slic3r {
+namespace arr {
+
+using namespace libnest2d;
+
+std::string toString(const Model& model, bool holes = true) {
+    std::stringstream  ss;
+
+    ss << "{\n";
+
+    for(auto objptr : model.objects) {
+        if(!objptr) continue;
+
+        auto rmesh = objptr->raw_mesh();
+
+        for(auto objinst : objptr->instances) {
+            if(!objinst) continue;
+
+            Slic3r::TriangleMesh tmpmesh = rmesh;
+            tmpmesh.scale(objinst->scaling_factor);
+            objinst->transform_mesh(&tmpmesh);
+            ExPolygons expolys = tmpmesh.horizontal_projection();
+            for(auto& expoly_complex : expolys) {
+
+                auto tmp = expoly_complex.simplify(1.0/SCALING_FACTOR);
+                if(tmp.empty()) continue;
+                auto expoly = tmp.front();
+                expoly.contour.make_clockwise();
+                for(auto& h : expoly.holes) h.make_counter_clockwise();
+
+                ss << "\t{\n";
+                ss << "\t\t{\n";
+
+                for(auto v : expoly.contour.points) ss << "\t\t\t{"
+                                                    << v.x << ", "
+                                                    << v.y << "},\n";
+                {
+                    auto v = expoly.contour.points.front();
+                    ss << "\t\t\t{" << v.x << ", " << v.y << "},\n";
+                }
+                ss << "\t\t},\n";
+
+                // Holes:
+                ss << "\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";
+            }
+        }
+    }
+
+    ss << "}\n";
+
+    return ss.str();
+}
+
+void toSVG(SVG& svg, const Model& model) {
+    for(auto objptr : model.objects) {
+        if(!objptr) continue;
+
+        auto rmesh = objptr->raw_mesh();
+
+        for(auto objinst : objptr->instances) {
+            if(!objinst) continue;
+
+            Slic3r::TriangleMesh tmpmesh = rmesh;
+            tmpmesh.scale(objinst->scaling_factor);
+            objinst->transform_mesh(&tmpmesh);
+            ExPolygons expolys = tmpmesh.horizontal_projection();
+            svg.draw(expolys);
+        }
+    }
+}
+
+namespace bgi = boost::geometry::index;
+
+using SpatElement = std::pair<Box, unsigned>;
+using SpatIndex = bgi::rtree< SpatElement, bgi::rstar<16, 4> >;
+
+std::tuple<double /*score*/, Box /*farthest point from bin center*/>
+objfunc(const PointImpl& bincenter,
+        double /*bin_area*/,
+        ShapeLike::Shapes<PolygonImpl>& pile,   // The currently arranged pile
+        double /*pile_area*/,
+        const Item &item,
+        double norm,            // A norming factor for physical dimensions
+        std::vector<double>& areacache, // pile item areas will be cached
+        // a spatial index to quickly get neighbors of the candidate item
+        SpatIndex& spatindex
+        )
+{
+    using pl = PointLike;
+    using sl = ShapeLike;
+
+    static const double BIG_ITEM_TRESHOLD = 0.2;
+    static const double ROUNDNESS_RATIO = 0.5;
+    static const double DENSITY_RATIO = 1.0 - ROUNDNESS_RATIO;
+
+    // We will treat big items (compared to the print bed) differently
+    auto normarea = [norm](double area) { return std::sqrt(area)/norm; };
+
+    // If a new bin has been created:
+    if(pile.size() < areacache.size()) {
+        areacache.clear();
+        spatindex.clear();
+    }
+
+    // We must fill the caches:
+    int idx = 0;
+    for(auto& p : pile) {
+        if(idx == areacache.size()) {
+            areacache.emplace_back(sl::area(p));
+            if(normarea(areacache[idx]) > BIG_ITEM_TRESHOLD)
+                spatindex.insert({sl::boundingBox(p), idx});
+        }
+
+        idx++;
+    }
+
+    // Candidate item bounding box
+    auto ibb = item.boundingBox();
+
+    // Calculate the full bounding box of the pile with the candidate item
+    pile.emplace_back(item.transformedShape());
+    auto fullbb = ShapeLike::boundingBox(pile);
+    pile.pop_back();
+
+    // The bounding box of the big items (they will accumulate in the center
+    // of the pile
+    Box bigbb;
+    if(spatindex.empty()) bigbb = fullbb;
+    else {
+        auto boostbb = spatindex.bounds();
+        boost::geometry::convert(boostbb, bigbb);
+    }
+
+    // The size indicator of the candidate item. This is not the area,
+    // but almost...
+    double item_normarea = normarea(item.area());
+
+    // Will hold the resulting score
+    double score = 0;
+
+    if(item_normarea > BIG_ITEM_TRESHOLD) {
+        // This branch is for the bigger items..
+        // Here we will use the closest point of the item bounding box to
+        // the already arranged pile. So not the bb center nor the a choosen
+        // corner but whichever is the closest to the center. This will
+        // prevent some unwanted strange arrangements.
+
+        auto minc = ibb.minCorner(); // bottom left corner
+        auto maxc = ibb.maxCorner(); // top right corner
+
+        // top left and bottom right corners
+        auto top_left = PointImpl{getX(minc), getY(maxc)};
+        auto bottom_right = PointImpl{getX(maxc), getY(minc)};
+
+        // Now the distance of the gravity center will be calculated to the
+        // five anchor points and the smallest will be chosen.
+        std::array<double, 5> dists;
+        auto cc = fullbb.center(); // The gravity center
+        dists[0] = pl::distance(minc, cc);
+        dists[1] = pl::distance(maxc, cc);
+        dists[2] = pl::distance(ibb.center(), cc);
+        dists[3] = pl::distance(top_left, cc);
+        dists[4] = pl::distance(bottom_right, cc);
+
+        // The smalles distance from the arranged pile center:
+        auto dist = *(std::min_element(dists.begin(), dists.end())) / norm;
+
+        // Density is the pack density: how big is the arranged pile
+        auto density = std::sqrt(fullbb.width()*fullbb.height()) / norm;
+
+        // Prepare a variable for the alignment score.
+        // This will indicate: how well is the candidate item aligned with
+        // its neighbors. We will check the aligment with all neighbors and
+        // return the score for the best alignment. So it is enough for the
+        // candidate to be aligned with only one item.
+        auto alignment_score = std::numeric_limits<double>::max();
+
+        auto& trsh =  item.transformedShape();
+
+        auto querybb = item.boundingBox();
+
+        // Query the spatial index for the neigbours
+        std::vector<SpatElement> result;
+        spatindex.query(bgi::intersects(querybb), std::back_inserter(result));
+
+        for(auto& e : result) { // now get the score for the best alignment
+            auto idx = e.second;
+            auto& p = pile[idx];
+            auto parea = areacache[idx];
+            auto bb = sl::boundingBox(sl::Shapes<PolygonImpl>{p, trsh});
+            auto bbarea = bb.area();
+            auto ascore = 1.0 - (item.area() + parea)/bbarea;
+
+            if(ascore < alignment_score) alignment_score = ascore;
+        }
+
+        // The final mix of the score is the balance between the distance
+        // from the full pile center, the pack density and the
+        // alignment with the neigbours
+        auto C = 0.33;
+        score = C * dist +  C * density + C * alignment_score;
+
+    } else if( item_normarea < BIG_ITEM_TRESHOLD && spatindex.empty()) {
+        // If there are no big items, only small, we should consider the
+        // density here as well to not get silly results
+        auto bindist = pl::distance(ibb.center(), bincenter) / norm;
+        auto density = std::sqrt(fullbb.width()*fullbb.height()) / norm;
+        score = ROUNDNESS_RATIO * bindist + DENSITY_RATIO * density;
+    } else {
+        // Here there are the small items that should be placed around the
+        // already processed bigger items.
+        // No need to play around with the anchor points, the center will be
+        // just fine for small items
+        score = pl::distance(ibb.center(), bigbb.center()) / norm;
+    }
+
+    return std::make_tuple(score, fullbb);
+}
+
+template<class PConf>
+void fillConfig(PConf& pcfg) {
+
+    // 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 };
+
+    // The accuracy of optimization.
+    // Goes from 0.0 to 1.0 and scales performance as well
+    pcfg.accuracy = 0.6f;
+}
+
+template<class TBin>
+class AutoArranger {};
+
+template<class TBin>
+class _ArrBase {
+protected:
+    using Placer = strategies::_NofitPolyPlacer<PolygonImpl, TBin>;
+    using Selector = FirstFitSelection;
+    using Packer = Arranger<Placer, Selector>;
+    using PConfig = typename Packer::PlacementConfig;
+    using Distance = TCoord<PointImpl>;
+    using Pile = ShapeLike::Shapes<PolygonImpl>;
+
+    Packer pck_;
+    PConfig pconf_; // Placement configuration
+    double bin_area_;
+    std::vector<double> areacache_;
+    SpatIndex rtree_;
+public:
+
+    _ArrBase(const TBin& bin, Distance dist,
+             std::function<void(unsigned)> progressind):
+       pck_(bin, dist), bin_area_(ShapeLike::area<PolygonImpl>(bin))
+    {
+        fillConfig(pconf_);
+        pck_.progressIndicator(progressind);
+    }
+
+    template<class...Args> inline IndexedPackGroup operator()(Args&&...args) {
+        areacache_.clear();
+        return pck_.arrangeIndexed(std::forward<Args>(args)...);
+    }
+};
+
+template<>
+class AutoArranger<Box>: public _ArrBase<Box> {
+public:
+
+    AutoArranger(const Box& bin, Distance dist,
+                 std::function<void(unsigned)> progressind):
+        _ArrBase<Box>(bin, dist, progressind)
+    {
+        pconf_.object_function = [this, bin] (
+                    Pile& pile,
+                    const Item &item,
+                    double pile_area,
+                    double norm,
+                    double /*penality*/) {
+
+            auto result = objfunc(bin.center(), bin_area_, pile,
+                                  pile_area, item, norm, areacache_, rtree_);
+            double score = std::get<0>(result);
+            auto& fullbb = std::get<1>(result);
+
+            auto wdiff = fullbb.width() - bin.width();
+            auto hdiff = fullbb.height() - bin.height();
+            if(wdiff > 0) score += std::pow(wdiff, 2) / norm;
+            if(hdiff > 0) score += std::pow(hdiff, 2) / norm;
+
+            return score;
+        };
+
+        pck_.configure(pconf_);
+    }
+};
+
+template<>
+class AutoArranger<PolygonImpl>: public _ArrBase<PolygonImpl> {
+public:
+    AutoArranger(const PolygonImpl& bin, Distance dist,
+                 std::function<void(unsigned)> progressind):
+        _ArrBase<PolygonImpl>(bin, dist, progressind)
+    {
+        pconf_.object_function = [this, &bin] (
+                    Pile& pile,
+                    const Item &item,
+                    double pile_area,
+                    double norm,
+                    double /*penality*/) {
+
+            auto binbb = ShapeLike::boundingBox(bin);
+            auto result = objfunc(binbb.center(), bin_area_, pile,
+                                  pile_area, item, norm, areacache_, rtree_);
+            double score = std::get<0>(result);
+
+            pile.emplace_back(item.transformedShape());
+            auto chull = ShapeLike::convexHull(pile);
+            pile.pop_back();
+
+            // If it does not fit into the print bed we will beat it 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(!Placer::wouldFit(chull, bin)) score += norm;
+
+            return score;
+        };
+
+        pck_.configure(pconf_);
+    }
+};
+
+template<> // Specialization with no bin
+class AutoArranger<bool>: public _ArrBase<Box> {
+public:
+
+    AutoArranger(Distance dist, std::function<void(unsigned)> progressind):
+        _ArrBase<Box>(Box(0, 0), dist, progressind)
+    {
+        this->pconf_.object_function = [this] (
+                    Pile& pile,
+                    const Item &item,
+                    double pile_area,
+                    double norm,
+                    double /*penality*/) {
+
+            auto result = objfunc({0, 0}, 0, pile, pile_area,
+                                  item, norm, areacache_, rtree_);
+            return std::get<0>(result);
+        };
+
+        this->pck_.configure(pconf_);
+    }
+};
+
+// A container which stores a pointer to the 3D object and its projected
+// 2D shape from top view.
+using ShapeData2D =
+    std::vector<std::pair<Slic3r::ModelInstance*, Item>>;
+
+ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
+    ShapeData2D ret;
+
+    auto s = std::accumulate(model.objects.begin(), model.objects.end(), 0,
+                    [](size_t s, ModelObject* o){
+        return s + o->instances.size();
+    });
+
+    ret.reserve(s);
+
+    for(auto objptr : model.objects) {
+        if(objptr) {
+
+            auto rmesh = objptr->raw_mesh();
+
+            for(auto objinst : objptr->instances) {
+                if(objinst) {
+                    Slic3r::TriangleMesh tmpmesh = rmesh;
+                    ClipperLib::PolygonImpl pn;
+
+                    tmpmesh.scale(objinst->scaling_factor);
+
+                    // TODO export the exact 2D projection
+                    auto p = tmpmesh.convex_hull();
+
+                    p.make_clockwise();
+                    p.append(p.first_point());
+                    pn.Contour = Slic3rMultiPoint_to_ClipperPath( p );
+
+                    // Efficient conversion to item.
+                    Item item(std::move(pn));
+
+                    // Invalid geometries would throw exceptions when arranging
+                    if(item.vertexCount() > 3) {
+                        item.rotation(objinst->rotation);
+                        item.translation( {
+                            ClipperLib::cInt(objinst->offset.x/SCALING_FACTOR),
+                            ClipperLib::cInt(objinst->offset.y/SCALING_FACTOR)
+                        });
+                        ret.emplace_back(objinst, item);
+                    }
+                }
+            }
+        }
+    }
+
+    return ret;
+}
+
+enum BedShapeHint {
+    BOX,
+    CIRCLE,
+    IRREGULAR,
+    WHO_KNOWS
+};
+
+BedShapeHint bedShape(const Slic3r::Polyline& /*bed*/) {
+    // Determine the bed shape by hand
+    return BOX;
+}
+
+void applyResult(
+        IndexedPackGroup::value_type& group,
+        Coord batch_offset,
+        ShapeData2D& shapemap)
+{
+    for(auto& r : group) {
+        auto idx = r.first;     // get the original item index
+        Item& item = r.second;  // get the item itself
+
+        // Get the model instance from the shapemap using the index
+        ModelInstance *inst_ptr = shapemap[idx].first;
+
+        // Get the tranformation data from the item object and scale it
+        // appropriately
+        auto off = item.translation();
+        Radians rot = item.rotation();
+        Pointf foff(off.X*SCALING_FACTOR + batch_offset,
+                    off.Y*SCALING_FACTOR);
+
+        // write the tranformation data into the model instance
+        inst_ptr->rotation = rot;
+        inst_ptr->offset = foff;
+    }
+}
+
+
+/**
+ * \brief Arranges the model objects on the screen.
+ *
+ * The arrangement considers multiple bins (aka. print beds) for placing all
+ * the items provided in the model argument. If the items don't fit on one
+ * print bed, the remaining will be placed onto newly created print beds.
+ * The first_bin_only parameter, if set to true, disables this behaviour and
+ * makes sure that only one print bed is filled and the remaining items will be
+ * untouched. When set to false, the items which could not fit onto the
+ * print bed will be placed next to the print bed so the user should see a
+ * pile of items on the print bed and some other piles outside the print
+ * area that can be dragged later onto the print bed as a group.
+ *
+ * \param model The model object with the 3D content.
+ * \param dist The minimum distance which is allowed for any pair of items
+ * on the print bed  in any direction.
+ * \param bb The bounding box of the print bed. It corresponds to the 'bin'
+ * for bin packing.
+ * \param first_bin_only This parameter controls whether to place the
+ * remaining items which do not fit onto the print area next to the print
+ * bed or leave them untouched (let the user arrange them by hand or remove
+ * them).
+ */
+bool arrange(Model &model, coordf_t min_obj_distance,
+             const Slic3r::Polyline& bed,
+             BedShapeHint bedhint,
+             bool first_bin_only,
+             std::function<void(unsigned)> progressind)
+{
+    using ArrangeResult = _IndexedPackGroup<PolygonImpl>;
+
+    bool ret = true;
+
+    // Get the 2D projected shapes with their 3D model instance pointers
+    auto shapemap = arr::projectModelFromTop(model);
+
+    // 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] (ShapeData2D::value_type& it)
+    {
+        shapes.push_back(std::ref(it.second));
+    });
+
+    IndexedPackGroup result;
+    BoundingBox bbb(bed.points);
+
+    auto binbb = Box({
+                         static_cast<libnest2d::Coord>(bbb.min.x),
+                         static_cast<libnest2d::Coord>(bbb.min.y)
+                     },
+                     {
+                         static_cast<libnest2d::Coord>(bbb.max.x),
+                         static_cast<libnest2d::Coord>(bbb.max.y)
+                     });
+
+    switch(bedhint) {
+    case BOX: {
+
+        // Create the arranger for the box shaped bed
+        AutoArranger<Box> arrange(binbb, min_obj_distance, progressind);
+
+        // Arrange and return the items with their respective indices within the
+        // input sequence.
+        result = arrange(shapes.begin(), shapes.end());
+        break;
+    }
+    case CIRCLE:
+        break;
+    case IRREGULAR:
+    case WHO_KNOWS: {
+        using P = libnest2d::PolygonImpl;
+
+        auto ctour = Slic3rMultiPoint_to_ClipperPath(bed);
+        P irrbed = ShapeLike::create<PolygonImpl>(std::move(ctour));
+
+//        std::cout << ShapeLike::toString(irrbed) << std::endl;
+
+        AutoArranger<P> arrange(irrbed, min_obj_distance, progressind);
+
+        // Arrange and return the items with their respective indices within the
+        // input sequence.
+        result = arrange(shapes.begin(), shapes.end());
+        break;
+    }
+    };
+
+    if(first_bin_only) {
+        applyResult(result.front(), 0, shapemap);
+    } else {
+
+        const auto STRIDE_PADDING = 1.2;
+
+        Coord stride = static_cast<Coord>(STRIDE_PADDING*
+                                          binbb.width()*SCALING_FACTOR);
+        Coord batch_offset = 0;
+
+        for(auto& group : result) {
+            applyResult(group, batch_offset, shapemap);
+
+            // Only the first pack group can be placed onto the print bed. The
+            // other objects which could not fit will be placed next to the
+            // print bed
+            batch_offset += stride;
+        }
+    }
+
+    for(auto objptr : model.objects) objptr->invalidate_bounding_box();
+
+    return ret && result.size() == 1;
+}
+
+}
+}
+#endif // MODELARRANGE_HPP
diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp
index f4e14cc59..332bd9cb7 100644
--- a/xs/src/libslic3r/Print.cpp
+++ b/xs/src/libslic3r/Print.cpp
@@ -132,7 +132,6 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
         "gcode_comments",
         "gcode_flavor",
         "infill_acceleration",
-        "infill_first",
         "layer_gcode",
         "min_fan_speed",
         "max_fan_speed",
@@ -159,6 +158,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
         "retract_restart_extra",
         "retract_restart_extra_toolchange",
         "retract_speed",
+        "single_extruder_multi_material_priming",
         "slowdown_below_layer_time",
         "standby_temperature_delta",
         "start_gcode",
@@ -170,17 +170,16 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
         "use_relative_e_distances",
         "use_volumetric_e",
         "variable_layer_height",
-        "wipe"
+        "wipe",
+        "wipe_tower_x",
+        "wipe_tower_y",
+        "wipe_tower_rotation_angle"
     };
 
     std::vector<PrintStep> steps;
     std::vector<PrintObjectStep> osteps;
     bool invalidated = false;
 
-    // Always invalidate the wipe tower. This is probably necessary because of the wipe_into_infill / wipe_into_objects
-    // features - nearly anything can influence what should (and could) be wiped into.
-    steps.emplace_back(psWipeTower);
-
     for (const t_config_option_key &opt_key : opt_keys) {
         if (steps_ignore.find(opt_key) != steps_ignore.end()) {
             // These options only affect G-code export or they are just notes without influence on the generated G-code,
@@ -208,18 +207,17 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
             || opt_key == "filament_unloading_speed"
             || opt_key == "filament_toolchange_delay"
             || opt_key == "filament_cooling_moves"
+            || opt_key == "filament_minimal_purge_on_wipe_tower"
             || opt_key == "filament_cooling_initial_speed"
             || opt_key == "filament_cooling_final_speed"
             || opt_key == "filament_ramming_parameters"
             || opt_key == "gcode_flavor"
+            || opt_key == "infill_first"
             || opt_key == "single_extruder_multi_material"
             || opt_key == "spiral_vase"
             || opt_key == "temperature"
             || opt_key == "wipe_tower"
-            || opt_key == "wipe_tower_x"
-            || opt_key == "wipe_tower_y"
             || opt_key == "wipe_tower_width"
-            || opt_key == "wipe_tower_rotation_angle"
             || opt_key == "wipe_tower_bridging"
             || opt_key == "wiping_volumes_matrix"
             || opt_key == "parking_pos_retraction"
@@ -1055,6 +1053,8 @@ void Print::_make_wipe_tower()
     if (! this->has_wipe_tower())
         return;
 
+    m_wipe_tower_depth = 0.f;
+
     // Get wiping matrix to get number of extruders and convert vector<double> to vector<float>:
     std::vector<float> wiping_matrix((this->config.wiping_volumes_matrix.values).begin(),(this->config.wiping_volumes_matrix.values).end());
     // Extract purging volumes for each extruder pair:
@@ -1148,12 +1148,19 @@ void Print::_make_wipe_tower()
             wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id,false);
             for (const auto extruder_id : layer_tools.extruders) {
                 if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) {
-                    float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id];    // total volume to wipe after this toolchange
+                    float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id];             // total volume to wipe after this toolchange
+                    // Not all of that can be used for infill purging:
+                    volume_to_wipe -= config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id);
 
                     // try to assign some infills/objects for the wiping:
-                    volume_to_wipe = layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, current_extruder_id, extruder_id, wipe_volumes[current_extruder_id][extruder_id]);
+                    volume_to_wipe = layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, current_extruder_id, extruder_id, volume_to_wipe);
 
-                    wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id, first_layer && extruder_id == m_tool_ordering.all_extruders().back(), volume_to_wipe);
+                    // add back the minimal amount toforce on the wipe tower:
+                    volume_to_wipe += config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id);
+
+                    // request a toolchange at the wipe tower with at least volume_to_wipe purging amount
+                    wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id,
+                                               first_layer && extruder_id == m_tool_ordering.all_extruders().back(), volume_to_wipe);
                     current_extruder_id = extruder_id;
                 }
             }
@@ -1166,7 +1173,8 @@ void Print::_make_wipe_tower()
     // Generate the wipe tower layers.
     m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size());
     wipe_tower.generate(m_wipe_tower_tool_changes);
-    
+    m_wipe_tower_depth = wipe_tower.get_depth();
+
     // Unload the current filament over the purge tower.
     coordf_t layer_height = this->objects.front()->config.layer_height.value;
     if (m_tool_ordering.back().wipe_tower_partitions > 0) {
@@ -1187,10 +1195,6 @@ void Print::_make_wipe_tower()
 		wipe_tower.tool_change((unsigned int)-1, false));
 }
 
-
-
-
-
 std::string Print::output_filename()
 {
     this->placeholder_parser.update_timestamp();
@@ -1244,7 +1248,6 @@ void Print::print_to_png(std::string dirpath) {
         float(this->config.exp_time_first.value));
 }
 
-
 // Returns extruder this eec should be printed with, according to PrintRegion config
 int Print::get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion &region)
 {
@@ -1252,5 +1255,4 @@ int Print::get_extruder(const ExtrusionEntityCollection& fill, const PrintRegion
                                     std::max<int>(region.config.perimeter_extruder.value - 1, 0);
 }
 
-
 }
diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp
index bb25a27fd..664c05a46 100644
--- a/xs/src/libslic3r/Print.hpp
+++ b/xs/src/libslic3r/Print.hpp
@@ -279,6 +279,7 @@ public:
     
     void add_model_object(ModelObject* model_object, int idx = -1);
     bool apply_config(DynamicPrintConfig config);
+    float get_wipe_tower_depth() const { return m_wipe_tower_depth; }
     bool has_infinite_skirt() const;
     bool has_skirt() const;
     // Returns an empty string if valid, otherwise returns an error message.
@@ -334,6 +335,9 @@ private:
     bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
     PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume);
 
+    // Depth of the wipe tower to pass to GLCanvas3D for exact bounding box:
+    float m_wipe_tower_depth = 0.f;
+
     // Has the calculation been canceled?
     tbb::atomic<bool>   m_canceled;
 };
diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp
index 70888bec8..8a0f79cb4 100644
--- a/xs/src/libslic3r/PrintConfig.cpp
+++ b/xs/src/libslic3r/PrintConfig.cpp
@@ -504,19 +504,38 @@ PrintConfigDef::PrintConfigDef()
     def = this->add("filament_cooling_initial_speed", coFloats);
     def->label = L("Speed of the first cooling move");
     def->tooltip = L("Cooling moves are gradually accelerating beginning at this speed. ");
-    def->cli = "filament-cooling-initial-speed=i@";
+    def->cli = "filament-cooling-initial-speed=f@";
     def->sidetext = L("mm/s");
     def->min = 0;
     def->default_value = new ConfigOptionFloats { 2.2f };
 
+    def = this->add("filament_minimal_purge_on_wipe_tower", coFloats);
+    def->label = L("Minimal purge on wipe tower");
+    def->tooltip = L("After a tool change, the exact position of the newly loaded filament inside "
+                     "the nozzle may not be known, and the filament pressure is likely not yet stable. "
+                     "Before purging the print head into an infill or a sacrificial object, Slic3r will always prime "
+                     "this amount of material into the wipe tower to produce successive infill or sacrificial object extrusions reliably.");
+    def->cli = "filament-minimal-purge-on-wipe-tower=f@";
+    def->sidetext = L("mm³");
+    def->min = 0;
+    def->default_value = new ConfigOptionFloats { 5.f };
+
     def = this->add("filament_cooling_final_speed", coFloats);
     def->label = L("Speed of the last cooling move");
     def->tooltip = L("Cooling moves are gradually accelerating towards this speed. ");
-    def->cli = "filament-cooling-final-speed=i@";
+    def->cli = "filament-cooling-final-speed=f@";
     def->sidetext = L("mm/s");
     def->min = 0;
     def->default_value = new ConfigOptionFloats { 3.4f };
 
+    def = this->add("filament_load_time", coFloats);
+    def->label = L("Filament load time");
+    def->tooltip = L("Time for the printer firmware (or the Multi Material Unit 2.0) to load a new filament during a tool change (when executing the T code). This time is added to the total print time by the G-code time estimator.");
+    def->cli = "filament-load-time=i@";
+    def->sidetext = L("s");
+    def->min = 0;
+    def->default_value = new ConfigOptionFloats { 0.0f };
+
     def = this->add("filament_ramming_parameters", coStrings);
     def->label = L("Ramming parameters");
     def->tooltip = L("This string is edited by RammingDialog and contains ramming specific parameters ");
@@ -524,6 +543,14 @@ PrintConfigDef::PrintConfigDef()
     def->default_value = new ConfigOptionStrings { "120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0|"
 	   " 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" };
 
+    def = this->add("filament_unload_time", coFloats);
+    def->label = L("Filament unload time");
+    def->tooltip = L("Time for the printer firmware (or the Multi Material Unit 2.0) to unload a filament during a tool change (when executing the T code). This time is added to the total print time by the G-code time estimator.");
+    def->cli = "filament-unload-time=i@";
+    def->sidetext = L("s");
+    def->min = 0;
+    def->default_value = new ConfigOptionFloats { 0.0f };
+
     def = this->add("filament_diameter", coFloats);
     def->label = L("Diameter");
     def->tooltip = L("Enter your filament diameter here. Good precision is required, so use a caliper "
@@ -892,8 +919,16 @@ PrintConfigDef::PrintConfigDef()
     def->min = 0;
     def->default_value = new ConfigOptionFloat(0.3);
 
+    def = this->add("remaining_times", coBool);
+    def->label = L("Supports remaining times");
+    def->tooltip = L("Emit M73 P[percent printed] R[remaining time in seconds] at 1 minute"
+                     " intervals into the G-code to let the firmware show accurate remaining time."
+                     " As of now only the Prusa i3 MK3 firmware recognizes M73."
+                     " Also the i3 MK3 firmware supports M73 Qxx Sxx for the silent mode.");
+    def->default_value = new ConfigOptionBool(false);
+
 	def = this->add("silent_mode", coBool);
-	def->label = L("Support silent mode");
+	def->label = L("Supports silent mode");
 	def->tooltip = L("Set silent mode for the G-code flavor");
 	def->default_value = new ConfigOptionBool(true);
 
@@ -1623,6 +1658,12 @@ PrintConfigDef::PrintConfigDef()
     def->cli = "single-extruder-multi-material!";
 	def->default_value = new ConfigOptionBool(false);
 
+    def = this->add("single_extruder_multi_material_priming", coBool);
+    def->label = L("Prime all printing extruders");
+    def->tooltip = L("If enabled, all printing extruders will be primed at the front edge of the print bed at the start of the print.");
+    def->cli = "single-extruder-multi-material-priming!";
+    def->default_value = new ConfigOptionBool(true);
+
     def = this->add("support_material", coBool);
     def->label = L("Generate support material");
     def->category = L("Support material");
@@ -1993,8 +2034,8 @@ PrintConfigDef::PrintConfigDef()
 
     def = this->add("wipe_into_infill", coBool);
     def->category = L("Extruders");
-    def->label = L("Purging into infill");
-    def->tooltip = L("Wiping after toolchange will be preferentially done inside infills. "
+    def->label = L("Purge into this object's infill");
+    def->tooltip = L("Purging after toolchange will done inside this object's infills. "
                      "This lowers the amount of waste but may result in longer print time "
                      " due to additional travel moves.");
     def->cli = "wipe-into-infill!";
@@ -2002,8 +2043,8 @@ PrintConfigDef::PrintConfigDef()
 
     def = this->add("wipe_into_objects", coBool);
     def->category = L("Extruders");
-    def->label = L("Purging into objects");
-    def->tooltip = L("Objects will be used to wipe the nozzle after a toolchange to save material "
+    def->label = L("Purge into this object");
+    def->tooltip = L("Object will be used to purge the nozzle after a toolchange to save material "
                      "that would otherwise end up in the wipe tower and decrease print time. "
                      "Colours of the objects will be mixed as a result.");
     def->cli = "wipe-into-objects!";
diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp
index 3045919b7..074a0e611 100644
--- a/xs/src/libslic3r/PrintConfig.hpp
+++ b/xs/src/libslic3r/PrintConfig.hpp
@@ -528,10 +528,13 @@ public:
     ConfigOptionFloats              filament_cost;
     ConfigOptionFloats              filament_max_volumetric_speed;
     ConfigOptionFloats              filament_loading_speed;
+    ConfigOptionFloats              filament_load_time;
     ConfigOptionFloats              filament_unloading_speed;
     ConfigOptionFloats              filament_toolchange_delay;
+    ConfigOptionFloats              filament_unload_time;
     ConfigOptionInts                filament_cooling_moves;
     ConfigOptionFloats              filament_cooling_initial_speed;
+    ConfigOptionFloats              filament_minimal_purge_on_wipe_tower;
     ConfigOptionFloats              filament_cooling_final_speed;
     ConfigOptionStrings             filament_ramming_parameters;
     ConfigOptionBool                gcode_comments;
@@ -553,6 +556,7 @@ public:
     ConfigOptionString              start_gcode;
     ConfigOptionStrings             start_filament_gcode;
     ConfigOptionBool                single_extruder_multi_material;
+    ConfigOptionBool                single_extruder_multi_material_priming;
     ConfigOptionString              toolchange_gcode;
     ConfigOptionFloat               travel_speed;
     ConfigOptionBool                use_firmware_retraction;
@@ -562,6 +566,7 @@ public:
     ConfigOptionFloat               cooling_tube_retraction;
     ConfigOptionFloat               cooling_tube_length;
     ConfigOptionFloat               parking_pos_retraction;
+    ConfigOptionBool                remaining_times;
     ConfigOptionBool                silent_mode;
     ConfigOptionFloat               extra_loading_move;
 
@@ -589,10 +594,13 @@ protected:
         OPT_PTR(filament_cost);
         OPT_PTR(filament_max_volumetric_speed);
         OPT_PTR(filament_loading_speed);
+        OPT_PTR(filament_load_time);
         OPT_PTR(filament_unloading_speed);
+        OPT_PTR(filament_unload_time);
         OPT_PTR(filament_toolchange_delay);
         OPT_PTR(filament_cooling_moves);
         OPT_PTR(filament_cooling_initial_speed);
+        OPT_PTR(filament_minimal_purge_on_wipe_tower);
         OPT_PTR(filament_cooling_final_speed);
         OPT_PTR(filament_ramming_parameters);
         OPT_PTR(gcode_comments);
@@ -612,6 +620,7 @@ protected:
         OPT_PTR(retract_restart_extra_toolchange);
         OPT_PTR(retract_speed);
         OPT_PTR(single_extruder_multi_material);
+        OPT_PTR(single_extruder_multi_material_priming);
         OPT_PTR(start_gcode);
         OPT_PTR(start_filament_gcode);
         OPT_PTR(toolchange_gcode);
@@ -623,6 +632,7 @@ protected:
         OPT_PTR(cooling_tube_retraction);
         OPT_PTR(cooling_tube_length);
         OPT_PTR(parking_pos_retraction);
+        OPT_PTR(remaining_times);
         OPT_PTR(silent_mode);
         OPT_PTR(extra_loading_move);
     }
diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp
index 47495dad8..7150ead59 100644
--- a/xs/src/libslic3r/PrintObject.cpp
+++ b/xs/src/libslic3r/PrintObject.cpp
@@ -75,6 +75,7 @@ bool PrintObject::delete_last_copy()
 
 bool PrintObject::set_copies(const Points &points)
 {
+    bool copies_num_changed = this->_copies.size() != points.size();
     this->_copies = points;
     
     // order copies with a nearest neighbor search and translate them by _copies_shift
@@ -93,7 +94,8 @@ bool PrintObject::set_copies(const Points &points)
     
     bool invalidated = this->_print->invalidate_step(psSkirt);
     invalidated |= this->_print->invalidate_step(psBrim);
-    invalidated |= this->_print->invalidate_step(psWipeTower);
+    if (copies_num_changed)
+        invalidated |= this->_print->invalidate_step(psWipeTower);
     return invalidated;
 }
 
diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h
index 77006cebe..34f61cb12 100644
--- a/xs/src/libslic3r/libslic3r.h
+++ b/xs/src/libslic3r/libslic3r.h
@@ -14,7 +14,7 @@
 #include <boost/thread.hpp>
 
 #define SLIC3R_FORK_NAME "Slic3r Prusa Edition"
-#define SLIC3R_VERSION "1.41.0-alpha2"
+#define SLIC3R_VERSION "1.41.0-beta"
 #define SLIC3R_BUILD "UNKNOWN"
 
 typedef int32_t coord_t;
diff --git a/xs/src/slic3r/AppController.cpp b/xs/src/slic3r/AppController.cpp
index 8c2cbaa16..a0b07dbc7 100644
--- a/xs/src/slic3r/AppController.cpp
+++ b/xs/src/slic3r/AppController.cpp
@@ -8,6 +8,7 @@
 #include <unordered_map>
 
 #include <slic3r/GUI/GUI.hpp>
+#include <ModelArrange.hpp>
 #include <slic3r/GUI/PresetBundle.hpp>
 
 #include <PrintConfig.hpp>
@@ -401,6 +402,8 @@ void AppController::arrange_model()
                supports_asynch()? std::launch::async : std::launch::deferred,
                [this]()
     {
+        using Coord = libnest2d::TCoord<libnest2d::PointImpl>;
+
         unsigned count = 0;
         for(auto obj : model_->objects) count += obj->instances.size();
 
@@ -418,13 +421,25 @@ void AppController::arrange_model()
 
         auto dist = print_ctl()->config().min_object_distance();
 
-        BoundingBoxf bb(print_ctl()->config().bed_shape.values);
+        // Create the arranger config
+        auto min_obj_distance = static_cast<Coord>(dist/SCALING_FACTOR);
+
+        auto& bedpoints = print_ctl()->config().bed_shape.values;
+        Polyline bed; bed.points.reserve(bedpoints.size());
+        for(auto& v : bedpoints)
+            bed.append(Point::new_scale(v.x, v.y));
 
         if(pind) pind->update(0, _(L("Arranging objects...")));
 
         try {
-            model_->arrange_objects(dist, &bb, [pind, count](unsigned rem){
-                if(pind) pind->update(count - rem, _(L("Arranging objects...")));
+            arr::arrange(*model_,
+                         min_obj_distance,
+                         bed,
+                         arr::BOX,
+                         false, // create many piles not just one pile
+                         [pind, count](unsigned rem) {
+                if(pind)
+                    pind->update(count - rem, _(L("Arranging objects...")));
             });
         } catch(std::exception& e) {
             std::cerr << e.what() << std::endl;
diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp
index 62659033a..3f01eb20c 100644
--- a/xs/src/slic3r/GUI/3DScene.cpp
+++ b/xs/src/slic3r/GUI/3DScene.cpp
@@ -210,11 +210,12 @@ GLVolume::GLVolume(float r, float g, float b, float a)
     , selected(false)
     , is_active(true)
     , zoom_to_volumes(true)
-    , outside_printer_detection_enabled(true)
+    , shader_outside_printer_detection_enabled(false)
     , is_outside(false)
     , hover(false)
     , is_modifier(false)
     , is_wipe_tower(false)
+    , is_extrusion_path(false)
     , tverts_range(0, size_t(-1))
     , qverts_range(0, size_t(-1))
 {
@@ -250,7 +251,7 @@ void GLVolume::set_render_color()
         set_render_color(is_outside ? SELECTED_OUTSIDE_COLOR : SELECTED_COLOR, 4);
     else if (hover)
         set_render_color(HOVER_COLOR, 4);
-    else if (is_outside)
+    else if (is_outside && shader_outside_printer_detection_enabled)
         set_render_color(OUTSIDE_COLOR, 4);
     else
         set_render_color(color, 4);
@@ -441,7 +442,7 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
             ::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]);
 
         if (detection_id != -1)
-            ::glUniform1i(detection_id, outside_printer_detection_enabled ? 1 : 0);
+            ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0);
 
         if (worldmatrix_id != -1)
             ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data());
@@ -460,7 +461,7 @@ void GLVolume::render_VBOs(int color_id, int detection_id, int worldmatrix_id) c
         ::glColor4f(render_color[0], render_color[1], render_color[2], render_color[3]);
 
     if (detection_id != -1)
-        ::glUniform1i(detection_id, outside_printer_detection_enabled ? 1 : 0);
+        ::glUniform1i(detection_id, shader_outside_printer_detection_enabled ? 1 : 0);
 
     if (worldmatrix_id != -1)
         ::glUniformMatrix4fv(worldmatrix_id, 1, GL_FALSE, (const GLfloat*)world_matrix().data());
@@ -633,7 +634,7 @@ std::vector<int> GLVolumeCollection::load_object(
                     v.extruder_id = extruder_id;
             }
             v.is_modifier = model_volume->modifier;
-            v.outside_printer_detection_enabled = !model_volume->modifier;
+            v.shader_outside_printer_detection_enabled = !model_volume->modifier;
             v.set_origin(Pointf3(instance->offset.x, instance->offset.y, 0.0));
             v.set_angle_z(instance->rotation);
             v.set_scale_factor(instance->scaling_factor);
@@ -643,20 +644,62 @@ std::vector<int> GLVolumeCollection::load_object(
     return volumes_idx; 
 }
 
-int GLVolumeCollection::load_wipe_tower_preview(
-    int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs)
-{
-    float color[4] = { 0.5f, 0.5f, 0.0f, 0.5f };
-    this->volumes.emplace_back(new GLVolume(color));
-    GLVolume &v = *this->volumes.back();
 
+int GLVolumeCollection::load_wipe_tower_preview(
+    int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width)
+{
+    if (depth < 0.01f)
+        return int(this->volumes.size() - 1);
     if (height == 0.0f)
         height = 0.1f;
-
-    auto mesh = make_cube(width, depth, height);
-    mesh.translate(-width / 2.f, -depth / 2.f, 0.f);
     Point origin_of_rotation(0.f, 0.f);
-    mesh.rotate(rotation_angle,&origin_of_rotation);
+    TriangleMesh mesh;
+    float color[4] = { 0.5f, 0.5f, 0.0f, 1.f };
+
+    // In case we don't know precise dimensions of the wipe tower yet, we'll draw the box with different color with one side jagged:
+    if (size_unknown) {
+        color[0] = 0.9f;
+        color[1] = 0.6f;
+
+        depth = std::max(depth, 10.f); // Too narrow tower would interfere with the teeth. The estimate is not precise anyway.
+        float min_width = 30.f;
+        // We'll now create the box with jagged edge. y-coordinates of the pre-generated model are shifted so that the front
+        // edge has y=0 and centerline of the back edge has y=depth:
+        Pointf3s points;
+        std::vector<Point3> facets;
+        float out_points_idx[][3] = {{0, -depth, 0}, {0, 0, 0}, {38.453, 0, 0}, {61.547, 0, 0}, {100, 0, 0}, {100, -depth, 0}, {55.7735, -10, 0}, {44.2265, 10, 0},
+                                     {38.453, 0, 1}, {0, 0, 1}, {0, -depth, 1}, {100, -depth, 1}, {100, 0, 1}, {61.547, 0, 1}, {55.7735, -10, 1}, {44.2265, 10, 1}};
+        int out_facets_idx[][3] = {{0, 1, 2}, {3, 4, 5}, {6, 5, 0}, {3, 5, 6}, {6, 2, 7}, {6, 0, 2}, {8, 9, 10}, {11, 12, 13}, {10, 11, 14}, {14, 11, 13}, {15, 8, 14},
+                                   {8, 10, 14}, {3, 12, 4}, {3, 13, 12}, {6, 13, 3}, {6, 14, 13}, {7, 14, 6}, {7, 15, 14}, {2, 15, 7}, {2, 8, 15}, {1, 8, 2}, {1, 9, 8},
+                                   {0, 9, 1}, {0, 10, 9}, {5, 10, 0}, {5, 11, 10}, {4, 11, 5}, {4, 12, 11}};
+        for (int i=0;i<16;++i)
+            points.push_back(Pointf3(out_points_idx[i][0] / (100.f/min_width), out_points_idx[i][1] + depth, out_points_idx[i][2]));
+        for (int i=0;i<28;++i)
+            facets.push_back(Point3(out_facets_idx[i][0], out_facets_idx[i][1], out_facets_idx[i][2]));
+        TriangleMesh tooth_mesh(points, facets);
+
+        // We have the mesh ready. It has one tooth and width of min_width. We will now append several of these together until we are close to
+        // the required width of the block. Than we can scale it precisely.
+        size_t n = std::max(1, int(width/min_width)); // How many shall be merged?
+        for (size_t i=0;i<n;++i) {
+            mesh.merge(tooth_mesh);
+            tooth_mesh.translate(min_width, 0.f, 0.f);
+        }
+
+        mesh.scale(Pointf3(width/(n*min_width), 1.f, height)); // Scaling to proper width
+    }
+    else
+        mesh = make_cube(width, depth, height);
+
+    // We'll make another mesh to show the brim (fixed layer height):
+    TriangleMesh brim_mesh = make_cube(width+2.f*brim_width, depth+2.f*brim_width, 0.2f);
+    brim_mesh.translate(-brim_width, -brim_width, 0.f);
+    mesh.merge(brim_mesh);
+
+    mesh.rotate(rotation_angle, &origin_of_rotation); // rotates the box according to the config rotation setting
+
+    this->volumes.emplace_back(new GLVolume(color));
+    GLVolume &v = *this->volumes.back();
 
     if (use_VBOs)
         v.indexed_vertex_array.load_mesh_full_shading(mesh);
@@ -672,6 +715,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
     v.select_group_id = obj_idx * 1000000;
     v.drag_group_id = obj_idx * 1000;
     v.is_wipe_tower = true;
+    v.shader_outside_printer_detection_enabled = ! size_unknown;
     return int(this->volumes.size() - 1);
 }
 
@@ -1786,6 +1830,11 @@ void _3DScene::enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable)
     s_canvas_mgr.enable_force_zoom_to_bed(canvas, enable);
 }
 
+void _3DScene::enable_dynamic_background(wxGLCanvas* canvas, bool enable)
+{
+    s_canvas_mgr.enable_dynamic_background(canvas, enable);
+}
+
 void _3DScene::allow_multisample(wxGLCanvas* canvas, bool allow)
 {
     s_canvas_mgr.allow_multisample(canvas, allow);
@@ -1968,26 +2017,16 @@ void _3DScene::reload_scene(wxGLCanvas* canvas, bool force)
     s_canvas_mgr.reload_scene(canvas, force);
 }
 
-void _3DScene::load_print_toolpaths(wxGLCanvas* canvas)
-{
-    s_canvas_mgr.load_print_toolpaths(canvas);
-}
-
-void _3DScene::load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& str_tool_colors)
-{
-    s_canvas_mgr.load_print_object_toolpaths(canvas, print_object, str_tool_colors);
-}
-
-void _3DScene::load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
-{
-    s_canvas_mgr.load_wipe_tower_toolpaths(canvas, str_tool_colors);
-}
-
 void _3DScene::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
 {
     s_canvas_mgr.load_gcode_preview(canvas, preview_data, str_tool_colors);
 }
 
+void _3DScene::load_preview(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
+{
+    s_canvas_mgr.load_preview(canvas, str_tool_colors);
+}
+
 void _3DScene::reset_legend_texture()
 {
     s_canvas_mgr.reset_legend_texture();
diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp
index 5409b9588..a552b32a7 100644
--- a/xs/src/slic3r/GUI/3DScene.hpp
+++ b/xs/src/slic3r/GUI/3DScene.hpp
@@ -289,8 +289,8 @@ public:
     bool                is_active;
     // Whether or not to use this volume when applying zoom_to_volumes()
     bool                zoom_to_volumes;
-    // Wheter or not this volume is enabled for outside print volume detection.
-    bool                outside_printer_detection_enabled;
+    // Wheter or not this volume is enabled for outside print volume detection in shader.
+    bool                shader_outside_printer_detection_enabled;
     // Wheter or not this volume is outside print volume.
     bool                is_outside;
     // Boolean: Is mouse over this object?
@@ -299,6 +299,8 @@ public:
     bool                is_modifier;
     // Wheter or not this volume has been generated from the wipe tower
     bool                is_wipe_tower;
+    // Wheter or not this volume has been generated from an extrusion path
+    bool                is_extrusion_path;
 
     // Interleaved triangles & normals with indexed triangles & quads.
     GLIndexedVertexArray        indexed_vertex_array;
@@ -399,7 +401,7 @@ public:
         bool                     use_VBOs);
 
     int load_wipe_tower_preview(
-        int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs);
+        int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width);
 
     // Render the volumes by OpenGL.
     void render_VBOs() const;
@@ -497,6 +499,7 @@ public:
     static void enable_gizmos(wxGLCanvas* canvas, bool enable);
     static void enable_shader(wxGLCanvas* canvas, bool enable);
     static void enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable);
+    static void enable_dynamic_background(wxGLCanvas* canvas, bool enable);
     static void allow_multisample(wxGLCanvas* canvas, bool allow);
 
     static void zoom_to_bed(wxGLCanvas* canvas);
@@ -536,10 +539,8 @@ public:
 
     static void reload_scene(wxGLCanvas* canvas, bool force);
 
-    static void load_print_toolpaths(wxGLCanvas* canvas);
-    static void load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& str_tool_colors);
-    static void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
     static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
+    static void load_preview(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
 
     static void reset_legend_texture();
 
diff --git a/xs/src/slic3r/GUI/BedShapeDialog.cpp b/xs/src/slic3r/GUI/BedShapeDialog.cpp
index 3dd60ef88..d52535589 100644
--- a/xs/src/slic3r/GUI/BedShapeDialog.cpp
+++ b/xs/src/slic3r/GUI/BedShapeDialog.cpp
@@ -9,6 +9,8 @@
 #include "Model.hpp"
 #include "boost/nowide/iostream.hpp"
 
+#include <algorithm>
+
 namespace Slic3r {
 namespace GUI {
 
@@ -146,21 +148,18 @@ void BedShapePanel::set_shape(ConfigOptionPoints* points)
 		if (lines[0].parallel_to(lines[2]) && lines[1].parallel_to(lines[3])) {
 			// okay, it's a rectangle
 			// find origin
-			// the || 0 hack prevents "-0" which might confuse the user
-			int x_min, x_max, y_min, y_max;
-			x_max = x_min = points->values[0].x;
+            coordf_t x_min, x_max, y_min, y_max;
+            x_max = x_min = points->values[0].x;
 			y_max = y_min = points->values[0].y;
-			for (auto pt : points->values){
-				if (x_min > pt.x) x_min = pt.x;
-				if (x_max < pt.x) x_max = pt.x;
-				if (y_min > pt.y) y_min = pt.y;
-				if (y_max < pt.y) y_max = pt.y;
-			}
-			if (x_min < 0) x_min = 0;
-			if (x_max < 0) x_max = 0;
-			if (y_min < 0) y_min = 0;
-			if (y_max < 0) y_max = 0;
-			auto origin = new ConfigOptionPoints{ Pointf(-x_min, -y_min) };
+			for (auto pt : points->values)
+            {
+                x_min = std::min(x_min, pt.x);
+                x_max = std::max(x_max, pt.x);
+                y_min = std::min(y_min, pt.y);
+                y_max = std::max(y_max, pt.y);
+            }
+
+            auto origin = new ConfigOptionPoints{ Pointf(-x_min, -y_min) };
 
 			m_shape_options_book->SetSelection(SHAPE_RECTANGULAR);
 			auto optgroup = m_optgroups[SHAPE_RECTANGULAR];
diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp
index 36a1c396f..85fa790a5 100644
--- a/xs/src/slic3r/GUI/Field.cpp
+++ b/xs/src/slic3r/GUI/Field.cpp
@@ -95,9 +95,10 @@ namespace Slic3r { namespace GUI {
 		wxString tooltip_text("");
 		wxString tooltip = _(m_opt.tooltip);
 		if (tooltip.length() > 0)
-			tooltip_text = tooltip + "(" + _(L("default")) + ": " +
-							(boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") + 
-							default_string + ")";
+            tooltip_text = tooltip + "\n" + _(L("default value")) + "\t: " +
+            (boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") + default_string +
+            (boost::iends_with(m_opt_id, "_gcode") ? "" : "\n") + 
+            _(L("parameter name")) + "\t: " + m_opt_id;
 
 		return tooltip_text;
 	}
diff --git a/xs/src/slic3r/GUI/FirmwareDialog.cpp b/xs/src/slic3r/GUI/FirmwareDialog.cpp
index d74743055..77e70c49b 100644
--- a/xs/src/slic3r/GUI/FirmwareDialog.cpp
+++ b/xs/src/slic3r/GUI/FirmwareDialog.cpp
@@ -1,11 +1,24 @@
-#include "FirmwareDialog.hpp"
-
 #include <numeric>
 #include <algorithm>
+#include <thread>
+#include <condition_variable>
+#include <stdexcept>
 #include <boost/format.hpp>
+#include <boost/asio.hpp>
 #include <boost/filesystem/path.hpp>
 #include <boost/filesystem/fstream.hpp>
 #include <boost/log/trivial.hpp>
+#include <boost/optional.hpp>
+
+#include "libslic3r/Utils.hpp"
+#include "avrdude/avrdude-slic3r.hpp"
+#include "GUI.hpp"
+#include "MsgDialog.hpp"
+#include "../Utils/HexFile.hpp"
+#include "../Utils/Serial.hpp"
+
+// wx includes need to come after asio because of the WinSock.h problem
+#include "FirmwareDialog.hpp"
 
 #include <wx/app.h>
 #include <wx/event.h>
@@ -21,17 +34,30 @@
 #include <wx/gauge.h>
 #include <wx/collpane.h>
 #include <wx/msgdlg.h>
+#include <wx/filefn.h>
 
-#include "libslic3r/Utils.hpp"
-#include "avrdude/avrdude-slic3r.hpp"
-#include "GUI.hpp"
-#include "../Utils/Serial.hpp"
 
 namespace fs = boost::filesystem;
+namespace asio = boost::asio;
+using boost::system::error_code;
+using boost::optional;
 
 
 namespace Slic3r {
 
+using Utils::HexFile;
+using Utils::SerialPortInfo;
+using Utils::Serial;
+
+
+// USB IDs used to perform device lookup
+enum {
+	USB_VID_PRUSA    = 0x2c99,
+	USB_PID_MK2      = 1,
+	USB_PID_MK3      = 2,
+	USB_PID_MMU_BOOT = 3,
+	USB_PID_MMU_APP  = 4,
+};
 
 // This enum discriminates the kind of information in EVT_AVRDUDE,
 // it's stored in the ExtraLong field of wxCommandEvent.
@@ -39,12 +65,16 @@ enum AvrdudeEvent
 {
 	AE_MESSAGE,
 	AE_PROGRESS,
+	AE_STATUS,
 	AE_EXIT,
 };
 
 wxDECLARE_EVENT(EVT_AVRDUDE, wxCommandEvent);
 wxDEFINE_EVENT(EVT_AVRDUDE, wxCommandEvent);
 
+wxDECLARE_EVENT(EVT_ASYNC_DIALOG, wxCommandEvent);
+wxDEFINE_EVENT(EVT_ASYNC_DIALOG, wxCommandEvent);
+
 
 // Private
 
@@ -55,13 +85,14 @@ struct FirmwareDialog::priv
 		AC_NONE,
 		AC_SUCCESS,
 		AC_FAILURE,
-		AC_CANCEL,
+		AC_USER_CANCELLED,
 	};
 
 	FirmwareDialog *q;      // PIMPL back pointer ("Q-Pointer")
 
+	// GUI elements
 	wxComboBox *port_picker;
-	std::vector<Utils::SerialPortInfo> ports;
+	wxStaticText *port_autodetect;
 	wxFilePickerCtrl *hex_picker;
 	wxStaticText *txt_status;
 	wxGauge *progressbar;
@@ -72,33 +103,67 @@ struct FirmwareDialog::priv
 	wxButton *btn_flash;
 	wxString btn_flash_label_ready;
 	wxString btn_flash_label_flashing;
+	wxString label_status_flashing;
 
 	wxTimer timer_pulse;
 
+	// Async modal dialog during flashing
+	std::mutex mutex;
+	int modal_response;
+	std::condition_variable response_cv;
+
+	// Data
+	std::vector<SerialPortInfo> ports;
+	optional<SerialPortInfo> port;
+	HexFile hex_file;
+
 	// This is a shared pointer holding the background AvrDude task
 	// also serves as a status indication (it is set _iff_ the background task is running, otherwise it is reset).
 	AvrDude::Ptr avrdude;
 	std::string avrdude_config;
 	unsigned progress_tasks_done;
-	bool cancelled;
+	unsigned progress_tasks_bar;
+	bool user_cancelled;
+	const bool extra_verbose;   // For debugging
 
 	priv(FirmwareDialog *q) :
 		q(q),
 		btn_flash_label_ready(_(L("Flash!"))),
 		btn_flash_label_flashing(_(L("Cancel"))),
+		label_status_flashing(_(L("Flashing in progress. Please do not disconnect the printer!"))),
 		timer_pulse(q),
 		avrdude_config((fs::path(::Slic3r::resources_dir()) / "avrdude" / "avrdude.conf").string()),
 		progress_tasks_done(0),
-		cancelled(false)
+		progress_tasks_bar(0),
+		user_cancelled(false),
+		extra_verbose(false)
 	{}
 
 	void find_serial_ports();
-	void flashing_start(bool flashing_l10n);
+	void fit_no_shrink();
+	void set_txt_status(const wxString &label);
+	void flashing_start(unsigned tasks);
 	void flashing_done(AvrDudeComplete complete);
-	size_t hex_lang_offset(const wxString &path);
+	void enable_port_picker(bool enable);
+	void load_hex_file(const wxString &path);
+	void queue_status(wxString message);
+	void queue_error(const wxString &message);
+
+	bool ask_model_id_mismatch(const std::string &printer_model);
+	bool check_model_id();
+	void wait_for_mmu_bootloader(unsigned retries);
+	void mmu_reboot(const SerialPortInfo &port);
+	void lookup_port_mmu();
+	void prepare_common();
+	void prepare_mk2();
+	void prepare_mk3();
+	void prepare_mm_control();
 	void perform_upload();
-	void cancel();
+
+	void user_cancel();
 	void on_avrdude(const wxCommandEvent &evt);
+	void on_async_dialog(const wxCommandEvent &evt);
+	void ensure_joined();
 };
 
 void FirmwareDialog::priv::find_serial_ports()
@@ -108,7 +173,7 @@ void FirmwareDialog::priv::find_serial_ports()
 		this->ports = new_ports;
 		port_picker->Clear();
 		for (const auto &port : this->ports)
-			port_picker->Append(port.friendly_name);
+			port_picker->Append(wxString::FromUTF8(port.friendly_name.data()));
 		if (ports.size() > 0) {
 			int idx = port_picker->GetValue().IsEmpty() ? 0 : -1;
 			for (int i = 0; i < (int)this->ports.size(); ++ i)
@@ -122,20 +187,43 @@ void FirmwareDialog::priv::find_serial_ports()
 	}
 }
 
-void FirmwareDialog::priv::flashing_start(bool flashing_l10n)
+void FirmwareDialog::priv::fit_no_shrink()
 {
+	// Ensure content fits into window and window is not shrinked
+	const auto old_size = q->GetSize();
+	q->Layout();
+	q->Fit();
+	const auto new_size = q->GetSize();
+	const auto new_width = std::max(old_size.GetWidth(), new_size.GetWidth());
+	const auto new_height = std::max(old_size.GetHeight(), new_size.GetHeight());
+	q->SetSize(new_width, new_height);
+}
+
+void FirmwareDialog::priv::set_txt_status(const wxString &label)
+{
+	const auto width = txt_status->GetSize().GetWidth();
+	txt_status->SetLabel(label);
+	txt_status->Wrap(width);
+
+	fit_no_shrink();
+}
+
+void FirmwareDialog::priv::flashing_start(unsigned tasks)
+{
+	modal_response = wxID_NONE;
 	txt_stdout->Clear();
-	txt_status->SetLabel(_(L("Flashing in progress. Please do not disconnect the printer!")));
+	set_txt_status(label_status_flashing);
 	txt_status->SetForegroundColour(GUI::get_label_clr_modified());
 	port_picker->Disable();
 	btn_rescan->Disable();
 	hex_picker->Disable();
 	btn_close->Disable();
 	btn_flash->SetLabel(btn_flash_label_flashing);
-	progressbar->SetRange(flashing_l10n ? 500 : 200);   // See progress callback below
+	progressbar->SetRange(200 * tasks);   // See progress callback below
 	progressbar->SetValue(0);
 	progress_tasks_done = 0;
-	cancelled = false;
+	progress_tasks_bar = 0;
+	user_cancelled = false;
 	timer_pulse.Start(50);
 }
 
@@ -152,69 +240,191 @@ void FirmwareDialog::priv::flashing_done(AvrDudeComplete complete)
 	progressbar->SetValue(progressbar->GetRange());
 
 	switch (complete) {
-	case AC_SUCCESS: txt_status->SetLabel(_(L("Flashing succeeded!"))); break;
-	case AC_FAILURE: txt_status->SetLabel(_(L("Flashing failed. Please see the avrdude log below."))); break;
-	case AC_CANCEL: txt_status->SetLabel(_(L("Flashing cancelled."))); break;
+	case AC_SUCCESS: set_txt_status(_(L("Flashing succeeded!"))); break;
+	case AC_FAILURE: set_txt_status(_(L("Flashing failed. Please see the avrdude log below."))); break;
+	case AC_USER_CANCELLED: set_txt_status(_(L("Flashing cancelled."))); break;
+	default: break;
 	}
 }
 
-size_t FirmwareDialog::priv::hex_lang_offset(const wxString &path)
+void FirmwareDialog::priv::enable_port_picker(bool enable)
 {
-	fs::ifstream file(fs::path(path.wx_str()));
-	if (! file.good()) {
-		return 0;
-	}
-
-	static const char *hex_terminator = ":00000001FF\r";
-	size_t res = 0;
-	std::string line;
-	while (getline(file, line, '\n').good()) {
-		// Account for LF vs CRLF
-		if (!line.empty() && line.back() != '\r') {
-			line.push_back('\r');
-		}
-
-		if (line == hex_terminator) {
-			if (res == 0) {
-				// This is the first terminator seen, save the position
-				res = file.tellg();
-			} else {
-				// We've found another terminator, return the offset just after the first one
-				// which is the start of the second 'section'.
-				return res;
-			}
-		}
-	}
-
-	return 0;
+	port_picker->Show(enable);
+	btn_rescan->Show(enable);
+	port_autodetect->Show(! enable);
+	q->Layout();
+	fit_no_shrink();
 }
 
-void FirmwareDialog::priv::perform_upload()
+void FirmwareDialog::priv::load_hex_file(const wxString &path)
 {
-	auto filename = hex_picker->GetPath();
-	std::string port = port_picker->GetValue().ToStdString();
-	int  selection = port_picker->GetSelection();
-	if (selection != -1) {
-		// Verify whether the combo box list selection equals to the combo box edit value.
-		if (this->ports[selection].friendly_name == port)
-			port = this->ports[selection].port;
+	hex_file = HexFile(path.wx_str());
+	enable_port_picker(hex_file.device != HexFile::DEV_MM_CONTROL);
+}
+
+void FirmwareDialog::priv::queue_status(wxString message)
+{
+	auto evt = new wxCommandEvent(EVT_AVRDUDE, this->q->GetId());
+	evt->SetExtraLong(AE_STATUS);
+	evt->SetString(std::move(message));
+	wxQueueEvent(this->q, evt);
+}
+
+void FirmwareDialog::priv::queue_error(const wxString &message)
+{
+	auto evt = new wxCommandEvent(EVT_AVRDUDE, this->q->GetId());
+	evt->SetExtraLong(AE_STATUS);
+	evt->SetString(wxString::Format(_(L("Flashing failed: %s")), message));
+
+	wxQueueEvent(this->q, evt);	avrdude->cancel();
+}
+
+bool FirmwareDialog::priv::ask_model_id_mismatch(const std::string &printer_model)
+{
+	// model_id in the hex file doesn't match what the printer repoted.
+	// Ask the user if it should be flashed anyway.
+
+	std::unique_lock<std::mutex> lock(mutex);
+
+	auto evt = new wxCommandEvent(EVT_ASYNC_DIALOG, this->q->GetId());
+	evt->SetString(wxString::Format(_(L(
+		"This firmware hex file does not match the printer model.\n"
+		"The hex file is intended for: %s\n"
+		"Printer reported: %s\n\n"
+		"Do you want to continue and flash this hex file anyway?\n"
+		"Please only continue if you are sure this is the right thing to do.")),
+		hex_file.model_id, printer_model
+	));
+	wxQueueEvent(this->q, evt);
+
+	response_cv.wait(lock, [this]() { return this->modal_response != wxID_NONE; });
+
+	if (modal_response == wxID_YES) { 
+		return true;
+	} else {
+		user_cancel();
+		return false;
 	}
-	if (filename.IsEmpty() || port.empty()) { return; }
+}
 
-	const bool extra_verbose = false;   // For debugging
-	const auto lang_offset = hex_lang_offset(filename);
-	const auto filename_utf8 = filename.utf8_str();
+bool FirmwareDialog::priv::check_model_id()
+{
+	// XXX: The implementation in Serial doesn't currently work reliably enough to be used.
+	// Therefore, regretably, so far the check cannot be used and we just return true here.
+	// TODO: Rewrite Serial using more platform-native code.
+	return true;
+	
+	// if (hex_file.model_id.empty()) {
+	// 	// No data to check against, assume it's ok
+	// 	return true;
+	// }
 
-	flashing_start(lang_offset > 0);
+	// asio::io_service io;
+	// Serial serial(io, port->port, 115200);
+	// serial.printer_setup();
 
-	// It is ok here to use the q-pointer to the FirmwareDialog
-	// because the dialog ensures it doesn't exit before the background thread is done.
-	auto q = this->q;
+	// enum {
+	// 	TIMEOUT = 2000,
+	// 	RETREIES = 5,
+	// };
 
-	// Init the avrdude object
-	AvrDude avrdude(avrdude_config);
+	// if (! serial.printer_ready_wait(RETREIES, TIMEOUT)) {
+	// 	queue_error(wxString::Format(_(L("Could not connect to the printer at %s")), port->port));
+	// 	return false;
+	// }
 
-	// Build argument list(s)
+	// std::string line;
+	// error_code ec;
+	// serial.printer_write_line("PRUSA Rev");
+	// while (serial.read_line(TIMEOUT, line, ec)) {
+	// 	if (ec) {
+	// 		queue_error(wxString::Format(_(L("Could not connect to the printer at %s")), port->port));
+	// 		return false;
+	// 	}
+
+	// 	if (line == "ok") { continue; }
+
+	// 	if (line == hex_file.model_id) {
+	// 		return true;
+	// 	} else {
+	// 		return ask_model_id_mismatch(line);
+	// 	}
+
+	// 	line.clear();
+	// }
+
+	// return false;
+}
+
+void FirmwareDialog::priv::wait_for_mmu_bootloader(unsigned retries)
+{
+	enum {
+		SLEEP_MS = 500,
+	};
+
+	for (unsigned i = 0; i < retries && !user_cancelled; i++) {
+		std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_MS));
+
+		auto ports = Utils::scan_serial_ports_extended();
+		ports.erase(std::remove_if(ports.begin(), ports.end(), [=](const SerialPortInfo &port ) {
+			return port.id_vendor != USB_VID_PRUSA && port.id_product != USB_PID_MMU_BOOT;
+		}), ports.end());
+
+		if (ports.size() == 1) {
+			port = ports[0];
+			return;
+		} else if (ports.size() > 1) {
+			BOOST_LOG_TRIVIAL(error) << "Several VID/PID 0x2c99/3 devices found";
+			queue_error(_(L("Multiple Original Prusa i3 MMU 2.0 devices found. Please only connect one at a time for flashing.")));
+			return;
+		}
+	}
+}
+
+void FirmwareDialog::priv::mmu_reboot(const SerialPortInfo &port)
+{
+	asio::io_service io;
+	Serial serial(io, port.port, 1200);
+	std::this_thread::sleep_for(std::chrono::milliseconds(50));
+}
+
+void FirmwareDialog::priv::lookup_port_mmu()
+{
+	BOOST_LOG_TRIVIAL(info) << "Flashing MMU 2.0, looking for VID/PID 0x2c99/3 or 0x2c99/4 ...";
+
+	auto ports = Utils::scan_serial_ports_extended();
+	ports.erase(std::remove_if(ports.begin(), ports.end(), [=](const SerialPortInfo &port ) {
+		return port.id_vendor != USB_VID_PRUSA &&
+			port.id_product != USB_PID_MMU_BOOT &&
+			port.id_product != USB_PID_MMU_APP;
+	}), ports.end());
+
+	if (ports.size() == 0) {
+		BOOST_LOG_TRIVIAL(info) << "MMU 2.0 device not found, asking the user to press Reset and waiting for the device to show up ...";
+
+		queue_status(_(L(
+			"The Multi Material Control device was not found.\n"
+			"If the device is connected, please press the Reset button next to the USB connector ..."
+		)));
+
+		wait_for_mmu_bootloader(30);
+	} else if (ports.size() > 1) {
+		BOOST_LOG_TRIVIAL(error) << "Several VID/PID 0x2c99/3 devices found";
+		queue_error(_(L("Multiple Original Prusa i3 MMU 2.0 devices found. Please only connect one at a time for flashing.")));
+	} else {
+		if (ports[0].id_product == USB_PID_MMU_APP) {
+			// The device needs to be rebooted into the bootloader mode
+			BOOST_LOG_TRIVIAL(info) << boost::format("Found VID/PID 0x2c99/4 at `%1%`, rebooting the device ...") % ports[0].port;
+			mmu_reboot(ports[0]);
+			wait_for_mmu_bootloader(10);
+		} else {
+			port = ports[0];
+		}
+	}
+}
+
+void FirmwareDialog::priv::prepare_common()
+{
 	std::vector<std::string> args {{
 		extra_verbose ? "-vvvvv" : "-v",
 		"-p", "atmega2560",
@@ -222,11 +432,10 @@ void FirmwareDialog::priv::perform_upload()
 		// The Prusa's avrdude is patched to never send semicolons inside the data packets, as the USB to serial chip
 		// is flashed with a buggy firmware.
 		"-c", "wiring",
-		"-P", port,
-		"-b", "115200",   // TODO: Allow other rates? Ditto below.
+		"-P", port->port,
+		"-b", "115200",   // TODO: Allow other rates? Ditto elsewhere.
 		"-D",
-		// XXX: Safe mode?
-		"-U", (boost::format("flash:w:0:%1%:i") % filename_utf8.data()).str(),
+		"-U", (boost::format("flash:w:0:%1%:i") % hex_file.path.string()).str(),
 	}};
 
 	BOOST_LOG_TRIVIAL(info) << "Invoking avrdude, arguments: "
@@ -234,33 +443,134 @@ void FirmwareDialog::priv::perform_upload()
 			return a + ' ' + b;
 		});
 
-	avrdude.push_args(std::move(args));
-	
-	if (lang_offset > 0) {
-		// The hex file also contains another section with l10n data to be flashed into the external flash on MK3 (Einsy)
-		// This is done via another avrdude invocation, here we build arg list for that:
-		std::vector<std::string> args_l10n {{
-			extra_verbose ? "-vvvvv" : "-v",
-			"-p", "atmega2560",
-			// Using the "Arduino" mode to program Einsy's external flash with languages, using the STK500 protocol (not the STK500v2).
-			// The Prusa's avrdude is patched again to never send semicolons inside the data packets.
-			"-c", "arduino",
-			"-P", port,
-			"-b", "115200",
-			"-D",
-			"-u", // disable safe mode
-			"-U", (boost::format("flash:w:%1%:%2%:i") % lang_offset % filename_utf8.data()).str(),
-		}};
+	avrdude->push_args(std::move(args));
+}
 
-		BOOST_LOG_TRIVIAL(info) << "Invoking avrdude for external flash flashing, arguments: "
-			<< std::accumulate(std::next(args_l10n.begin()), args_l10n.end(), args_l10n[0], [](std::string a, const std::string &b) {
-				return a + ' ' + b;
-			});
+void FirmwareDialog::priv::prepare_mk2()
+{
+	if (! port) { return; }
 
-		avrdude.push_args(std::move(args_l10n));
+	if (! check_model_id()) {
+		avrdude->cancel();
+		return;
 	}
-	
+
+	prepare_common();
+}
+
+void FirmwareDialog::priv::prepare_mk3()
+{
+	if (! port) { return; }
+
+	if (! check_model_id()) {
+		avrdude->cancel();
+		return;
+	}
+
+	prepare_common();
+
+	// The hex file also contains another section with l10n data to be flashed into the external flash on MK3 (Einsy)
+	// This is done via another avrdude invocation, here we build arg list for that:
+	std::vector<std::string> args {{
+		extra_verbose ? "-vvvvv" : "-v",
+		"-p", "atmega2560",
+		// Using the "Arduino" mode to program Einsy's external flash with languages, using the STK500 protocol (not the STK500v2).
+		// The Prusa's avrdude is patched again to never send semicolons inside the data packets.
+		"-c", "arduino",
+		"-P", port->port,
+		"-b", "115200",
+		"-D",
+		"-u", // disable safe mode
+		"-U", (boost::format("flash:w:1:%1%:i") % hex_file.path.string()).str(),
+	}};
+
+	BOOST_LOG_TRIVIAL(info) << "Invoking avrdude for external flash flashing, arguments: "
+		<< std::accumulate(std::next(args.begin()), args.end(), args[0], [](std::string a, const std::string &b) {
+			return a + ' ' + b;
+		});
+
+	avrdude->push_args(std::move(args));
+}
+
+void FirmwareDialog::priv::prepare_mm_control()
+{
+	port = boost::none;
+	lookup_port_mmu();
+	if (! port) {
+		queue_error(_(L("The device could not have been found")));
+		return;
+	}
+
+	BOOST_LOG_TRIVIAL(info) << boost::format("Found VID/PID 0x2c99/3 at `%1%`, flashing ...") % port->port;
+	queue_status(label_status_flashing);
+
+	std::vector<std::string> args {{
+		extra_verbose ? "-vvvvv" : "-v",
+		"-p", "atmega32u4",
+		"-c", "avr109",
+		"-P", port->port,
+		"-b", "57600",
+		"-D",
+		"-U", (boost::format("flash:w:0:%1%:i") % hex_file.path.string()).str(),
+	}};
+
+	BOOST_LOG_TRIVIAL(info) << "Invoking avrdude, arguments: "
+		<< std::accumulate(std::next(args.begin()), args.end(), args[0], [](std::string a, const std::string &b) {
+			return a + ' ' + b;
+		});
+
+	avrdude->push_args(std::move(args));
+}
+
+
+void FirmwareDialog::priv::perform_upload()
+{
+	auto filename = hex_picker->GetPath();
+	if (filename.IsEmpty()) { return; }
+
+	load_hex_file(filename);  // Might already be loaded, but we want to make sure it's fresh
+
+	int selection = port_picker->GetSelection();
+	if (selection != wxNOT_FOUND) {
+		port = this->ports[selection];
+
+		// Verify whether the combo box list selection equals to the combo box edit value.
+		if (wxString::FromUTF8(port->friendly_name.data()) != port_picker->GetValue()) {
+			return;
+		}
+	}
+
+	const bool extra_verbose = false;   // For debugging
+
+	flashing_start(hex_file.device == HexFile::DEV_MK3 ? 2 : 1);
+
+	// Init the avrdude object
+	AvrDude avrdude(avrdude_config);
+
+	// It is ok here to use the q-pointer to the FirmwareDialog
+	// because the dialog ensures it doesn't exit before the background thread is done.
+	auto q = this->q;
+
 	this->avrdude = avrdude
+		.on_run([this]() {
+			try {
+				switch (this->hex_file.device) {
+				case HexFile::DEV_MK3:
+					this->prepare_mk3();
+					break;
+
+				case HexFile::DEV_MM_CONTROL:
+					this->prepare_mm_control();
+					break;
+
+				default:
+					this->prepare_mk2();
+					break;
+				}
+			} catch (const std::exception &ex) {
+				queue_error(wxString::Format(_(L("Error accessing port at %s: %s")), port->port, ex.what()));
+			}
+		})
 		.on_message(std::move([q, extra_verbose](const char *msg, unsigned /* size */) {
 			if (extra_verbose) {
 				BOOST_LOG_TRIVIAL(debug) << "avrdude: " << msg;
@@ -278,20 +588,19 @@ void FirmwareDialog::priv::perform_upload()
 			evt->SetInt(progress);
 			wxQueueEvent(q, evt);
 		}))
-		.on_complete(std::move([q](int status, size_t /* args_id */) {
-			auto evt = new wxCommandEvent(EVT_AVRDUDE, q->GetId());
+		.on_complete(std::move([this]() {
+			auto evt = new wxCommandEvent(EVT_AVRDUDE, this->q->GetId());
 			evt->SetExtraLong(AE_EXIT);
-			evt->SetInt(status);
-			wxQueueEvent(q, evt);
+			evt->SetInt(this->avrdude->exit_code());
+			wxQueueEvent(this->q, evt);
 		}))
 		.run();
 }
 
-void FirmwareDialog::priv::cancel()
+void FirmwareDialog::priv::user_cancel()
 {
 	if (avrdude) {
-		cancelled = true;
-		txt_status->SetLabel(_(L("Cancelling...")));
+		user_cancelled = true;
 		avrdude->cancel();
 	}
 }
@@ -313,12 +622,15 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt)
 		// and then display overall progress during the latter tasks.
 
 		if (progress_tasks_done > 0) {
-			progressbar->SetValue(progress_tasks_done - 100 + evt.GetInt());
+			progressbar->SetValue(progress_tasks_bar + evt.GetInt());
 		}
 
 		if (evt.GetInt() == 100) {
 			timer_pulse.Stop();
-			progress_tasks_done += 100;
+			if (progress_tasks_done % 3 != 0) {
+				progress_tasks_bar += 100;
+			}
+			progress_tasks_done++;
 		}
 
 		break;
@@ -326,13 +638,17 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt)
 	case AE_EXIT:
 		BOOST_LOG_TRIVIAL(info) << "avrdude exit code: " << evt.GetInt();
 
-		complete_kind = cancelled ? AC_CANCEL : (evt.GetInt() == 0 ? AC_SUCCESS : AC_FAILURE);
+		// Figure out the exit state
+		if (user_cancelled) { complete_kind = AC_USER_CANCELLED; }
+		else if (avrdude->cancelled()) { complete_kind = AC_NONE; } // Ie. cancelled programatically
+		else { complete_kind = evt.GetInt() == 0 ? AC_SUCCESS : AC_FAILURE; }
+
 		flashing_done(complete_kind);
+		ensure_joined();
+		break;
 
-		// Make sure the background thread is collected and the AvrDude object reset
-		if (avrdude) { avrdude->join(); }
-		avrdude.reset();
-
+	case AE_STATUS:
+		set_txt_status(evt.GetString());
 		break;
 
 	default:
@@ -340,6 +656,23 @@ void FirmwareDialog::priv::on_avrdude(const wxCommandEvent &evt)
 	}
 }
 
+void FirmwareDialog::priv::on_async_dialog(const wxCommandEvent &evt)
+{
+	wxMessageDialog dlg(this->q, evt.GetString(), wxMessageBoxCaptionStr, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
+	{
+		std::lock_guard<std::mutex> lock(mutex);
+		modal_response = dlg.ShowModal();
+	}
+	response_cv.notify_all();
+}
+
+void FirmwareDialog::priv::ensure_joined()
+{
+	// Make sure the background thread is collected and the AvrDude object reset
+	if (avrdude) { avrdude->join(); }
+	avrdude.reset();
+}
+
 
 // Public
 
@@ -360,44 +693,50 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
 	wxFont mono_font(wxFontInfo().Family(wxFONTFAMILY_TELETYPE));
 	mono_font.MakeSmaller();
 
+	// Create GUI components and layout
+
 	auto *panel = new wxPanel(this);
 	wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL);
 	panel->SetSizer(vsizer);
 
+	auto *label_hex_picker = new wxStaticText(panel, wxID_ANY, _(L("Firmware image:")));
+	p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY);
+
 	auto *label_port_picker = new wxStaticText(panel, wxID_ANY, _(L("Serial port:")));
 	p->port_picker = new wxComboBox(panel, wxID_ANY);
+	p->port_autodetect = new wxStaticText(panel, wxID_ANY, _(L("Autodetected")));
 	p->btn_rescan = new wxButton(panel, wxID_ANY, _(L("Rescan")));
 	auto *port_sizer = new wxBoxSizer(wxHORIZONTAL);
 	port_sizer->Add(p->port_picker, 1, wxEXPAND | wxRIGHT, SPACING);
 	port_sizer->Add(p->btn_rescan, 0);
+	port_sizer->Add(p->port_autodetect, 1, wxEXPAND);
+	p->enable_port_picker(true);
 
-	auto *label_hex_picker = new wxStaticText(panel, wxID_ANY, _(L("Firmware image:")));
-	p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY);
+	auto *label_progress = new wxStaticText(panel, wxID_ANY, _(L("Progress:")));
+	p->progressbar = new wxGauge(panel, wxID_ANY, 1, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL | wxGA_SMOOTH);
 
 	auto *label_status = new wxStaticText(panel, wxID_ANY, _(L("Status:")));
 	p->txt_status = new wxStaticText(panel, wxID_ANY, _(L("Ready")));
 	p->txt_status->SetFont(status_font);
 
-	auto *label_progress = new wxStaticText(panel, wxID_ANY, _(L("Progress:")));
-	p->progressbar = new wxGauge(panel, wxID_ANY, 1, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL | wxGA_SMOOTH);
-
 	auto *grid = new wxFlexGridSizer(2, SPACING, SPACING);
 	grid->AddGrowableCol(1);
-	grid->Add(label_port_picker, 0, wxALIGN_CENTER_VERTICAL);
-	grid->Add(port_sizer, 0, wxEXPAND);
 
 	grid->Add(label_hex_picker, 0, wxALIGN_CENTER_VERTICAL);
 	grid->Add(p->hex_picker, 0, wxEXPAND);
 
-	grid->Add(label_status, 0, wxALIGN_CENTER_VERTICAL);
-	grid->Add(p->txt_status, 0, wxEXPAND);
+	grid->Add(label_port_picker, 0, wxALIGN_CENTER_VERTICAL);
+	grid->Add(port_sizer, 0, wxEXPAND);
 
 	grid->Add(label_progress, 0, wxALIGN_CENTER_VERTICAL);
 	grid->Add(p->progressbar, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL);
 
+	grid->Add(label_status, 0, wxALIGN_CENTER_VERTICAL);
+	grid->Add(p->txt_status, 0, wxEXPAND);
+
 	vsizer->Add(grid, 0, wxEXPAND | wxTOP | wxBOTTOM, SPACING);
 
-	p->spoiler = new wxCollapsiblePane(panel, wxID_ANY, _(L("Advanced: avrdude output log")));
+	p->spoiler = new wxCollapsiblePane(panel, wxID_ANY, _(L("Advanced: avrdude output log")), wxDefaultPosition, wxDefaultSize, wxCP_DEFAULT_STYLE | wxCP_NO_TLW_RESIZE);
 	auto *spoiler_pane = p->spoiler->GetPane();
 	auto *spoiler_sizer = new wxBoxSizer(wxVERTICAL);
 	p->txt_stdout = new wxTextCtrl(spoiler_pane, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY);
@@ -410,6 +749,7 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
 
 	p->btn_close = new wxButton(panel, wxID_CLOSE);
 	p->btn_flash = new wxButton(panel, wxID_ANY, p->btn_flash_label_ready);
+	p->btn_flash->Disable();
 	auto *bsizer = new wxBoxSizer(wxHORIZONTAL);
 	bsizer->Add(p->btn_close);
 	bsizer->AddStretchSpacer();
@@ -424,16 +764,26 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
 	SetSize(std::max(size.GetWidth(), static_cast<int>(MIN_WIDTH)), std::max(size.GetHeight(), static_cast<int>(MIN_HEIGHT)));
 	Layout();
 
+	// Bind events
+
+	p->hex_picker->Bind(wxEVT_FILEPICKER_CHANGED, [this](wxFileDirPickerEvent& evt) {
+		if (wxFileExists(evt.GetPath())) {
+			this->p->load_hex_file(evt.GetPath());
+			this->p->btn_flash->Enable();
+		}
+	});
+
 	p->spoiler->Bind(wxEVT_COLLAPSIBLEPANE_CHANGED, [this](wxCollapsiblePaneEvent &evt) {
-		// Dialog size gets screwed up by wxCollapsiblePane, we need to fix it here
 		if (evt.GetCollapsed()) {
 			this->SetMinSize(wxSize(MIN_WIDTH, MIN_HEIGHT));
+			const auto new_height = this->GetSize().GetHeight() - this->p->txt_stdout->GetSize().GetHeight();
+			this->SetSize(this->GetSize().GetWidth(), new_height);
 		} else {
 			this->SetMinSize(wxSize(MIN_WIDTH, MIN_HEIGHT_EXPANDED));
 		}
 
-		this->Fit();
 		this->Layout();
+		this->p->fit_no_shrink();
 	});
 
 	p->btn_close->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { this->Close(); });
@@ -447,7 +797,8 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
 				_(L("Confirmation")),
 				wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
 			if (dlg.ShowModal() == wxID_YES) {
-				this->p->cancel();
+				this->p->set_txt_status(_(L("Cancelling...")));
+				this->p->user_cancel();
 			}
 		} else {
 			// Start a flashing task
@@ -458,6 +809,7 @@ FirmwareDialog::FirmwareDialog(wxWindow *parent) :
 	Bind(wxEVT_TIMER, [this](wxTimerEvent &evt) { this->p->progressbar->Pulse(); });
 
 	Bind(EVT_AVRDUDE, [this](wxCommandEvent &evt) { this->p->on_avrdude(evt); });
+	Bind(EVT_ASYNC_DIALOG, [this](wxCommandEvent &evt) { this->p->on_async_dialog(evt); });
 
 	Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent &evt) {
 		if (this->p->avrdude) {
diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp
index 722f1c112..ab4095e6f 100644
--- a/xs/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp
@@ -51,6 +51,9 @@ static const float UNIT_MATRIX[] = { 1.0f, 0.0f, 0.0f, 0.0f,
                                      0.0f, 0.0f, 1.0f, 0.0f,
                                      0.0f, 0.0f, 0.0f, 1.0f };
 
+static const float DEFAULT_BG_COLOR[3] = { 10.0f / 255.0f, 98.0f / 255.0f, 144.0f / 255.0f };
+static const float ERROR_BG_COLOR[3] = { 144.0f / 255.0f, 49.0f / 255.0f, 10.0f / 255.0f };
+
 namespace Slic3r {
 namespace GUI {
 
@@ -302,10 +305,14 @@ const Pointfs& GLCanvas3D::Bed::get_shape() const
     return m_shape;
 }
 
-void GLCanvas3D::Bed::set_shape(const Pointfs& shape)
+bool GLCanvas3D::Bed::set_shape(const Pointfs& shape)
 {
+    EType new_type = _detect_type();
+    if (m_shape == shape && m_type == new_type)
+        // No change, no need to update the UI.
+        return false;
     m_shape = shape;
-    m_type = _detect_type();
+    m_type = new_type;
 
     _calc_bounding_box();
 
@@ -321,6 +328,8 @@ void GLCanvas3D::Bed::set_shape(const Pointfs& shape)
     _calc_gridlines(poly, bed_bbox);
 
     m_polygon = offset_ex(poly.contour, (float)bed_bbox.radius() * 1.7f, jtRound, scale_(0.5))[0].contour;
+    // Let the calee to update the UI.
+    return true;
 }
 
 const BoundingBoxf3& GLCanvas3D::Bed::get_bounding_box() const
@@ -1703,6 +1712,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas)
     , m_picking_enabled(false)
     , m_moving_enabled(false)
     , m_shader_enabled(false)
+    , m_dynamic_background_enabled(false)
     , m_multisample_allowed(false)
     , m_color_by("volume")
     , m_select_by("object")
@@ -1828,7 +1838,6 @@ unsigned int GLCanvas3D::get_volumes_count() const
 
 void GLCanvas3D::reset_volumes()
 {
-
     if (!m_volumes.empty())
     {
         // ensures this canvas is current
@@ -1839,6 +1848,9 @@ void GLCanvas3D::reset_volumes()
         m_volumes.clear();
         m_dirty = true;
     }
+
+    enable_warning_texture(false);
+    _reset_warning_texture();
 }
 
 void GLCanvas3D::deselect_volumes()
@@ -1935,12 +1947,21 @@ void GLCanvas3D::set_model(Model* model)
 
 void GLCanvas3D::set_bed_shape(const Pointfs& shape)
 {
-    m_bed.set_shape(shape);
+    bool new_shape = m_bed.set_shape(shape);
 
     // Set the origin and size for painting of the coordinate system axes.
     m_axes.origin = Pointf3(0.0, 0.0, (coordf_t)GROUND_Z);
     set_axes_length(0.3f * (float)m_bed.get_bounding_box().max_size());
 
+    if (new_shape)
+    {
+        // forces the selection of the proper camera target
+        if (m_volumes.volumes.empty())
+            zoom_to_bed();
+        else
+            zoom_to_volumes();
+    }
+
     m_dirty = true;
 }
 
@@ -2065,6 +2086,11 @@ void GLCanvas3D::enable_force_zoom_to_bed(bool enable)
     m_force_zoom_to_bed_enabled = enable;
 }
 
+void GLCanvas3D::enable_dynamic_background(bool enable)
+{
+    m_dynamic_background_enabled = enable;
+}
+
 void GLCanvas3D::allow_multisample(bool allow)
 {
     m_multisample_allowed = allow;
@@ -2292,7 +2318,12 @@ void GLCanvas3D::reload_scene(bool force)
             float w = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_width"))->value;
             float a = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_rotation_angle"))->value;
 
-            m_volumes.load_wipe_tower_preview(1000, x, y, w, 15.0f * (float)(extruders_count - 1), (float)height, a, m_use_VBOs && m_initialized);
+            float depth = m_print->get_wipe_tower_depth();
+            if (!m_print->state.is_done(psWipeTower))
+                depth = (900.f/w) * (float)(extruders_count - 1) ;
+
+            m_volumes.load_wipe_tower_preview(1000, x, y, w, depth, (float)height, a, m_use_VBOs && m_initialized, !m_print->state.is_done(psWipeTower),
+                                              m_print->config.nozzle_diameter.values[0] * 1.25f * 4.5f);
         }
     }
 
@@ -2326,372 +2357,6 @@ void GLCanvas3D::reload_scene(bool force)
     }
 }
 
-void GLCanvas3D::load_print_toolpaths()
-{
-    // ensures this canvas is current
-    if (!set_current())
-        return;
-
-    if (m_print == nullptr)
-        return;
-
-    if (!m_print->state.is_done(psSkirt) || !m_print->state.is_done(psBrim))
-        return;
-
-    if (!m_print->has_skirt() && (m_print->config.brim_width.value == 0))
-        return;
-
-    const float color[] = { 0.5f, 1.0f, 0.5f, 1.0f }; // greenish
-
-    // number of skirt layers
-    size_t total_layer_count = 0;
-    for (const PrintObject* print_object : m_print->objects)
-    {
-        total_layer_count = std::max(total_layer_count, print_object->total_layer_count());
-    }
-    size_t skirt_height = m_print->has_infinite_skirt() ? total_layer_count : std::min<size_t>(m_print->config.skirt_height.value, total_layer_count);
-    if ((skirt_height == 0) && (m_print->config.brim_width.value > 0))
-        skirt_height = 1;
-
-    // get first skirt_height layers (maybe this should be moved to a PrintObject method?)
-    const PrintObject* object0 = m_print->objects.front();
-    std::vector<float> print_zs;
-    print_zs.reserve(skirt_height * 2);
-    for (size_t i = 0; i < std::min(skirt_height, object0->layers.size()); ++i)
-    {
-        print_zs.push_back(float(object0->layers[i]->print_z));
-    }
-    //FIXME why there are support layers?
-    for (size_t i = 0; i < std::min(skirt_height, object0->support_layers.size()); ++i)
-    {
-        print_zs.push_back(float(object0->support_layers[i]->print_z));
-    }
-    sort_remove_duplicates(print_zs);
-    if (print_zs.size() > skirt_height)
-        print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
-
-    m_volumes.volumes.emplace_back(new GLVolume(color));
-    GLVolume& volume = *m_volumes.volumes.back();
-    for (size_t i = 0; i < skirt_height; ++i) {
-        volume.print_zs.push_back(print_zs[i]);
-        volume.offsets.push_back(volume.indexed_vertex_array.quad_indices.size());
-        volume.offsets.push_back(volume.indexed_vertex_array.triangle_indices.size());
-        if (i == 0)
-            _3DScene::extrusionentity_to_verts(m_print->brim, print_zs[i], Point(0, 0), volume);
-
-        _3DScene::extrusionentity_to_verts(m_print->skirt, print_zs[i], Point(0, 0), volume);
-    }
-    volume.bounding_box = volume.indexed_vertex_array.bounding_box();
-    volume.indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
-}
-
-void GLCanvas3D::load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors)
-{
-    std::vector<float> tool_colors = _parse_colors(str_tool_colors);
-
-    struct Ctxt
-    {
-        const Points                *shifted_copies;
-        std::vector<const Layer*>    layers;
-        bool                         has_perimeters;
-        bool                         has_infill;
-        bool                         has_support;
-        const std::vector<float>*    tool_colors;
-
-        // Number of vertices (each vertex is 6x4=24 bytes long)
-        static const size_t          alloc_size_max() { return 131072; } // 3.15MB
-        //        static const size_t          alloc_size_max    () { return 65536; } // 1.57MB 
-        //        static const size_t          alloc_size_max    () { return 32768; } // 786kB
-        static const size_t          alloc_size_reserve() { return alloc_size_max() * 2; }
-
-        static const float*          color_perimeters() { static float color[4] = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
-        static const float*          color_infill() { static float color[4] = { 1.0f, 0.5f, 0.5f, 1.f }; return color; } // redish
-        static const float*          color_support() { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
-
-        // For cloring by a tool, return a parsed color.
-        bool                         color_by_tool() const { return tool_colors != nullptr; }
-        size_t                       number_tools()  const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
-        const float*                 color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
-        int                          volume_idx(int extruder, int feature) const
-        {
-            return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(extruder - 1, 0)) : feature;
-        }
-    } ctxt;
-
-    ctxt.shifted_copies = &print_object._shifted_copies;
-
-    // order layers by print_z
-    ctxt.layers.reserve(print_object.layers.size() + print_object.support_layers.size());
-    for (const Layer *layer : print_object.layers)
-        ctxt.layers.push_back(layer);
-    for (const Layer *layer : print_object.support_layers)
-        ctxt.layers.push_back(layer);
-    std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
-
-    // Maximum size of an allocation block: 32MB / sizeof(float)
-    ctxt.has_perimeters = print_object.state.is_done(posPerimeters);
-    ctxt.has_infill = print_object.state.is_done(posInfill);
-    ctxt.has_support = print_object.state.is_done(posSupportMaterial);
-    ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
-
-    BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
-
-    //FIXME Improve the heuristics for a grain size.
-    size_t          grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
-    tbb::spin_mutex new_volume_mutex;
-    auto            new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* {
-        auto *volume = new GLVolume(color);
-        new_volume_mutex.lock();
-        volume->outside_printer_detection_enabled = false;
-        m_volumes.volumes.emplace_back(volume);
-        new_volume_mutex.unlock();
-        return volume;
-    };
-    const size_t   volumes_cnt_initial = m_volumes.volumes.size();
-    std::vector<GLVolumeCollection> volumes_per_thread(ctxt.layers.size());
-    tbb::parallel_for(
-        tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
-        [&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
-        std::vector<GLVolume*> vols;
-        if (ctxt.color_by_tool()) {
-            for (size_t i = 0; i < ctxt.number_tools(); ++i)
-                vols.emplace_back(new_volume(ctxt.color_tool(i)));
-        }
-        else
-            vols = { new_volume(ctxt.color_perimeters()), new_volume(ctxt.color_infill()), new_volume(ctxt.color_support()) };
-        for (GLVolume *vol : vols)
-            vol->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
-        for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
-            const Layer *layer = ctxt.layers[idx_layer];
-            for (size_t i = 0; i < vols.size(); ++i) {
-                GLVolume &vol = *vols[i];
-                if (vol.print_zs.empty() || vol.print_zs.back() != layer->print_z) {
-                    vol.print_zs.push_back(layer->print_z);
-                    vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
-                    vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
-                }
-            }
-            for (const Point &copy : *ctxt.shifted_copies) {
-                for (const LayerRegion *layerm : layer->regions) {
-                    if (ctxt.has_perimeters)
-                        _3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
-                        *vols[ctxt.volume_idx(layerm->region()->config.perimeter_extruder.value, 0)]);
-                    if (ctxt.has_infill) {
-                        for (const ExtrusionEntity *ee : layerm->fills.entities) {
-                            // fill represents infill extrusions of a single island.
-                            const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
-                            if (!fill->entities.empty())
-                                _3DScene::extrusionentity_to_verts(*fill, float(layer->print_z), copy,
-                                *vols[ctxt.volume_idx(
-                                is_solid_infill(fill->entities.front()->role()) ?
-                                layerm->region()->config.solid_infill_extruder :
-                                layerm->region()->config.infill_extruder,
-                                1)]);
-                        }
-                    }
-                }
-                if (ctxt.has_support) {
-                    const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
-                    if (support_layer) {
-                        for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
-                            _3DScene::extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
-                            *vols[ctxt.volume_idx(
-                            (extrusion_entity->role() == erSupportMaterial) ?
-                            support_layer->object()->config.support_material_extruder :
-                            support_layer->object()->config.support_material_interface_extruder,
-                            2)]);
-                    }
-                }
-            }
-            for (size_t i = 0; i < vols.size(); ++i) {
-                GLVolume &vol = *vols[i];
-                if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
-                    // Store the vertex arrays and restart their containers, 
-                    vols[i] = new_volume(vol.color);
-                    GLVolume &vol_new = *vols[i];
-                    // Assign the large pre-allocated buffers to the new GLVolume.
-                    vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
-                    // Copy the content back to the old GLVolume.
-                    vol.indexed_vertex_array = vol_new.indexed_vertex_array;
-                    // Finalize a bounding box of the old GLVolume.
-                    vol.bounding_box = vol.indexed_vertex_array.bounding_box();
-                    // Clear the buffers, but keep them pre-allocated.
-                    vol_new.indexed_vertex_array.clear();
-                    // Just make sure that clear did not clear the reserved memory.
-                    vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
-                }
-            }
-        }
-        for (GLVolume *vol : vols) {
-            vol->bounding_box = vol->indexed_vertex_array.bounding_box();
-            vol->indexed_vertex_array.shrink_to_fit();
-        }
-    });
-
-    BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results";
-    // Remove empty volumes from the newly added volumes.
-    m_volumes.volumes.erase(
-        std::remove_if(m_volumes.volumes.begin() + volumes_cnt_initial, m_volumes.volumes.end(),
-        [](const GLVolume *volume) { return volume->empty(); }),
-        m_volumes.volumes.end());
-    for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i)
-        m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
-
-    BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
-}
-
-void GLCanvas3D::load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors)
-{
-    if ((m_print == nullptr) || m_print->m_wipe_tower_tool_changes.empty())
-        return;
-
-    if (!m_print->state.is_done(psWipeTower))
-        return;
-
-    std::vector<float> tool_colors = _parse_colors(str_tool_colors);
-
-    struct Ctxt
-    {
-        const Print                 *print;
-        const std::vector<float>    *tool_colors;
-
-        // Number of vertices (each vertex is 6x4=24 bytes long)
-        static const size_t          alloc_size_max() { return 131072; } // 3.15MB
-        static const size_t          alloc_size_reserve() { return alloc_size_max() * 2; }
-
-        static const float*          color_support() { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
-
-        // For cloring by a tool, return a parsed color.
-        bool                         color_by_tool() const { return tool_colors != nullptr; }
-        size_t                       number_tools()  const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
-        const float*                 color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
-        int                          volume_idx(int tool, int feature) const
-        {
-            return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(tool, 0)) : feature;
-        }
-
-        const std::vector<WipeTower::ToolChangeResult>& tool_change(size_t idx) {
-            return priming.empty() ?
-                ((idx == print->m_wipe_tower_tool_changes.size()) ? final : print->m_wipe_tower_tool_changes[idx]) :
-                ((idx == 0) ? priming : (idx == print->m_wipe_tower_tool_changes.size() + 1) ? final : print->m_wipe_tower_tool_changes[idx - 1]);
-        }
-        std::vector<WipeTower::ToolChangeResult> priming;
-        std::vector<WipeTower::ToolChangeResult> final;
-    } ctxt;
-
-    ctxt.print = m_print;
-    ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
-    if (m_print->m_wipe_tower_priming)
-        ctxt.priming.emplace_back(*m_print->m_wipe_tower_priming.get());
-    if (m_print->m_wipe_tower_final_purge)
-        ctxt.final.emplace_back(*m_print->m_wipe_tower_final_purge.get());
-
-    BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
-
-    //FIXME Improve the heuristics for a grain size.
-    size_t          n_items = m_print->m_wipe_tower_tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
-    size_t          grain_size = std::max(n_items / 128, size_t(1));
-    tbb::spin_mutex new_volume_mutex;
-    auto            new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* {
-        auto *volume = new GLVolume(color);
-        new_volume_mutex.lock();
-        volume->outside_printer_detection_enabled = false;
-        m_volumes.volumes.emplace_back(volume);
-        new_volume_mutex.unlock();
-        return volume;
-    };
-    const size_t   volumes_cnt_initial = m_volumes.volumes.size();
-    std::vector<GLVolumeCollection> volumes_per_thread(n_items);
-    tbb::parallel_for(
-        tbb::blocked_range<size_t>(0, n_items, grain_size),
-        [&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
-        // Bounding box of this slab of a wipe tower.
-        std::vector<GLVolume*> vols;
-        if (ctxt.color_by_tool()) {
-            for (size_t i = 0; i < ctxt.number_tools(); ++i)
-                vols.emplace_back(new_volume(ctxt.color_tool(i)));
-        }
-        else
-            vols = { new_volume(ctxt.color_support()) };
-        for (GLVolume *volume : vols)
-            volume->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
-        for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
-            const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer);
-            for (size_t i = 0; i < vols.size(); ++i) {
-                GLVolume &vol = *vols[i];
-                if (vol.print_zs.empty() || vol.print_zs.back() != layer.front().print_z) {
-                    vol.print_zs.push_back(layer.front().print_z);
-                    vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
-                    vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
-                }
-            }
-            for (const WipeTower::ToolChangeResult &extrusions : layer) {
-                for (size_t i = 1; i < extrusions.extrusions.size();) {
-                    const WipeTower::Extrusion &e = extrusions.extrusions[i];
-                    if (e.width == 0.) {
-                        ++i;
-                        continue;
-                    }
-                    size_t j = i + 1;
-                    if (ctxt.color_by_tool())
-                        for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].tool == e.tool && extrusions.extrusions[j].width > 0.f; ++j);
-                    else
-                        for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].width > 0.f; ++j);
-                    size_t              n_lines = j - i;
-                    Lines               lines;
-                    std::vector<double> widths;
-                    std::vector<double> heights;
-                    lines.reserve(n_lines);
-                    widths.reserve(n_lines);
-                    heights.assign(n_lines, extrusions.layer_height);
-                    for (; i < j; ++i) {
-                        const WipeTower::Extrusion &e = extrusions.extrusions[i];
-                        assert(e.width > 0.f);
-                        const WipeTower::Extrusion &e_prev = *(&e - 1);
-                        lines.emplace_back(Point::new_scale(e_prev.pos.x, e_prev.pos.y), Point::new_scale(e.pos.x, e.pos.y));
-                        widths.emplace_back(e.width);
-                    }
-                    _3DScene::thick_lines_to_verts(lines, widths, heights, lines.front().a == lines.back().b, extrusions.print_z,
-                        *vols[ctxt.volume_idx(e.tool, 0)]);
-                }
-            }
-        }
-        for (size_t i = 0; i < vols.size(); ++i) {
-            GLVolume &vol = *vols[i];
-            if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
-                // Store the vertex arrays and restart their containers, 
-                vols[i] = new_volume(vol.color);
-                GLVolume &vol_new = *vols[i];
-                // Assign the large pre-allocated buffers to the new GLVolume.
-                vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
-                // Copy the content back to the old GLVolume.
-                vol.indexed_vertex_array = vol_new.indexed_vertex_array;
-                // Finalize a bounding box of the old GLVolume.
-                vol.bounding_box = vol.indexed_vertex_array.bounding_box();
-                // Clear the buffers, but keep them pre-allocated.
-                vol_new.indexed_vertex_array.clear();
-                // Just make sure that clear did not clear the reserved memory.
-                vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
-            }
-        }
-        for (GLVolume *vol : vols) {
-            vol->bounding_box = vol->indexed_vertex_array.bounding_box();
-            vol->indexed_vertex_array.shrink_to_fit();
-        }
-    });
-
-    BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results";
-    // Remove empty volumes from the newly added volumes.
-    m_volumes.volumes.erase(
-        std::remove_if(m_volumes.volumes.begin() + volumes_cnt_initial, m_volumes.volumes.end(),
-        [](const GLVolume *volume) { return volume->empty(); }),
-        m_volumes.volumes.end());
-    for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i)
-        m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
-
-    BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end";
-}
-
 void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors)
 {
     if ((m_canvas != nullptr) && (m_print != nullptr))
@@ -2723,12 +2388,37 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
 
                 _load_shells();
             }
+            _update_toolpath_volumes_outside_state();
         }
         
         _update_gcode_volumes_visibility(preview_data);
+        _show_warning_texture_if_needed();
     }
 }
 
+void GLCanvas3D::load_preview(const std::vector<std::string>& str_tool_colors)
+{
+    if (m_print == nullptr)
+        return;
+
+    _load_print_toolpaths();
+    _load_wipe_tower_toolpaths(str_tool_colors);
+    for (const PrintObject* object : m_print->objects)
+    {
+        if (object != nullptr)
+            _load_print_object_toolpaths(*object, str_tool_colors);
+    }
+
+    for (GLVolume* volume : m_volumes.volumes)
+    {
+        volume->is_extrusion_path = true;
+    }
+
+    _update_toolpath_volumes_outside_state();
+    _show_warning_texture_if_needed();
+    reset_legend_texture();
+}
+
 void GLCanvas3D::register_on_viewport_changed_callback(void* callback)
 {
     if (callback != nullptr)
@@ -3025,6 +2715,12 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         m_mouse.set_start_position_2D_as_invalid();
 #endif
     } 
+    else if (evt.Leaving())
+    {
+        // to remove hover on objects when the mouse goes out of this canvas
+        m_mouse.position = Pointf(-1.0, -1.0);
+        m_dirty = true;
+    }
     else if (evt.LeftDClick() && (m_hover_volume_id != -1))
         m_on_double_click_callback.call();
     else if (evt.LeftDown() || evt.RightDown())
@@ -3062,7 +2758,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         {
             update_gizmos_data();
             m_gizmos.start_dragging();
-            m_mouse.drag.gizmo_volume_idx = _get_first_selected_volume_id();
+            m_mouse.drag.gizmo_volume_idx = _get_first_selected_volume_id(selected_object_idx);
             m_dirty = true;
         }
         else
@@ -3163,7 +2859,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             {
                 if (v != nullptr)
                 {
-                    if ((m_mouse.drag.move_with_shift && (v->select_group_id == group_id)) || (v->drag_group_id == group_id))
+                    if ((m_mouse.drag.move_with_shift && (v->select_group_id == group_id)) || (!m_mouse.drag.move_with_shift && (v->drag_group_id == group_id)))
                         volumes.push_back(v);
                 }
             }
@@ -3234,7 +2930,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
 
         if (!volumes.empty())
         {
-            const BoundingBoxf3& bb = volumes[0]->transformed_bounding_box();
+            BoundingBoxf3 bb;
+            for (const GLVolume* volume : volumes)
+            {
+                bb.merge(volume->transformed_bounding_box());
+            }
             const Pointf3& size = bb.size();
             m_on_update_geometry_info_callback.call(size.x, size.y, size.z, m_gizmos.get_scale());
         }
@@ -3381,7 +3081,13 @@ void GLCanvas3D::on_key_down(wxKeyEvent& evt)
         if (key == WXK_DELETE)
             m_on_remove_object_callback.call();
         else
-            evt.Skip();
+		{
+#ifdef __WXOSX__
+			if (key == WXK_BACK)
+				m_on_remove_object_callback.call();
+#endif
+			evt.Skip();
+		}
     }
 }
 
@@ -3502,11 +3208,45 @@ BoundingBoxf3 GLCanvas3D::_max_bounding_box() const
 BoundingBoxf3 GLCanvas3D::_selected_volumes_bounding_box() const
 {
     BoundingBoxf3 bb;
+
+    std::vector<const GLVolume*> selected_volumes;
     for (const GLVolume* volume : m_volumes.volumes)
     {
         if ((volume != nullptr) && !volume->is_wipe_tower && volume->selected)
-            bb.merge(volume->transformed_bounding_box());
+            selected_volumes.push_back(volume);
     }
+
+    bool use_drag_group_id = selected_volumes.size() > 1;
+    if (use_drag_group_id)
+    {
+        int drag_group_id = selected_volumes[0]->drag_group_id;
+        for (const GLVolume* volume : selected_volumes)
+        {
+            if (drag_group_id != volume->drag_group_id)
+            {
+                use_drag_group_id = false;
+                break;
+            }
+        }
+    }
+
+    if (use_drag_group_id)
+    {
+        for (const GLVolume* volume : selected_volumes)
+        {
+            bb.merge(volume->bounding_box);
+        }
+
+        bb = bb.transformed(selected_volumes[0]->world_matrix());
+    }
+    else
+    {
+        for (const GLVolume* volume : selected_volumes)
+        {
+            bb.merge(volume->transformed_bounding_box());
+        }
+    }
+
     return bb;
 }
 
@@ -3652,7 +3392,7 @@ void GLCanvas3D::_camera_tranform() const
     ::glMatrixMode(GL_MODELVIEW);
     ::glLoadIdentity();
 
-    ::glRotatef(-m_camera.get_theta(), 1.0f, 0.0f, 0.0f); //�pitch
+    ::glRotatef(-m_camera.get_theta(), 1.0f, 0.0f, 0.0f); // pitch
     ::glRotatef(m_camera.phi, 0.0f, 0.0f, 1.0f);          // yaw
 
     Pointf3 neg_target = m_camera.target.negative();
@@ -3683,20 +3423,22 @@ void GLCanvas3D::_picking_pass() const
         if (m_multisample_allowed)
             ::glEnable(GL_MULTISAMPLE);
 
-        const Size& cnv_size = get_canvas_size();
-
-        GLubyte color[4];
-        ::glReadPixels(pos.x, cnv_size.get_height() - pos.y - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color);
-        int volume_id = color[0] + color[1] * 256 + color[2] * 256 * 256;
-
-        m_hover_volume_id = -1;
-
+        int volume_id = -1;
         for (GLVolume* vol : m_volumes.volumes)
         {
             vol->hover = false;
         }
 
-        if (volume_id < (int)m_volumes.volumes.size())
+        GLubyte color[4] = { 0, 0, 0, 0 };
+        const Size& cnv_size = get_canvas_size();
+        bool inside = (0 <= pos.x) && (pos.x < cnv_size.get_width()) && (0 <= pos.y) && (pos.y < cnv_size.get_height());
+        if (inside)
+        {
+            ::glReadPixels(pos.x, cnv_size.get_height() - pos.y - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color);
+            volume_id = color[0] + color[1] * 256 + color[2] * 256 * 256;
+        }
+
+        if ((0 <= volume_id) && (volume_id < (int)m_volumes.volumes.size()))
         {
             m_hover_volume_id = volume_id;
             m_volumes.volumes[volume_id]->hover = true;
@@ -3712,7 +3454,10 @@ void GLCanvas3D::_picking_pass() const
             m_gizmos.set_hover_id(-1);
         }
         else
-            m_gizmos.set_hover_id(254 - (int)color[2]);
+        {
+            m_hover_volume_id = -1;
+            m_gizmos.set_hover_id(inside ? (254 - (int)color[2]) : -1);
+        }
 
         // updates gizmos overlay
         if (_get_first_selected_object_id() != -1)
@@ -3726,8 +3471,6 @@ void GLCanvas3D::_render_background() const
 {
     ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
-    static const float COLOR[3] = { 10.0f / 255.0f, 98.0f / 255.0f, 144.0f / 255.0f };
-
     ::glPushMatrix();
     ::glLoadIdentity();
     ::glMatrixMode(GL_PROJECTION);
@@ -3739,11 +3482,16 @@ void GLCanvas3D::_render_background() const
 
     ::glBegin(GL_QUADS);
     ::glColor3f(0.0f, 0.0f, 0.0f);
-    ::glVertex3f(-1.0f, -1.0f, 1.0f);
-    ::glVertex3f(1.0f, -1.0f, 1.0f);
-    ::glColor3f(COLOR[0], COLOR[1], COLOR[2]);
-    ::glVertex3f(1.0f, 1.0f, 1.0f);
-    ::glVertex3f(-1.0f, 1.0f, 1.0f);
+    ::glVertex2f(-1.0f, -1.0f);
+    ::glVertex2f(1.0f, -1.0f);
+
+    if (m_dynamic_background_enabled && _is_any_volume_outside())
+        ::glColor3f(ERROR_BG_COLOR[0], ERROR_BG_COLOR[1], ERROR_BG_COLOR[2]);
+    else
+        ::glColor3f(DEFAULT_BG_COLOR[0], DEFAULT_BG_COLOR[1], DEFAULT_BG_COLOR[2]);
+
+    ::glVertex2f(1.0f, 1.0f);
+    ::glVertex2f(-1.0f, 1.0f);
     ::glEnd();
 
     ::glEnable(GL_DEPTH_TEST);
@@ -4083,33 +3831,400 @@ int GLCanvas3D::_get_first_selected_object_id() const
     return -1;
 }
 
-int GLCanvas3D::_get_first_selected_volume_id() const
+int GLCanvas3D::_get_first_selected_volume_id(int object_id) const
 {
-    if (m_print != nullptr)
-    {
-        int objects_count = (int)m_print->objects.size();
+    int volume_id = -1;
 
-        for (const GLVolume* vol : m_volumes.volumes)
+    for (const GLVolume* vol : m_volumes.volumes)
+    {
+        ++volume_id;
+        if ((vol != nullptr) && vol->selected && (object_id == vol->select_group_id / 1000000))
+            return volume_id;
+    }
+
+    return -1;
+}
+
+void GLCanvas3D::_load_print_toolpaths()
+{
+    // ensures this canvas is current
+    if (!set_current())
+        return;
+
+    if (m_print == nullptr)
+        return;
+
+    if (!m_print->state.is_done(psSkirt) || !m_print->state.is_done(psBrim))
+        return;
+
+    if (!m_print->has_skirt() && (m_print->config.brim_width.value == 0))
+        return;
+
+    const float color[] = { 0.5f, 1.0f, 0.5f, 1.0f }; // greenish
+
+    // number of skirt layers
+    size_t total_layer_count = 0;
+    for (const PrintObject* print_object : m_print->objects)
+    {
+        total_layer_count = std::max(total_layer_count, print_object->total_layer_count());
+    }
+    size_t skirt_height = m_print->has_infinite_skirt() ? total_layer_count : std::min<size_t>(m_print->config.skirt_height.value, total_layer_count);
+    if ((skirt_height == 0) && (m_print->config.brim_width.value > 0))
+        skirt_height = 1;
+
+    // get first skirt_height layers (maybe this should be moved to a PrintObject method?)
+    const PrintObject* object0 = m_print->objects.front();
+    std::vector<float> print_zs;
+    print_zs.reserve(skirt_height * 2);
+    for (size_t i = 0; i < std::min(skirt_height, object0->layers.size()); ++i)
+    {
+        print_zs.push_back(float(object0->layers[i]->print_z));
+    }
+    //FIXME why there are support layers?
+    for (size_t i = 0; i < std::min(skirt_height, object0->support_layers.size()); ++i)
+    {
+        print_zs.push_back(float(object0->support_layers[i]->print_z));
+    }
+    sort_remove_duplicates(print_zs);
+    if (print_zs.size() > skirt_height)
+        print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
+
+    m_volumes.volumes.emplace_back(new GLVolume(color));
+    GLVolume& volume = *m_volumes.volumes.back();
+    for (size_t i = 0; i < skirt_height; ++i) {
+        volume.print_zs.push_back(print_zs[i]);
+        volume.offsets.push_back(volume.indexed_vertex_array.quad_indices.size());
+        volume.offsets.push_back(volume.indexed_vertex_array.triangle_indices.size());
+        if (i == 0)
+            _3DScene::extrusionentity_to_verts(m_print->brim, print_zs[i], Point(0, 0), volume);
+
+        _3DScene::extrusionentity_to_verts(m_print->skirt, print_zs[i], Point(0, 0), volume);
+    }
+    volume.bounding_box = volume.indexed_vertex_array.bounding_box();
+    volume.indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
+}
+
+void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors)
+{
+    std::vector<float> tool_colors = _parse_colors(str_tool_colors);
+
+    struct Ctxt
+    {
+        const Points                *shifted_copies;
+        std::vector<const Layer*>    layers;
+        bool                         has_perimeters;
+        bool                         has_infill;
+        bool                         has_support;
+        const std::vector<float>*    tool_colors;
+
+        // Number of vertices (each vertex is 6x4=24 bytes long)
+        static const size_t          alloc_size_max() { return 131072; } // 3.15MB
+        //        static const size_t          alloc_size_max    () { return 65536; } // 1.57MB 
+        //        static const size_t          alloc_size_max    () { return 32768; } // 786kB
+        static const size_t          alloc_size_reserve() { return alloc_size_max() * 2; }
+
+        static const float*          color_perimeters() { static float color[4] = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
+        static const float*          color_infill() { static float color[4] = { 1.0f, 0.5f, 0.5f, 1.f }; return color; } // redish
+        static const float*          color_support() { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
+
+        // For cloring by a tool, return a parsed color.
+        bool                         color_by_tool() const { return tool_colors != nullptr; }
+        size_t                       number_tools()  const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
+        const float*                 color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
+        int                          volume_idx(int extruder, int feature) const
         {
-            if ((vol != nullptr) && vol->selected)
-            {
-                int object_id = vol->select_group_id / 1000000;
-                // Objects with object_id >= 1000 have a specific meaning, for example the wipe tower proxy.
-                if ((object_id < 10000) && (object_id < objects_count))
-                {
-                    int volume_id = 0;
-                    for (int i = 0; i < object_id; ++i)
-                    {
-                        const PrintObject* obj = m_print->objects[i];
-                        const ModelObject* model = obj->model_object();
-                        volume_id += model->instances.size();
+            return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(extruder - 1, 0)) : feature;
+        }
+    } ctxt;
+
+    ctxt.shifted_copies = &print_object._shifted_copies;
+
+    // order layers by print_z
+    ctxt.layers.reserve(print_object.layers.size() + print_object.support_layers.size());
+    for (const Layer *layer : print_object.layers)
+        ctxt.layers.push_back(layer);
+    for (const Layer *layer : print_object.support_layers)
+        ctxt.layers.push_back(layer);
+    std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
+
+    // Maximum size of an allocation block: 32MB / sizeof(float)
+    ctxt.has_perimeters = print_object.state.is_done(posPerimeters);
+    ctxt.has_infill = print_object.state.is_done(posInfill);
+    ctxt.has_support = print_object.state.is_done(posSupportMaterial);
+    ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
+
+    BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
+
+    //FIXME Improve the heuristics for a grain size.
+    size_t          grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
+    tbb::spin_mutex new_volume_mutex;
+    auto            new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* {
+        auto *volume = new GLVolume(color);
+        new_volume_mutex.lock();
+        m_volumes.volumes.emplace_back(volume);
+        new_volume_mutex.unlock();
+        return volume;
+    };
+    const size_t   volumes_cnt_initial = m_volumes.volumes.size();
+    std::vector<GLVolumeCollection> volumes_per_thread(ctxt.layers.size());
+    tbb::parallel_for(
+        tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
+        [&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
+        std::vector<GLVolume*> vols;
+        if (ctxt.color_by_tool()) {
+            for (size_t i = 0; i < ctxt.number_tools(); ++i)
+                vols.emplace_back(new_volume(ctxt.color_tool(i)));
+        }
+        else
+            vols = { new_volume(ctxt.color_perimeters()), new_volume(ctxt.color_infill()), new_volume(ctxt.color_support()) };
+        for (GLVolume *vol : vols)
+            vol->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
+        for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
+            const Layer *layer = ctxt.layers[idx_layer];
+            for (size_t i = 0; i < vols.size(); ++i) {
+                GLVolume &vol = *vols[i];
+                if (vol.print_zs.empty() || vol.print_zs.back() != layer->print_z) {
+                    vol.print_zs.push_back(layer->print_z);
+                    vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
+                    vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
+                }
+            }
+            for (const Point &copy : *ctxt.shifted_copies) {
+                for (const LayerRegion *layerm : layer->regions) {
+                    if (ctxt.has_perimeters)
+                        _3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
+                        *vols[ctxt.volume_idx(layerm->region()->config.perimeter_extruder.value, 0)]);
+                    if (ctxt.has_infill) {
+                        for (const ExtrusionEntity *ee : layerm->fills.entities) {
+                            // fill represents infill extrusions of a single island.
+                            const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
+                            if (!fill->entities.empty())
+                                _3DScene::extrusionentity_to_verts(*fill, float(layer->print_z), copy,
+                                *vols[ctxt.volume_idx(
+                                is_solid_infill(fill->entities.front()->role()) ?
+                                layerm->region()->config.solid_infill_extruder :
+                                layerm->region()->config.infill_extruder,
+                                1)]);
+                        }
                     }
-                    return volume_id;
+                }
+                if (ctxt.has_support) {
+                    const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
+                    if (support_layer) {
+                        for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
+                            _3DScene::extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
+                            *vols[ctxt.volume_idx(
+                            (extrusion_entity->role() == erSupportMaterial) ?
+                            support_layer->object()->config.support_material_extruder :
+                            support_layer->object()->config.support_material_interface_extruder,
+                            2)]);
+                    }
+                }
+            }
+            for (size_t i = 0; i < vols.size(); ++i) {
+                GLVolume &vol = *vols[i];
+                if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
+                    // Store the vertex arrays and restart their containers, 
+                    vols[i] = new_volume(vol.color);
+                    GLVolume &vol_new = *vols[i];
+                    // Assign the large pre-allocated buffers to the new GLVolume.
+                    vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
+                    // Copy the content back to the old GLVolume.
+                    vol.indexed_vertex_array = vol_new.indexed_vertex_array;
+                    // Finalize a bounding box of the old GLVolume.
+                    vol.bounding_box = vol.indexed_vertex_array.bounding_box();
+                    // Clear the buffers, but keep them pre-allocated.
+                    vol_new.indexed_vertex_array.clear();
+                    // Just make sure that clear did not clear the reserved memory.
+                    vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
                 }
             }
         }
-    }
-    return -1;
+        for (GLVolume *vol : vols) {
+            vol->bounding_box = vol->indexed_vertex_array.bounding_box();
+            vol->indexed_vertex_array.shrink_to_fit();
+        }
+    });
+
+    BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results";
+    // Remove empty volumes from the newly added volumes.
+    m_volumes.volumes.erase(
+        std::remove_if(m_volumes.volumes.begin() + volumes_cnt_initial, m_volumes.volumes.end(),
+        [](const GLVolume *volume) { return volume->empty(); }),
+        m_volumes.volumes.end());
+    for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i)
+        m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
+
+    BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
+}
+
+void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors)
+{
+    if ((m_print == nullptr) || m_print->m_wipe_tower_tool_changes.empty())
+        return;
+
+    if (!m_print->state.is_done(psWipeTower))
+        return;
+
+    std::vector<float> tool_colors = _parse_colors(str_tool_colors);
+
+    struct Ctxt
+    {
+        const Print                 *print;
+        const std::vector<float>    *tool_colors;
+        WipeTower::xy                wipe_tower_pos;
+        float                        wipe_tower_angle;
+
+        // Number of vertices (each vertex is 6x4=24 bytes long)
+        static const size_t          alloc_size_max() { return 131072; } // 3.15MB
+        static const size_t          alloc_size_reserve() { return alloc_size_max() * 2; }
+
+        static const float*          color_support() { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
+
+        // For cloring by a tool, return a parsed color.
+        bool                         color_by_tool() const { return tool_colors != nullptr; }
+        size_t                       number_tools()  const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
+        const float*                 color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
+        int                          volume_idx(int tool, int feature) const
+        {
+            return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(tool, 0)) : feature;
+        }
+
+        const std::vector<WipeTower::ToolChangeResult>& tool_change(size_t idx) {
+            return priming.empty() ?
+                ((idx == print->m_wipe_tower_tool_changes.size()) ? final : print->m_wipe_tower_tool_changes[idx]) :
+                ((idx == 0) ? priming : (idx == print->m_wipe_tower_tool_changes.size() + 1) ? final : print->m_wipe_tower_tool_changes[idx - 1]);
+        }
+        std::vector<WipeTower::ToolChangeResult> priming;
+        std::vector<WipeTower::ToolChangeResult> final;
+    } ctxt;
+
+    ctxt.print = m_print;
+    ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
+    if (m_print->m_wipe_tower_priming && m_print->config.single_extruder_multi_material_priming)
+        ctxt.priming.emplace_back(*m_print->m_wipe_tower_priming.get());
+    if (m_print->m_wipe_tower_final_purge)
+        ctxt.final.emplace_back(*m_print->m_wipe_tower_final_purge.get());
+
+    ctxt.wipe_tower_angle = ctxt.print->config.wipe_tower_rotation_angle.value/180.f * M_PI;
+    ctxt.wipe_tower_pos = WipeTower::xy(ctxt.print->config.wipe_tower_x.value, ctxt.print->config.wipe_tower_y.value);
+
+    BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
+
+    //FIXME Improve the heuristics for a grain size.
+    size_t          n_items = m_print->m_wipe_tower_tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
+    size_t          grain_size = std::max(n_items / 128, size_t(1));
+    tbb::spin_mutex new_volume_mutex;
+    auto            new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* {
+        auto *volume = new GLVolume(color);
+        new_volume_mutex.lock();
+        m_volumes.volumes.emplace_back(volume);
+        new_volume_mutex.unlock();
+        return volume;
+    };
+    const size_t   volumes_cnt_initial = m_volumes.volumes.size();
+    std::vector<GLVolumeCollection> volumes_per_thread(n_items);
+    tbb::parallel_for(
+        tbb::blocked_range<size_t>(0, n_items, grain_size),
+        [&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
+        // Bounding box of this slab of a wipe tower.
+        std::vector<GLVolume*> vols;
+        if (ctxt.color_by_tool()) {
+            for (size_t i = 0; i < ctxt.number_tools(); ++i)
+                vols.emplace_back(new_volume(ctxt.color_tool(i)));
+        }
+        else
+            vols = { new_volume(ctxt.color_support()) };
+        for (GLVolume *volume : vols)
+            volume->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
+        for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
+            const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer);
+            for (size_t i = 0; i < vols.size(); ++i) {
+                GLVolume &vol = *vols[i];
+                if (vol.print_zs.empty() || vol.print_zs.back() != layer.front().print_z) {
+                    vol.print_zs.push_back(layer.front().print_z);
+                    vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
+                    vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
+                }
+            }
+            for (const WipeTower::ToolChangeResult &extrusions : layer) {
+                for (size_t i = 1; i < extrusions.extrusions.size();) {
+                    const WipeTower::Extrusion &e = extrusions.extrusions[i];
+                    if (e.width == 0.) {
+                        ++i;
+                        continue;
+                    }
+                    size_t j = i + 1;
+                    if (ctxt.color_by_tool())
+                        for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].tool == e.tool && extrusions.extrusions[j].width > 0.f; ++j);
+                    else
+                        for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].width > 0.f; ++j);
+                    size_t              n_lines = j - i;
+                    Lines               lines;
+                    std::vector<double> widths;
+                    std::vector<double> heights;
+                    lines.reserve(n_lines);
+                    widths.reserve(n_lines);
+                    heights.assign(n_lines, extrusions.layer_height);
+                    WipeTower::Extrusion e_prev = extrusions.extrusions[i-1];
+
+                    if (!extrusions.priming) { // wipe tower extrusions describe the wipe tower at the origin with no rotation
+                        e_prev.pos.rotate(ctxt.wipe_tower_angle);
+                        e_prev.pos.translate(ctxt.wipe_tower_pos);
+                    }
+
+                    for (; i < j; ++i) {
+                        WipeTower::Extrusion e = extrusions.extrusions[i];
+                        assert(e.width > 0.f);
+                        if (!extrusions.priming) {
+                            e.pos.rotate(ctxt.wipe_tower_angle);
+                            e.pos.translate(ctxt.wipe_tower_pos);
+                        }
+
+                        lines.emplace_back(Point::new_scale(e_prev.pos.x, e_prev.pos.y), Point::new_scale(e.pos.x, e.pos.y));
+                        widths.emplace_back(e.width);
+
+                        e_prev = e;
+                    }
+                    _3DScene::thick_lines_to_verts(lines, widths, heights, lines.front().a == lines.back().b, extrusions.print_z,
+                        *vols[ctxt.volume_idx(e.tool, 0)]);
+                }
+            }
+        }
+        for (size_t i = 0; i < vols.size(); ++i) {
+            GLVolume &vol = *vols[i];
+            if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
+                // Store the vertex arrays and restart their containers, 
+                vols[i] = new_volume(vol.color);
+                GLVolume &vol_new = *vols[i];
+                // Assign the large pre-allocated buffers to the new GLVolume.
+                vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
+                // Copy the content back to the old GLVolume.
+                vol.indexed_vertex_array = vol_new.indexed_vertex_array;
+                // Finalize a bounding box of the old GLVolume.
+                vol.bounding_box = vol.indexed_vertex_array.bounding_box();
+                // Clear the buffers, but keep them pre-allocated.
+                vol_new.indexed_vertex_array.clear();
+                // Just make sure that clear did not clear the reserved memory.
+                vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
+            }
+        }
+        for (GLVolume *vol : vols) {
+            vol->bounding_box = vol->indexed_vertex_array.bounding_box();
+            vol->indexed_vertex_array.shrink_to_fit();
+        }
+    });
+
+    BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results";
+    // Remove empty volumes from the newly added volumes.
+    m_volumes.volumes.erase(
+        std::remove_if(m_volumes.volumes.begin() + volumes_cnt_initial, m_volumes.volumes.end(),
+        [](const GLVolume *volume) { return volume->empty(); }),
+        m_volumes.volumes.end());
+    for (size_t i = volumes_cnt_initial; i < m_volumes.volumes.size(); ++i)
+        m_volumes.volumes[i]->indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
+
+    BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end";
 }
 
 static inline int hex_digit_to_int(const char c)
@@ -4230,6 +4345,7 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
         if (volume != nullptr)
         {
             filter.volume = volume;
+            volume->is_extrusion_path = true;
             m_volumes.volumes.emplace_back(volume);
         }
         else
@@ -4627,8 +4743,11 @@ void GLCanvas3D::_load_shells()
     const PrintConfig& config = m_print->config;
     unsigned int extruders_count = config.nozzle_diameter.size();
     if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects) {
-        const float width_per_extruder = 15.0f; // a simple workaround after wipe_tower_per_color_wipe got obsolete
-        m_volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, width_per_extruder * (extruders_count - 1), max_z, config.wipe_tower_rotation_angle, m_use_VBOs && m_initialized);
+        float depth = m_print->get_wipe_tower_depth();
+        if (!m_print->state.is_done(psWipeTower))
+            depth = (900.f/config.wipe_tower_width) * (float)(extruders_count - 1) ;
+        m_volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle,
+                                          m_use_VBOs && m_initialized, !m_print->state.is_done(psWipeTower), m_print->config.nozzle_diameter.values[0] * 1.25f * 4.5f);
     }
 }
 
@@ -4643,7 +4762,6 @@ void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& previe
         for (std::vector<GLVolume*>::iterator it = begin; it != end; ++it)
         {
             GLVolume* volume = *it;
-            volume->outside_printer_detection_enabled = false;
 
             switch (m_gcode_preview_volume_index.first_volumes[i].type)
             {
@@ -4691,12 +4809,51 @@ void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& previe
     }
 }
 
+void GLCanvas3D::_update_toolpath_volumes_outside_state()
+{
+    // tolerance to avoid false detection at bed edges
+    static const coordf_t tolerance_x = 0.05;
+    static const coordf_t tolerance_y = 0.05;
+
+    BoundingBoxf3 print_volume;
+    if (m_config != nullptr)
+    {
+        const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(m_config->option("bed_shape"));
+        if (opt != nullptr)
+        {
+            BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
+            print_volume = BoundingBoxf3(Pointf3(unscale(bed_box_2D.min.x) - tolerance_x, unscale(bed_box_2D.min.y) - tolerance_y, 0.0), Pointf3(unscale(bed_box_2D.max.x) + tolerance_x, unscale(bed_box_2D.max.y) + tolerance_y, m_config->opt_float("max_print_height")));
+            // Allow the objects to protrude below the print bed
+            print_volume.min.z = -1e10;
+        }
+    }
+
+    for (GLVolume* volume : m_volumes.volumes)
+    {
+        volume->is_outside = ((print_volume.radius() > 0.0) && volume->is_extrusion_path) ? !print_volume.contains(volume->bounding_box) : false;
+    }
+}
+
+void GLCanvas3D::_show_warning_texture_if_needed()
+{
+    if (_is_any_volume_outside())
+    {
+        enable_warning_texture(true);
+        _generate_warning_texture(L("Detected toolpath outside print volume"));
+    }
+    else
+    {
+        enable_warning_texture(false);
+        _reset_warning_texture();
+    }
+}
+
 void GLCanvas3D::_on_move(const std::vector<int>& volume_idxs)
 {
     if (m_model == nullptr)
         return;
 
-    std::set<std::string> done;  //�prevent moving instances twice
+    std::set<std::string> done;  // prevent moving instances twice
     bool object_moved = false;
     Pointf3 wipe_tower_origin(0.0, 0.0, 0.0);
     for (int volume_idx : volume_idxs)
@@ -4705,7 +4862,7 @@ void GLCanvas3D::_on_move(const std::vector<int>& volume_idxs)
         int obj_idx = volume->object_idx();
         int instance_idx = volume->instance_idx();
 
-        //�prevent moving instances twice
+        // prevent moving instances twice
         char done_id[64];
         ::sprintf(done_id, "%d_%d", obj_idx, instance_idx);
         if (done.find(done_id) != done.end())
@@ -4796,5 +4953,16 @@ void GLCanvas3D::_reset_warning_texture()
     m_warning_texture.reset();
 }
 
+bool GLCanvas3D::_is_any_volume_outside() const
+{
+    for (const GLVolume* volume : m_volumes.volumes)
+    {
+        if ((volume != nullptr) && volume->is_outside)
+            return true;
+    }
+
+    return false;
+}
+
 } // namespace GUI
 } // namespace Slic3r
diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp
index a9a6117ec..ae20882fc 100644
--- a/xs/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp
@@ -162,7 +162,8 @@ public:
         bool is_custom() const;
 
         const Pointfs& get_shape() const;
-        void set_shape(const Pointfs& shape);
+        // Return true if the bed shape changed, so the calee will update the UI.
+        bool set_shape(const Pointfs& shape);
 
         const BoundingBoxf3& get_bounding_box() const;
         bool contains(const Point& point) const;
@@ -449,6 +450,7 @@ private:
     bool m_picking_enabled;
     bool m_moving_enabled;
     bool m_shader_enabled;
+    bool m_dynamic_background_enabled;
     bool m_multisample_allowed;
 
     std::string m_color_by;
@@ -539,6 +541,7 @@ public:
     void enable_gizmos(bool enable);
     void enable_shader(bool enable);
     void enable_force_zoom_to_bed(bool enable);
+    void enable_dynamic_background(bool enable);
     void allow_multisample(bool allow);
 
     void zoom_to_bed();
@@ -559,16 +562,8 @@ public:
 
     void reload_scene(bool force);
 
-    // Create 3D thick extrusion lines for a skirt and brim.
-    // Adds a new Slic3r::GUI::3DScene::Volume to volumes.
-    void load_print_toolpaths();
-    // Create 3D thick extrusion lines for object forming extrusions.
-    // Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
-    // one for perimeters, one for infill and one for supports.
-    void load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors);
-    // Create 3D thick extrusion lines for wipe tower extrusions
-    void load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);
     void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
+    void load_preview(const std::vector<std::string>& str_tool_colors);
 
     void register_on_viewport_changed_callback(void* callback);
     void register_on_double_click_callback(void* callback);
@@ -650,7 +645,17 @@ private:
     void _stop_timer();
 
     int _get_first_selected_object_id() const;
-    int _get_first_selected_volume_id() const;
+    int _get_first_selected_volume_id(int object_id) const;
+
+    // Create 3D thick extrusion lines for a skirt and brim.
+    // Adds a new Slic3r::GUI::3DScene::Volume to volumes.
+    void _load_print_toolpaths();
+    // Create 3D thick extrusion lines for object forming extrusions.
+    // Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
+    // one for perimeters, one for infill and one for supports.
+    void _load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors);
+    // Create 3D thick extrusion lines for wipe tower extrusions
+    void _load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);
 
     // generates gcode extrusion paths geometry
     void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
@@ -667,6 +672,8 @@ private:
     void _load_shells();
     // sets gcode geometry visibility according to user selection
     void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
+    void _update_toolpath_volumes_outside_state();
+    void _show_warning_texture_if_needed();
 
     void _on_move(const std::vector<int>& volume_idxs);
     void _on_select(int volume_idx);
@@ -678,6 +685,8 @@ private:
     void _generate_warning_texture(const std::string& msg);
     void _reset_warning_texture();
 
+    bool _is_any_volume_outside() const;
+
     static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
 };
 
diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp
index 5e9048d54..5249f6dc4 100644
--- a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp
+++ b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp
@@ -418,6 +418,13 @@ void GLCanvas3DManager::enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable
         it->second->enable_force_zoom_to_bed(enable);
 }
 
+void GLCanvas3DManager::enable_dynamic_background(wxGLCanvas* canvas, bool enable)
+{
+    CanvasesMap::iterator it = _get_canvas(canvas);
+    if (it != m_canvases.end())
+        it->second->enable_dynamic_background(enable);
+}
+
 void GLCanvas3DManager::allow_multisample(wxGLCanvas* canvas, bool allow)
 {
     CanvasesMap::iterator it = _get_canvas(canvas);
@@ -516,30 +523,6 @@ void GLCanvas3DManager::reload_scene(wxGLCanvas* canvas, bool force)
         it->second->reload_scene(force);
 }
 
-void GLCanvas3DManager::load_print_toolpaths(wxGLCanvas* canvas)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->load_print_toolpaths();
-}
-
-void GLCanvas3DManager::load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& tool_colors)
-{
-    if (print_object == nullptr)
-        return;
-
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->load_print_object_toolpaths(*print_object, tool_colors);
-}
-
-void GLCanvas3DManager::load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
-{
-    CanvasesMap::iterator it = _get_canvas(canvas);
-    if (it != m_canvases.end())
-        it->second->load_wipe_tower_toolpaths(str_tool_colors);
-}
-
 void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
 {
     if (preview_data == nullptr)
@@ -550,6 +533,13 @@ void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePrevie
         it->second->load_gcode_preview(*preview_data, str_tool_colors);
 }
 
+void GLCanvas3DManager::load_preview(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
+{
+    CanvasesMap::iterator it = _get_canvas(canvas);
+    if (it != m_canvases.end())
+        it->second->load_preview(str_tool_colors);
+}
+
 void GLCanvas3DManager::reset_legend_texture()
 {
     for (CanvasesMap::value_type& canvas : m_canvases)
diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp
index 32aa712d3..55c42fda6 100644
--- a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp
+++ b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp
@@ -112,6 +112,7 @@ public:
     void enable_gizmos(wxGLCanvas* canvas, bool enable);
     void enable_shader(wxGLCanvas* canvas, bool enable);
     void enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable);
+    void enable_dynamic_background(wxGLCanvas* canvas, bool enable);
     void allow_multisample(wxGLCanvas* canvas, bool allow);
 
     void zoom_to_bed(wxGLCanvas* canvas);
@@ -132,10 +133,8 @@ public:
 
     void reload_scene(wxGLCanvas* canvas, bool force);
 
-    void load_print_toolpaths(wxGLCanvas* canvas);
-    void load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& tool_colors);
-    void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
     void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
+    void load_preview(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
 
     void reset_legend_texture();
 
diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp
index af7022f2b..8cd7ed776 100644
--- a/xs/src/slic3r/GUI/GUI.cpp
+++ b/xs/src/slic3r/GUI/GUI.cpp
@@ -250,6 +250,7 @@ bool select_language(wxArrayString & names,
 		g_wxLocale->AddCatalogLookupPathPrefix(wxPathOnly(localization_dir()));
 		g_wxLocale->AddCatalog(g_wxApp->GetAppName());
 		wxSetlocale(LC_NUMERIC, "C");
+		Preset::update_suffix_modified();
 		return true;
 	}
 	return false;
@@ -275,6 +276,7 @@ bool load_language()
 			g_wxLocale->AddCatalogLookupPathPrefix(wxPathOnly(localization_dir()));
 			g_wxLocale->AddCatalog(g_wxApp->GetAppName());
 			wxSetlocale(LC_NUMERIC, "C");
+			Preset::update_suffix_modified();
 			return true;
 		}
 	}
@@ -901,6 +903,7 @@ void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFl
                     std::vector<float> extruders = dlg.get_extruders();
                     (config.option<ConfigOptionFloats>("wiping_volumes_matrix"))->values = std::vector<double>(matrix.begin(),matrix.end());
                     (config.option<ConfigOptionFloats>("wiping_volumes_extruders"))->values = std::vector<double>(extruders.begin(),extruders.end());
+                    g_on_request_update_callback.call();
                 }
 			}));
 			return sizer;
@@ -917,7 +920,6 @@ ConfigOptionsGroup* get_optgroup()
 	return m_optgroup.get();
 }
 
-
 wxButton* get_wiping_dialog_button()
 {
 	return g_wiping_dialog_button;
diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp
index efb11b7df..165288819 100644
--- a/xs/src/slic3r/GUI/GUI.hpp
+++ b/xs/src/slic3r/GUI/GUI.hpp
@@ -4,6 +4,7 @@
 #include <string>
 #include <vector>
 #include "Config.hpp"
+#include "../../libslic3r/Utils.hpp"
 
 #include <wx/intl.h>
 #include <wx/string.h>
@@ -171,6 +172,9 @@ wxString	from_u8(const std::string &str);
 
 void add_frequently_changed_parameters(wxWindow* parent, wxBoxSizer* sizer, wxFlexGridSizer* preset_sizer);
 
+// Callback to trigger a configuration update timer on the Plater.
+static PerlCallback g_on_request_update_callback;
+ 
 ConfigOptionsGroup* get_optgroup();
 wxButton*			get_wiping_dialog_button();
 
diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp
index f3b44af54..effe9f4fb 100644
--- a/xs/src/slic3r/GUI/Preset.cpp
+++ b/xs/src/slic3r/GUI/Preset.cpp
@@ -146,6 +146,11 @@ const std::string& Preset::suffix_modified()
 {
     return g_suffix_modified;
 }
+
+void Preset::update_suffix_modified()
+{
+	g_suffix_modified = (" (" + _(L("modified")) + ")").ToUTF8().data();
+}
 // Remove an optional "(modified)" suffix from a name.
 // This converts a UI name to a unique preset identifier.
 std::string Preset::remove_suffix_modified(const std::string &name)
@@ -298,8 +303,8 @@ const std::vector<std::string>& Preset::print_options()
         "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", 
         "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "bridge_flow_ratio", "clip_multipart_objects", 
         "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y",
-        "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "compatible_printers",
-        "compatible_printers_condition","inherits"
+        "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "single_extruder_multi_material_priming", 
+        "compatible_printers", "compatible_printers_condition","inherits"
     };
     return s_opts;
 }
@@ -308,11 +313,13 @@ const std::vector<std::string>& Preset::filament_options()
 {    
     static std::vector<std::string> s_opts {
         "filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed",
-        "extrusion_multiplier", "filament_density", "filament_cost", "filament_loading_speed", "filament_unloading_speed", "filament_toolchange_delay",
-        "filament_cooling_moves", "filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters", "temperature",
-        "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature", "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed",
-        "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time", "slowdown_below_layer_time", "min_print_speed",
-        "start_filament_gcode", "end_filament_gcode","compatible_printers", "compatible_printers_condition", "inherits"
+        "extrusion_multiplier", "filament_density", "filament_cost", 
+        "filament_loading_speed", "filament_load_time", "filament_unloading_speed", "filament_unload_time", "filament_toolchange_delay",
+        "filament_cooling_moves", "filament_cooling_initial_speed", "filament_cooling_final_speed", "filament_ramming_parameters",
+        "filament_minimal_purge_on_wipe_tower", "temperature", "first_layer_temperature", "bed_temperature", "first_layer_bed_temperature",
+        "fan_always_on", "cooling", "min_fan_speed", "max_fan_speed", "bridge_fan_speed", "disable_fan_first_layers", "fan_below_layer_time",
+        "slowdown_below_layer_time", "min_print_speed", "start_filament_gcode", "end_filament_gcode","compatible_printers", "compatible_printers_condition",
+        "inherits"
     };
     return s_opts;
 }
@@ -327,7 +334,7 @@ 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",
+            "remaining_times", "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",
diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp
index a2ee1d2eb..0d00cae48 100644
--- a/xs/src/slic3r/GUI/Preset.hpp
+++ b/xs/src/slic3r/GUI/Preset.hpp
@@ -167,6 +167,7 @@ public:
     static const std::vector<std::string>&  printer_options();
     // Nozzle options of the printer options.
     static const std::vector<std::string>&  nozzle_options();
+	static void update_suffix_modified();
 
 protected:
     friend class        PresetCollection;
@@ -260,7 +261,7 @@ public:
 	// used to update preset_choice from Tab
 	const std::deque<Preset>&	get_presets()	{ return m_presets; }
 	int						get_idx_selected()	{ return m_idx_selected; }
-	const std::string&		get_suffix_modified();
+	static const std::string&	get_suffix_modified();
 
     // Return a preset possibly with modifications.
 	Preset&			default_preset()			{ return m_presets.front(); }
diff --git a/xs/src/slic3r/GUI/PresetBundle.cpp b/xs/src/slic3r/GUI/PresetBundle.cpp
index 58553e1bc..94baa0e0e 100644
--- a/xs/src/slic3r/GUI/PresetBundle.cpp
+++ b/xs/src/slic3r/GUI/PresetBundle.cpp
@@ -552,6 +552,8 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
     std::string &inherits                       = Preset::inherits(config);
     compatible_printers_condition_values.resize(num_extruders + 2, std::string());
     inherits_values.resize(num_extruders + 2, std::string());
+    // The "default_filament_profile" will be later extracted into the printer profile.
+    config.option<ConfigOptionStrings>("default_filament_profile", true)->values.resize(num_extruders, std::string());
 
     // 1) Create a name from the file name.
     // Keep the suffix (.ini, .gcode, .amf, .3mf etc) to differentiate it from the normal profiles.
@@ -576,7 +578,6 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
     // 3) Now load the filaments. If there are multiple filament presets, split them and load them.
     auto old_filament_profile_names = config.option<ConfigOptionStrings>("filament_settings_id", true);
 	old_filament_profile_names->values.resize(num_extruders, std::string());
-    config.option<ConfigOptionStrings>("default_filament_profile", true)->values.resize(num_extruders, std::string());
 
     if (num_extruders <= 1) {
         // Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets.
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index 5d1c51eb3..7c4322c5a 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -919,6 +919,7 @@ void TabPrint::build()
 		optgroup->append_single_option_line("wipe_tower_width");
 		optgroup->append_single_option_line("wipe_tower_rotation_angle");
         optgroup->append_single_option_line("wipe_tower_bridging");
+        optgroup->append_single_option_line("single_extruder_multi_material_priming");
 
 		optgroup = page->new_optgroup(_(L("Advanced")));
 		optgroup->append_single_option_line("interface_shells");
@@ -1291,10 +1292,13 @@ void TabFilament::build()
         optgroup = page->new_optgroup(_(L("Toolchange parameters with single extruder MM printers")));
 		optgroup->append_single_option_line("filament_loading_speed");
         optgroup->append_single_option_line("filament_unloading_speed");
+		optgroup->append_single_option_line("filament_load_time");
+		optgroup->append_single_option_line("filament_unload_time");
         optgroup->append_single_option_line("filament_toolchange_delay");
         optgroup->append_single_option_line("filament_cooling_moves");
         optgroup->append_single_option_line("filament_cooling_initial_speed");
         optgroup->append_single_option_line("filament_cooling_final_speed");
+        optgroup->append_single_option_line("filament_minimal_purge_on_wipe_tower");
 
         line = { _(L("Ramming")), "" };
         line.widget = [this](wxWindow* parent){
@@ -1606,6 +1610,7 @@ void TabPrinter::build()
 		optgroup = page->new_optgroup(_(L("Firmware")));
 		optgroup->append_single_option_line("gcode_flavor");
 		optgroup->append_single_option_line("silent_mode");
+		optgroup->append_single_option_line("remaining_times");
 
 		optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value){
 			wxTheApp->CallAfter([this, opt_key, value](){
@@ -2728,7 +2733,7 @@ void SavePresetWindow::accept()
 		const char* unusable_symbols = "<>:/\\|?*\"";
 		bool is_unusable_symbol = false;
 		bool is_unusable_postfix = false;
-		const std::string unusable_postfix = "(modified)";
+		const std::string unusable_postfix = PresetCollection::get_suffix_modified();//"(modified)";
 		for (size_t i = 0; i < std::strlen(unusable_symbols); i++){
 			if (m_chosen_name.find_first_of(unusable_symbols[i]) != std::string::npos){
 				is_unusable_symbol = true;
@@ -2743,8 +2748,9 @@ void SavePresetWindow::accept()
 							_(L("the following characters are not allowed:")) + " <>:/\\|?*\"");
 		}
 		else if (is_unusable_postfix){
-			show_error(this,	_(L("The supplied name is not valid;")) + "\n" + 
-								_(L("the following postfix are not allowed:")) + "\n\t" + unusable_postfix);
+			show_error(this,_(L("The supplied name is not valid;")) + "\n" +
+							_(L("the following postfix are not allowed:")) + "\n\t" + //unusable_postfix);
+							wxString::FromUTF8(unusable_postfix.c_str()));
 		}
 		else if (m_chosen_name.compare("- default -") == 0) {
 			show_error(this, _(L("The supplied name is not available.")));
diff --git a/xs/src/slic3r/Utils/HexFile.cpp b/xs/src/slic3r/Utils/HexFile.cpp
new file mode 100644
index 000000000..282c647bd
--- /dev/null
+++ b/xs/src/slic3r/Utils/HexFile.cpp
@@ -0,0 +1,106 @@
+#include "HexFile.hpp"
+
+#include <sstream>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/ini_parser.hpp>
+
+namespace fs = boost::filesystem;
+namespace pt = boost::property_tree;
+
+
+namespace Slic3r {
+namespace Utils {
+
+
+static HexFile::DeviceKind parse_device_kind(const std::string &str)
+{
+	     if (str == "mk2") { return HexFile::DEV_MK2; }
+	else if (str == "mk3") { return HexFile::DEV_MK3; }
+	else if (str == "mm-control") { return HexFile::DEV_MM_CONTROL; }
+	else { return HexFile::DEV_GENERIC; }
+}
+
+static size_t hex_num_sections(fs::ifstream &file)
+{
+	file.seekg(0);
+	if (! file.good()) {
+		return 0;
+	}
+
+	static const char *hex_terminator = ":00000001FF\r";
+	size_t res = 0;
+	std::string line;
+	while (getline(file, line, '\n').good()) {
+		// Account for LF vs CRLF
+		if (!line.empty() && line.back() != '\r') {
+			line.push_back('\r');
+		}
+
+		if (line == hex_terminator) {
+			res++;
+		}
+	}
+
+	return res;
+}
+
+HexFile::HexFile(fs::path path) :
+	path(std::move(path))
+{
+	fs::ifstream file(this->path);
+	if (! file.good()) {
+		return;
+	}
+
+	std::string line;
+	std::stringstream header_ini;
+	while (std::getline(file, line, '\n').good()) {
+		if (line.empty()) {
+			continue;
+		}
+
+		// Account for LF vs CRLF
+		if (!line.empty() && line.back() == '\r') {
+			line.pop_back();
+		}
+
+		if (line.front() == ';') {
+			line.front() = ' ';
+			header_ini << line << std::endl;
+		} else if (line.front() == ':') {
+			break;
+		}
+	}
+
+	pt::ptree ptree;
+	try {
+		pt::read_ini(header_ini, ptree);
+	} catch (std::exception &e) {
+		return;
+	}
+
+	bool has_device_meta = false;
+	const auto device = ptree.find("device");
+	if (device != ptree.not_found()) {
+		this->device = parse_device_kind(device->second.data());
+		has_device_meta = true;
+	}
+
+	const auto model_id = ptree.find("model_id");
+	if (model_id != ptree.not_found()) {
+		this->model_id = model_id->second.data();
+	}
+
+	if (! has_device_meta) {
+		// No device metadata, look at the number of 'sections'
+		if (hex_num_sections(file) == 2) {
+			// Looks like a pre-metadata l10n firmware for the MK3, assume that's the case
+			this->device = DEV_MK3;
+		}
+	}
+}
+
+
+}
+}
diff --git a/xs/src/slic3r/Utils/HexFile.hpp b/xs/src/slic3r/Utils/HexFile.hpp
new file mode 100644
index 000000000..1201d23a4
--- /dev/null
+++ b/xs/src/slic3r/Utils/HexFile.hpp
@@ -0,0 +1,33 @@
+#ifndef slic3r_Hex_hpp_
+#define slic3r_Hex_hpp_
+
+#include <string>
+#include <boost/filesystem/path.hpp>
+
+
+namespace Slic3r {
+namespace Utils {
+
+
+struct HexFile
+{
+	enum DeviceKind {
+		DEV_GENERIC,
+		DEV_MK2,
+		DEV_MK3,
+		DEV_MM_CONTROL,
+	};
+
+	boost::filesystem::path path;
+	DeviceKind device = DEV_GENERIC;
+	std::string model_id;
+
+	HexFile() {}
+	HexFile(boost::filesystem::path path);
+};
+
+
+}
+}
+
+#endif
diff --git a/xs/src/slic3r/Utils/Serial.cpp b/xs/src/slic3r/Utils/Serial.cpp
index 32b6bb160..183119b44 100644
--- a/xs/src/slic3r/Utils/Serial.cpp
+++ b/xs/src/slic3r/Utils/Serial.cpp
@@ -3,17 +3,22 @@
 #include <algorithm>
 #include <string>
 #include <vector>
+#include <chrono>
+#include <thread>
 #include <fstream>
+#include <stdexcept>
 
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/format.hpp>
+#include <boost/optional.hpp>
 
 #if _WIN32
 	#include <Windows.h>
 	#include <Setupapi.h>
 	#include <initguid.h>
 	#include <devguid.h>
+	#include <regex>
 	// Undefine min/max macros incompatible with the standard library
 	// For example, std::numeric_limits<std::streamsize>::max()
 	// produces some weird errors
@@ -34,6 +39,23 @@
 	#include <sys/syslimits.h>
 #endif
 
+#ifndef _WIN32
+	#include <sys/ioctl.h>
+	#include <sys/time.h>
+	#include <sys/unistd.h>
+	#include <sys/select.h>
+#endif
+
+#if defined(__APPLE__) || defined(__OpenBSD__)
+	#include <termios.h>
+#elif defined __linux__
+	#include <fcntl.h>
+	#include <asm-generic/ioctls.h>
+#endif
+
+using boost::optional;
+
+
 namespace Slic3r {
 namespace Utils {
 
@@ -42,15 +64,43 @@ static bool looks_like_printer(const std::string &friendly_name)
 	return friendly_name.find("Original Prusa") != std::string::npos;
 }
 
-#ifdef __linux__
-static std::string get_tty_friendly_name(const std::string &path, const std::string &name)
+#if _WIN32
+void parse_hardware_id(const std::string &hardware_id, SerialPortInfo &spi)
 {
-	const auto sysfs_product = (boost::format("/sys/class/tty/%1%/device/../product") % name).str();
-	std::ifstream file(sysfs_product);
-	std::string product;
+	unsigned vid, pid;
+	std::regex pattern("USB\\\\.*VID_([[:xdigit:]]+)&PID_([[:xdigit:]]+).*");
+	std::smatch matches;
+	if (std::regex_match(hardware_id, matches, pattern)) {
+		try {
+			vid = std::stoul(matches[1].str(), 0, 16);
+			pid = std::stoul(matches[2].str(), 0, 16);
+			spi.id_vendor = vid;
+			spi.id_product = pid;
+		}
+		catch (...) {}
+	}
+}
+#endif
 
-	std::getline(file, product);
-	return file.good() ? (boost::format("%1% (%2%)") % product % path).str() : path;
+#ifdef __linux__
+optional<std::string> sysfs_tty_prop(const std::string &tty_dev, const std::string &name)
+{
+	const auto prop_path = (boost::format("/sys/class/tty/%1%/device/../%2%") % tty_dev % name).str();
+	std::ifstream file(prop_path);
+	std::string res;
+
+	std::getline(file, res);
+	if (file.good()) { return res; }
+	else { return boost::none; }
+}
+
+optional<unsigned long> sysfs_tty_prop_hex(const std::string &tty_dev, const std::string &name)
+{
+	auto prop = sysfs_tty_prop(tty_dev, name);
+	if (!prop) { return boost::none; }
+
+	try { return std::stoul(*prop, 0, 16); }
+	catch (...) { return boost::none; }
 }
 #endif
 
@@ -80,6 +130,7 @@ std::vector<SerialPortInfo> scan_serial_ports_extended()
 				if (port_info.port.empty())
 					continue;
 			}
+
 			// Find the size required to hold the device info.
 			DWORD regDataType;
 			DWORD reqSize = 0;
@@ -88,7 +139,8 @@ std::vector<SerialPortInfo> scan_serial_ports_extended()
 			// Now store it in a buffer.
 			if (! SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, &regDataType, (BYTE*)hardware_id.data(), reqSize, nullptr))
 				continue;
-			port_info.hardware_id = boost::nowide::narrow(hardware_id.data());
+			parse_hardware_id(boost::nowide::narrow(hardware_id.data()), port_info);
+
 			// Find the size required to hold the friendly name.
 			reqSize = 0;
 			SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, nullptr, 0, &reqSize);
@@ -120,6 +172,8 @@ std::vector<SerialPortInfo> scan_serial_ports_extended()
 					if (result) {
 						SerialPortInfo port_info;
 						port_info.port = path;
+
+						// Attempt to read out the device friendly name
 						if ((cf_property = IORegistryEntrySearchCFProperty(port, kIOServicePlane,
 						         CFSTR("USB Interface Name"), kCFAllocatorDefault,
 						         kIORegistryIterateRecursively | kIORegistryIterateParents)) ||
@@ -141,6 +195,23 @@ std::vector<SerialPortInfo> scan_serial_ports_extended()
 						}
 						if (port_info.friendly_name.empty())
 							port_info.friendly_name = port_info.port;
+
+						// Attempt to read out the VID & PID
+						int vid, pid;
+						auto cf_vendor = IORegistryEntrySearchCFProperty(port, kIOServicePlane, CFSTR("idVendor"),
+							kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
+						auto cf_product = IORegistryEntrySearchCFProperty(port, kIOServicePlane, CFSTR("idProduct"),
+							kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
+						if (cf_vendor && cf_product) {
+							if (CFNumberGetValue((CFNumberRef)cf_vendor, kCFNumberIntType, &vid) &&
+								CFNumberGetValue((CFNumberRef)cf_product, kCFNumberIntType, &pid)) {
+								port_info.id_vendor = vid;
+								port_info.id_product = pid;
+							}
+						}
+						if (cf_vendor) { CFRelease(cf_vendor); }
+						if (cf_product) { CFRelease(cf_product); }
+
 						output.emplace_back(std::move(port_info));
 					}
 				}
@@ -158,9 +229,15 @@ std::vector<SerialPortInfo> scan_serial_ports_extended()
                 const auto path = dir_entry.path().string();
                 SerialPortInfo spi;
                 spi.port = path;
-                spi.hardware_id = path;
 #ifdef __linux__
-                spi.friendly_name = get_tty_friendly_name(path, name);
+				auto friendly_name = sysfs_tty_prop(name, "product");
+				spi.friendly_name = friendly_name ? (boost::format("%1% (%2%)") % *friendly_name % path).str() : path;
+				auto vid = sysfs_tty_prop_hex(name, "idVendor");
+				auto pid = sysfs_tty_prop_hex(name, "idProduct");
+				if (vid && pid) {
+					spi.id_vendor = *vid;
+					spi.id_product = *pid;
+				}
 #else
                 spi.friendly_name = path;
 #endif
@@ -189,5 +266,225 @@ std::vector<std::string> scan_serial_ports()
 	return output;
 }
 
+
+
+// Class Serial
+
+namespace asio = boost::asio;
+using boost::system::error_code;
+
+Serial::Serial(asio::io_service& io_service) :
+	asio::serial_port(io_service)
+{}
+
+Serial::Serial(asio::io_service& io_service, const std::string &name, unsigned baud_rate) :
+	asio::serial_port(io_service, name)
+{
+	set_baud_rate(baud_rate);
+}
+
+Serial::~Serial() {}
+
+void Serial::set_baud_rate(unsigned baud_rate)
+{
+	try {
+		// This does not support speeds > 115200
+		set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
+	} catch (boost::system::system_error &) {
+		auto handle = native_handle();
+
+		auto handle_errno = [](int retval) {
+			if (retval != 0) {
+				throw std::runtime_error(
+					(boost::format("Could not set baud rate: %1%") % strerror(errno)).str()
+				);
+			}
+		};
+
+#if __APPLE__
+		termios ios;
+		handle_errno(::tcgetattr(handle, &ios));
+		handle_errno(::cfsetspeed(&ios, baud_rate));
+		speed_t newSpeed = baud_rate;
+		handle_errno(::ioctl(handle, IOSSIOSPEED, &newSpeed));
+		handle_errno(::tcsetattr(handle, TCSANOW, &ios));
+#elif __linux
+
+		/* The following definitions are kindly borrowed from:
+			/usr/include/asm-generic/termbits.h
+			Unfortunately we cannot just include that one because
+			it would redefine the "struct termios" already defined
+			the <termios.h> already included by Boost.ASIO. */
+#define K_NCCS 19
+		struct termios2 {
+			tcflag_t c_iflag;
+			tcflag_t c_oflag;
+			tcflag_t c_cflag;
+			tcflag_t c_lflag;
+			cc_t c_line;
+			cc_t c_cc[K_NCCS];
+			speed_t c_ispeed;
+			speed_t c_ospeed;
+		};
+#define BOTHER CBAUDEX
+
+		termios2 ios;
+		handle_errno(::ioctl(handle, TCGETS2, &ios));
+		ios.c_ispeed = ios.c_ospeed = baud_rate;
+		ios.c_cflag &= ~CBAUD;
+		ios.c_cflag |= BOTHER | CLOCAL | CREAD;
+		ios.c_cc[VMIN] = 1; // Minimum of characters to read, prevents eof errors when 0 bytes are read
+		ios.c_cc[VTIME] = 1;
+		handle_errno(::ioctl(handle, TCSETS2, &ios));
+
+#elif __OpenBSD__
+		struct termios ios;
+		handle_errno(::tcgetattr(handle, &ios));
+		handle_errno(::cfsetspeed(&ios, baud_rate));
+		handle_errno(::tcsetattr(handle, TCSAFLUSH, &ios));
+#else
+		throw std::runtime_error("Custom baud rates are not currently supported on this OS");
+#endif
+	}
+}
+
+void Serial::set_DTR(bool on)
+{
+	auto handle = native_handle();
+#if defined(_WIN32) && !defined(__SYMBIAN32__)
+	if (! EscapeCommFunction(handle, on ? SETDTR : CLRDTR)) {
+		throw std::runtime_error("Could not set serial port DTR");
+	}
+#else
+	int status;
+	if (::ioctl(handle, TIOCMGET, &status) == 0) {
+		on ? status |= TIOCM_DTR : status &= ~TIOCM_DTR;
+		if (::ioctl(handle, TIOCMSET, &status) == 0) {
+			return;
+		}
+	}
+
+	throw std::runtime_error(
+		(boost::format("Could not set serial port DTR: %1%") % strerror(errno)).str()
+	);
+#endif
+}
+
+void Serial::reset_line_num()
+{
+	// See https://github.com/MarlinFirmware/Marlin/wiki/M110
+	write_string("M110 N0\n");
+	m_line_num = 0;
+}
+
+bool Serial::read_line(unsigned timeout, std::string &line, error_code &ec)
+{
+	auto &io_service = get_io_service();
+	asio::deadline_timer timer(io_service);
+	char c = 0;
+	bool fail = false;
+
+	while (true) {
+		io_service.reset();
+
+		asio::async_read(*this, boost::asio::buffer(&c, 1), [&](const error_code &read_ec, size_t size) {
+			if (ec || size == 0) {
+				fail = true;
+				ec = read_ec;   // FIXME: only if operation not aborted
+			}
+			timer.cancel();   // FIXME: ditto
+		});
+
+		if (timeout > 0) {
+			timer.expires_from_now(boost::posix_time::milliseconds(timeout));
+			timer.async_wait([&](const error_code &ec) {
+				// Ignore timer aborts
+				if (!ec) {
+					fail = true;
+					this->cancel();
+				}
+			});
+		}
+
+		io_service.run();
+
+		if (fail) {
+			return false;
+		} else if (c != '\n') {
+			line += c;
+		} else {
+			return true;
+		}
+	}
+}
+
+void Serial::printer_setup()
+{
+	printer_reset();
+	write_string("\r\r\r\r\r\r\r\r\r\r");    // Gets rid of line noise, if any
+}
+
+size_t Serial::write_string(const std::string &str)
+{
+	// TODO: might be wise to timeout here as well
+	return asio::write(*this, asio::buffer(str));
+}
+
+bool Serial::printer_ready_wait(unsigned retries, unsigned timeout)
+{
+	std::string line;
+	error_code ec;
+
+	for (; retries > 0; retries--) {
+		reset_line_num();
+
+		while (read_line(timeout, line, ec)) {
+			if (line == "ok") {
+				return true;
+			}
+			line.clear();
+		}
+
+		line.clear();
+	}
+
+	return false;
+}
+
+size_t Serial::printer_write_line(const std::string &line, unsigned line_num)
+{
+	const auto formatted_line = Utils::Serial::printer_format_line(line, line_num);
+	return write_string(formatted_line);
+}
+
+size_t Serial::printer_write_line(const std::string &line)
+{
+	m_line_num++;
+	return printer_write_line(line, m_line_num);
+}
+
+void Serial::printer_reset()
+{
+	this->set_DTR(false);
+	std::this_thread::sleep_for(std::chrono::milliseconds(200));
+	this->set_DTR(true);
+	std::this_thread::sleep_for(std::chrono::milliseconds(200));
+	this->set_DTR(false);
+	std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+}
+
+std::string Serial::printer_format_line(const std::string &line, unsigned line_num)
+{
+	const auto line_num_str = std::to_string(line_num);
+
+	unsigned checksum = 'N';
+	for (auto c : line_num_str) { checksum ^= c; }
+	checksum ^= ' ';
+	for (auto c : line) { checksum ^= c; }
+
+	return (boost::format("N%1% %2%*%3%\n") % line_num_str % line % checksum).str();
+}
+
+
 } // namespace Utils
 } // namespace Slic3r
diff --git a/xs/src/slic3r/Utils/Serial.hpp b/xs/src/slic3r/Utils/Serial.hpp
index 9381ab398..e4a28de09 100644
--- a/xs/src/slic3r/Utils/Serial.hpp
+++ b/xs/src/slic3r/Utils/Serial.hpp
@@ -1,31 +1,81 @@
 #ifndef slic3r_GUI_Utils_Serial_hpp_
 #define slic3r_GUI_Utils_Serial_hpp_
 
-#include <memory>
 #include <vector>
 #include <string>
-#include <vector>
+#include <boost/system/error_code.hpp>
+#include <boost/asio.hpp>
+
 
 namespace Slic3r {
 namespace Utils {
 
 struct SerialPortInfo {
 	std::string port;
-	std::string hardware_id;
+	unsigned    id_vendor = -1;
+	unsigned    id_product = -1;
 	std::string friendly_name;
-	bool 		is_printer = false;
+	bool        is_printer = false;
+
+	bool id_match(unsigned id_vendor, unsigned id_product) const { return id_vendor == this->id_vendor && id_product == this->id_product; }
 };
 
-inline bool operator==(const SerialPortInfo &sp1, const SerialPortInfo &sp2) 
+inline bool operator==(const SerialPortInfo &sp1, const SerialPortInfo &sp2)
 {
-	return sp1.port 	   == sp2.port 	      &&
-		   sp1.hardware_id == sp2.hardware_id &&
-		   sp1.is_printer  == sp2.is_printer;
+	return
+		sp1.port       == sp2.port       &&
+		sp1.id_vendor  == sp2.id_vendor  &&
+		sp1.id_product == sp2.id_product &&
+		sp1.is_printer == sp2.is_printer;
 }
 
 extern std::vector<std::string> 	scan_serial_ports();
 extern std::vector<SerialPortInfo> 	scan_serial_ports_extended();
 
+
+class Serial : public boost::asio::serial_port
+{
+public:
+	Serial(boost::asio::io_service &io_service);
+	Serial(boost::asio::io_service &io_service, const std::string &name, unsigned baud_rate);
+	Serial(const Serial &) = delete;
+	Serial &operator=(const Serial &) = delete;
+	~Serial();
+
+	void set_baud_rate(unsigned baud_rate);
+	void set_DTR(bool on);
+
+	// Resets the line number both internally as well as with the firmware using M110
+	void reset_line_num();
+
+	// Reads a line or times out, the timeout is in milliseconds
+	bool read_line(unsigned timeout, std::string &line, boost::system::error_code &ec);
+
+	// Perform an initial setup for communicating with a printer
+	void printer_setup();
+
+	// Write data from a string
+	size_t write_string(const std::string &str);
+
+	// Attempts to reset the line numer and waits until the printer says "ok"
+	bool printer_ready_wait(unsigned retries, unsigned timeout);
+
+	// Write Marlin-formatted line, with a line number and a checksum
+	size_t printer_write_line(const std::string &line, unsigned line_num);
+
+	// Same as above, but with internally-managed line number
+	size_t printer_write_line(const std::string &line);
+	
+	// Toggles DTR to reset the printer
+	void printer_reset();
+
+	// Formats a line Marlin-style, ie. with a sequential number and a checksum
+	static std::string printer_format_line(const std::string &line, unsigned line_num);
+private:
+	unsigned m_line_num = 0;
+};
+
+
 } // Utils
 } // Slic3r
 
diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp
index 6b05e9a67..c6eead1ad 100644
--- a/xs/xsp/GUI.xsp
+++ b/xs/xsp/GUI.xsp
@@ -104,3 +104,10 @@ void fix_model_by_win10_sdk_gui(ModelObject *model_object_src, Print *print, Mod
 
 void set_3DScene(SV *scene)
     %code%{ Slic3r::GUI::set_3DScene((_3DScene *)wxPli_sv_2_object(aTHX_ scene, "Slic3r::Model::3DScene") ); %};
+
+void register_on_request_update_callback(SV* callback)
+    %code%{ Slic3r::GUI::g_on_request_update_callback.register_callback(callback); %};
+
+void deregister_on_request_update_callback()
+    %code%{ Slic3r::GUI::g_on_request_update_callback.deregister_callback(); %};
+
diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp
index 5c2f7df85..0e0a03f5e 100644
--- a/xs/xsp/GUI_3DScene.xsp
+++ b/xs/xsp/GUI_3DScene.xsp
@@ -89,7 +89,7 @@
 
     std::vector<int> load_object(ModelObject *object, int obj_idx, std::vector<int> instance_idxs, std::string color_by, std::string select_by, std::string drag_by, bool use_VBOs);
 
-    int load_wipe_tower_preview(int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs);
+    int load_wipe_tower_preview(int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width);
 
     void erase()
         %code{% THIS->clear(); %};
@@ -430,6 +430,13 @@ enable_force_zoom_to_bed(canvas, enable)
     CODE:
         _3DScene::enable_force_zoom_to_bed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
 
+void
+enable_dynamic_background(canvas, enable)
+        SV   *canvas;
+        bool enable;
+    CODE:
+        _3DScene::enable_dynamic_background((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
+
 void
 allow_multisample(canvas, allow)
         SV   *canvas;
@@ -657,27 +664,6 @@ reload_scene(canvas, force)
     CODE:
         _3DScene::reload_scene((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), force);
 
-void
-load_print_toolpaths(canvas)
-        SV *canvas;
-    CODE:
-        _3DScene::load_print_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
-
-void 
-load_print_object_toolpaths(canvas, print_object, tool_colors)
-        SV                       *canvas;
-        PrintObject              *print_object;
-        std::vector<std::string> tool_colors;
-    CODE:
-        _3DScene::load_print_object_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), print_object, tool_colors);
-
-void
-load_wipe_tower_toolpaths(canvas, tool_colors)
-        SV                       *canvas;
-        std::vector<std::string> tool_colors;
-    CODE:
-        _3DScene::load_wipe_tower_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), tool_colors);
-
 void 
 load_gcode_preview(canvas, preview_data, str_tool_colors)
         SV                       *canvas;
@@ -685,5 +671,12 @@ load_gcode_preview(canvas, preview_data, str_tool_colors)
         std::vector<std::string> str_tool_colors;
     CODE:
         _3DScene::load_gcode_preview((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), preview_data, str_tool_colors);
-        
+
+void
+load_preview(canvas, str_tool_colors)
+        SV                       *canvas;
+        std::vector<std::string> str_tool_colors;
+    CODE:
+        _3DScene::load_preview((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), str_tool_colors);
+
 %}