diff --git a/resources/localization/Slic3rPE.pot b/resources/localization/Slic3rPE.pot
index e2f4a6ec2..b0852567f 100644
--- a/resources/localization/Slic3rPE.pot
+++ b/resources/localization/Slic3rPE.pot
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-09 19:23+0200\n"
+"POT-Creation-Date: 2019-05-10 11:50+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"
@@ -46,6 +46,33 @@ msgid ""
 "numerous others."
 msgstr ""
 
+#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:84
+#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:400
+msgid "Copying of the temporary G-code to the output G-code failed"
+msgstr ""
+
+#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:85
+#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:398
+msgid "Running post-processing scripts"
+msgstr ""
+
+#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:87
+msgid "G-code file exported to %1%"
+msgstr ""
+
+#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:91
+#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:109
+msgid "Slicing complete"
+msgstr ""
+
+#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:105
+msgid "Masked SLA file exported to %1%"
+msgstr ""
+
+#: src/slic3r/GUI/BackgroundSlicingProcess.cpp:409
+msgid "Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"
+msgstr ""
+
 #: src/slic3r/GUI/BedShapeDialog.cpp:60
 msgid "Shape"
 msgstr ""
@@ -225,6 +252,7 @@ msgid "slic3r version"
 msgstr ""
 
 #: src/slic3r/GUI/ConfigSnapshotDialog.cpp:46 src/slic3r/GUI/Preset.cpp:1274
+#: src/slic3r/GUI/Tab.hpp:315
 msgid "print"
 msgstr ""
 
@@ -233,6 +261,7 @@ msgid "filaments"
 msgstr ""
 
 #: src/slic3r/GUI/ConfigSnapshotDialog.cpp:48 src/slic3r/GUI/Preset.cpp:1278
+#: src/slic3r/GUI/Tab.hpp:366
 msgid "printer"
 msgstr ""
 
@@ -285,7 +314,7 @@ msgstr ""
 msgid "All standard"
 msgstr ""
 
-#: src/slic3r/GUI/ConfigWizard.cpp:189 src/slic3r/GUI/Tab.cpp:2987
+#: src/slic3r/GUI/ConfigWizard.cpp:189 src/slic3r/GUI/Tab.cpp:3000
 msgid "All"
 msgstr ""
 
@@ -538,28 +567,28 @@ msgstr ""
 msgid "Configuration &Wizard"
 msgstr ""
 
-#: src/slic3r/GUI/Field.cpp:93
+#: src/slic3r/GUI/Field.cpp:117
 msgid "default value"
 msgstr ""
 
-#: src/slic3r/GUI/Field.cpp:96
+#: src/slic3r/GUI/Field.cpp:120
 msgid "parameter name"
 msgstr ""
 
-#: src/slic3r/GUI/Field.cpp:124
+#: src/slic3r/GUI/Field.cpp:148
 #, possible-c-format
 msgid "%s doesn't support percentage"
 msgstr ""
 
-#: src/slic3r/GUI/Field.cpp:138 src/slic3r/GUI/Field.cpp:161
+#: src/slic3r/GUI/Field.cpp:162 src/slic3r/GUI/Field.cpp:185
 msgid "Invalid numeric input."
 msgstr ""
 
-#: src/slic3r/GUI/Field.cpp:143
+#: src/slic3r/GUI/Field.cpp:167
 msgid "Input value is out of range"
 msgstr ""
 
-#: src/slic3r/GUI/Field.cpp:169
+#: src/slic3r/GUI/Field.cpp:193
 #, possible-c-format
 msgid ""
 "Do you mean %d%% instead of %d %s?\n"
@@ -567,7 +596,7 @@ msgid ""
 "or NO if you are sure that %d %s is a correct value."
 msgstr ""
 
-#: src/slic3r/GUI/Field.cpp:172
+#: src/slic3r/GUI/Field.cpp:196
 msgid "Parameter validation"
 msgstr ""
 
@@ -694,67 +723,71 @@ msgstr ""
 msgid "Cancelling..."
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:719
-msgid "Detected object outside print volume"
-msgstr ""
-
 #: src/slic3r/GUI/GLCanvas3D.cpp:720
-msgid "Detected toolpath outside print volume"
+msgid "An object outside the print area was detected"
 msgstr ""
 
 #: src/slic3r/GUI/GLCanvas3D.cpp:721
-msgid "Some objects are not visible when editing supports"
+msgid "A toolpath outside the print area was detected"
+msgstr ""
+
+#: src/slic3r/GUI/GLCanvas3D.cpp:722
+msgid "SLA supports outside the print area were detected"
 msgstr ""
 
 #: src/slic3r/GUI/GLCanvas3D.cpp:723
-msgid ""
-"Detected object outside print volume\n"
-"Resolve a clash to continue slicing/export process correctly"
+msgid "Some objects are not visible when editing supports"
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3392
+#: src/slic3r/GUI/GLCanvas3D.cpp:725
+msgid ""
+"An object outside the print area was detected\n"
+"Resolve the current problem to continue slicing"
+msgstr ""
+
+#: src/slic3r/GUI/GLCanvas3D.cpp:3434
 msgid "Add..."
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3402 src/slic3r/GUI/GUI_ObjectList.cpp:1269
-#: src/slic3r/GUI/Plater.cpp:2908 src/slic3r/GUI/Plater.cpp:2926
-#: src/slic3r/GUI/Tab.cpp:2938
+#: src/slic3r/GUI/GLCanvas3D.cpp:3444 src/slic3r/GUI/GUI_ObjectList.cpp:1269
+#: src/slic3r/GUI/Plater.cpp:2933 src/slic3r/GUI/Plater.cpp:2951
+#: src/slic3r/GUI/Tab.cpp:2951
 msgid "Delete"
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3413 src/slic3r/GUI/Plater.cpp:3316
+#: src/slic3r/GUI/GLCanvas3D.cpp:3455 src/slic3r/GUI/Plater.cpp:3341
 msgid "Delete all"
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3424 src/slic3r/GUI/KBShortcutsDialog.cpp:135
+#: src/slic3r/GUI/GLCanvas3D.cpp:3466 src/slic3r/GUI/KBShortcutsDialog.cpp:135
 msgid "Arrange"
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3438 src/slic3r/GUI/Tab.cpp:2879
+#: src/slic3r/GUI/GLCanvas3D.cpp:3480 src/slic3r/GUI/Tab.cpp:2892
 msgid "Copy"
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3449
+#: src/slic3r/GUI/GLCanvas3D.cpp:3491
 msgid "Paste"
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3463
+#: src/slic3r/GUI/GLCanvas3D.cpp:3505
 msgid "Add instance"
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3475
+#: src/slic3r/GUI/GLCanvas3D.cpp:3517
 msgid "Remove instance"
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3490
+#: src/slic3r/GUI/GLCanvas3D.cpp:3532
 msgid "Split to objects"
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3502 src/slic3r/GUI/GUI_ObjectList.cpp:1122
+#: src/slic3r/GUI/GLCanvas3D.cpp:3544 src/slic3r/GUI/GUI_ObjectList.cpp:1122
 msgid "Split to parts"
 msgstr ""
 
-#: src/slic3r/GUI/GLCanvas3D.cpp:3517
+#: src/slic3r/GUI/GLCanvas3D.cpp:3559
 msgid "Layers editing"
 msgstr ""
 
@@ -974,7 +1007,7 @@ msgstr ""
 msgid "Switch to editing mode"
 msgstr ""
 
-#: src/slic3r/GUI/GUI.cpp:142 src/slic3r/GUI/Tab.cpp:2797
+#: src/slic3r/GUI/GUI.cpp:142 src/slic3r/GUI/Tab.cpp:2810
 msgid "It's impossible to print multi-part object(s) with SLA technology."
 msgstr ""
 
@@ -982,7 +1015,7 @@ msgstr ""
 msgid "Please check and fix your object list."
 msgstr ""
 
-#: src/slic3r/GUI/GUI.cpp:144 src/slic3r/GUI/Tab.cpp:2799
+#: src/slic3r/GUI/GUI.cpp:144 src/slic3r/GUI/Tab.cpp:2812
 msgid "Attention!"
 msgstr ""
 
@@ -1067,7 +1100,7 @@ msgstr ""
 #: src/slic3r/GUI/GUI_ObjectList.cpp:539 src/slic3r/GUI/Tab.cpp:1027
 #: src/slic3r/GUI/Tab.cpp:1042 src/slic3r/GUI/Tab.cpp:1140
 #: src/slic3r/GUI/Tab.cpp:1143 src/slic3r/GUI/Tab.cpp:1516
-#: src/slic3r/GUI/Tab.cpp:1941 src/slic3r/GUI/Tab.cpp:3440
+#: src/slic3r/GUI/Tab.cpp:1941 src/slic3r/GUI/Tab.cpp:3453
 #: src/slic3r/GUI/wxExtensions.cpp:2510 src/libslic3r/PrintConfig.cpp:73
 #: src/libslic3r/PrintConfig.cpp:188 src/libslic3r/PrintConfig.cpp:351
 #: src/libslic3r/PrintConfig.cpp:989 src/libslic3r/PrintConfig.cpp:2200
@@ -1134,10 +1167,10 @@ msgid "&Configuration"
 msgstr ""
 
 #: src/slic3r/GUI/GUI_App.cpp:801
-msgid "The following presets were modified: "
+msgid "The following presets were modified"
 msgstr ""
 
-#: src/slic3r/GUI/GUI_App.cpp:801 src/slic3r/GUI/Tab.cpp:2785
+#: src/slic3r/GUI/GUI_App.cpp:801 src/slic3r/GUI/Tab.cpp:2798
 msgid "Discard changes and continue anyway?"
 msgstr ""
 
@@ -1235,8 +1268,8 @@ msgid "Extrusion Width"
 msgstr ""
 
 #: src/slic3r/GUI/GUI_ObjectList.cpp:87 src/slic3r/GUI/GUI_ObjectList.cpp:541
-#: src/slic3r/GUI/Plater.cpp:429 src/slic3r/GUI/Tab.cpp:3402
-#: src/slic3r/GUI/Tab.cpp:3403 src/libslic3r/PrintConfig.cpp:2388
+#: src/slic3r/GUI/Plater.cpp:429 src/slic3r/GUI/Tab.cpp:3415
+#: src/slic3r/GUI/Tab.cpp:3416 src/libslic3r/PrintConfig.cpp:2388
 #: src/libslic3r/PrintConfig.cpp:2395 src/libslic3r/PrintConfig.cpp:2404
 #: src/libslic3r/PrintConfig.cpp:2413 src/libslic3r/PrintConfig.cpp:2423
 #: src/libslic3r/PrintConfig.cpp:2449 src/libslic3r/PrintConfig.cpp:2456
@@ -1248,7 +1281,7 @@ msgid "Supports"
 msgstr ""
 
 #: src/slic3r/GUI/GUI_ObjectList.cpp:88 src/slic3r/GUI/GUI_ObjectList.cpp:542
-#: src/slic3r/GUI/Tab.cpp:3430 src/slic3r/GUI/Tab.cpp:3431
+#: src/slic3r/GUI/Tab.cpp:3443 src/slic3r/GUI/Tab.cpp:3444
 #: src/libslic3r/PrintConfig.cpp:2541 src/libslic3r/PrintConfig.cpp:2548
 #: src/libslic3r/PrintConfig.cpp:2562 src/libslic3r/PrintConfig.cpp:2572
 #: src/libslic3r/PrintConfig.cpp:2585 src/libslic3r/PrintConfig.cpp:2594
@@ -1355,7 +1388,7 @@ msgstr ""
 msgid "Fix through the Netfabb"
 msgstr ""
 
-#: src/slic3r/GUI/GUI_ObjectList.cpp:1231 src/slic3r/GUI/Plater.cpp:2944
+#: src/slic3r/GUI/GUI_ObjectList.cpp:1231 src/slic3r/GUI/Plater.cpp:2969
 msgid "Export as STL"
 msgstr ""
 
@@ -1383,7 +1416,7 @@ msgstr ""
 msgid "You can't delete the last intance from object."
 msgstr ""
 
-#: src/slic3r/GUI/GUI_ObjectList.cpp:1742 src/slic3r/GUI/Plater.cpp:2290
+#: src/slic3r/GUI/GUI_ObjectList.cpp:1742 src/slic3r/GUI/Plater.cpp:2306
 msgid ""
 "The selected object couldn't be split because it contains only one part."
 msgstr ""
@@ -1460,13 +1493,13 @@ msgid "Renaming"
 msgstr ""
 
 #: src/slic3r/GUI/GUI_ObjectList.cpp:2730
-#: src/slic3r/GUI/GUI_ObjectList.cpp:2824 src/slic3r/GUI/Tab.cpp:3283
-#: src/slic3r/GUI/Tab.cpp:3287
+#: src/slic3r/GUI/GUI_ObjectList.cpp:2824 src/slic3r/GUI/Tab.cpp:3296
+#: src/slic3r/GUI/Tab.cpp:3300
 msgid "The supplied name is not valid;"
 msgstr ""
 
 #: src/slic3r/GUI/GUI_ObjectList.cpp:2731
-#: src/slic3r/GUI/GUI_ObjectList.cpp:2825 src/slic3r/GUI/Tab.cpp:3284
+#: src/slic3r/GUI/GUI_ObjectList.cpp:2825 src/slic3r/GUI/Tab.cpp:3297
 msgid "the following characters are not allowed:"
 msgstr ""
 
@@ -1668,7 +1701,7 @@ msgid "Load Config from .ini/amf/3mf/gcode"
 msgstr ""
 
 #: src/slic3r/GUI/KBShortcutsDialog.cpp:108 src/slic3r/GUI/Plater.cpp:740
-#: src/slic3r/GUI/Plater.cpp:3839 src/libslic3r/PrintConfig.cpp:2990
+#: src/slic3r/GUI/Plater.cpp:3864 src/libslic3r/PrintConfig.cpp:2990
 msgid "Export G-code"
 msgstr ""
 
@@ -2161,8 +2194,13 @@ msgid "Iso View"
 msgstr ""
 
 #. TRN To be shown in the main menu View->Top
+#: src/slic3r/GUI/MainFrame.cpp:527
+msgctxt "Layers"
+msgid "Top"
+msgstr ""
+
 #. TRN To be shown in Print Settings "Top solid layers"
-#: src/slic3r/GUI/MainFrame.cpp:527 src/libslic3r/PrintConfig.cpp:2068
+#: src/libslic3r/PrintConfig.cpp:2068
 msgid "Top"
 msgstr ""
 
@@ -2171,8 +2209,13 @@ msgid "Top View"
 msgstr ""
 
 #. TRN To be shown in the main menu View->Bottom
+#: src/slic3r/GUI/MainFrame.cpp:529
+msgid "Bottom"
+msgstr ""
+
 #. TRN To be shown in Print Settings "Bottom solid layers"
-#: src/slic3r/GUI/MainFrame.cpp:529 src/libslic3r/PrintConfig.cpp:150
+#: src/libslic3r/PrintConfig.cpp:150
+msgctxt "Layers"
 msgid "Bottom"
 msgstr ""
 
@@ -2306,7 +2349,7 @@ msgstr ""
 msgid "&Help"
 msgstr ""
 
-#: src/slic3r/GUI/MainFrame.cpp:607 src/slic3r/GUI/Plater.cpp:3839
+#: src/slic3r/GUI/MainFrame.cpp:607 src/slic3r/GUI/Plater.cpp:3864
 msgid "Export"
 msgstr ""
 
@@ -2338,7 +2381,7 @@ msgstr ""
 msgid "File Not Found"
 msgstr ""
 
-#: src/slic3r/GUI/MainFrame.cpp:686 src/slic3r/GUI/Tab.cpp:3244
+#: src/slic3r/GUI/MainFrame.cpp:686 src/slic3r/GUI/Tab.cpp:3257
 msgid "Save "
 msgstr ""
 
@@ -2358,9 +2401,9 @@ msgstr ""
 msgid "Save zip file as:"
 msgstr ""
 
-#: src/slic3r/GUI/MainFrame.cpp:713 src/slic3r/GUI/Plater.cpp:2423
-#: src/slic3r/GUI/Plater.cpp:3633 src/slic3r/GUI/Tab.cpp:1160
-#: src/slic3r/GUI/Tab.cpp:3441
+#: src/slic3r/GUI/MainFrame.cpp:713 src/slic3r/GUI/Plater.cpp:2439
+#: src/slic3r/GUI/Plater.cpp:3658 src/slic3r/GUI/Tab.cpp:1160
+#: src/slic3r/GUI/Tab.cpp:3454
 msgid "Slicing"
 msgstr ""
 
@@ -2525,12 +2568,12 @@ msgstr ""
 msgid "Printer"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:738 src/slic3r/GUI/Plater.cpp:3840
+#: src/slic3r/GUI/Plater.cpp:738 src/slic3r/GUI/Plater.cpp:3865
 msgid "Send to printer"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:741 src/slic3r/GUI/Plater.cpp:2423
-#: src/slic3r/GUI/Plater.cpp:3636
+#: src/slic3r/GUI/Plater.cpp:741 src/slic3r/GUI/Plater.cpp:2439
+#: src/slic3r/GUI/Plater.cpp:3661
 msgid "Slice now"
 msgstr ""
 
@@ -2587,286 +2630,286 @@ msgstr ""
 msgid "stealth mode"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1601
+#: src/slic3r/GUI/Plater.cpp:1604
 msgid "Loading"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1611
+#: src/slic3r/GUI/Plater.cpp:1614
 #, possible-c-format
 msgid "Processing input file %s\n"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1669
+#: src/slic3r/GUI/Plater.cpp:1672
 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 ""
 
-#: src/slic3r/GUI/Plater.cpp:1672 src/slic3r/GUI/Plater.cpp:1780
+#: src/slic3r/GUI/Plater.cpp:1675 src/slic3r/GUI/Plater.cpp:1783
 msgid "Multi-part object detected"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1723
+#: src/slic3r/GUI/Plater.cpp:1726
 msgid ""
 "This file cannot be loaded in a simple mode. Do you want to switch to an "
 "advanced mode?\n"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1724
+#: src/slic3r/GUI/Plater.cpp:1727
 msgid "Detected advanced data"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1757
+#: src/slic3r/GUI/Plater.cpp:1760
 #, possible-c-format
 msgid ""
 "You can't to add the object(s) from %s because of one or some of them "
 "is(are) multi-part"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1777
+#: src/slic3r/GUI/Plater.cpp:1780
 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 ""
 
-#: src/slic3r/GUI/Plater.cpp:1793
+#: src/slic3r/GUI/Plater.cpp:1796
 msgid "Loaded"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1885
+#: src/slic3r/GUI/Plater.cpp:1894
 msgid ""
 "Your object appears to be too large, so it was automatically scaled down to "
 "fit your print bed."
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1886
+#: src/slic3r/GUI/Plater.cpp:1895
 msgid "Object too large?"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1936
+#: src/slic3r/GUI/Plater.cpp:1945
 msgid "Export STL file:"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1943
+#: src/slic3r/GUI/Plater.cpp:1952
 msgid "Export AMF file:"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:1949
+#: src/slic3r/GUI/Plater.cpp:1958
 msgid "Save file as:"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2114
+#: src/slic3r/GUI/Plater.cpp:2123
 msgid "Arranging canceled"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2117
+#: src/slic3r/GUI/Plater.cpp:2126
 msgid "Arranging"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2151
+#: src/slic3r/GUI/Plater.cpp:2163
 msgid "Could not arrange model objects! Some geometries may be invalid."
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2155
+#: src/slic3r/GUI/Plater.cpp:2170
 msgid "Arranging done."
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2196
+#: src/slic3r/GUI/Plater.cpp:2211
 msgid "Orientation search canceled"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2201
+#: src/slic3r/GUI/Plater.cpp:2216
 msgid "Searching for optimal orientation"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2262
+#: src/slic3r/GUI/Plater.cpp:2278
 msgid "Orientation found."
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2282
+#: src/slic3r/GUI/Plater.cpp:2298
 msgid ""
 "The selected object can't be split because it contains more than one volume/"
 "material."
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2408
+#: src/slic3r/GUI/Plater.cpp:2424
 msgid "Invalid data"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2417
+#: src/slic3r/GUI/Plater.cpp:2433
 msgid "Ready to slice"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2455 src/slic3r/GUI/PrintHostDialogs.cpp:231
+#: src/slic3r/GUI/Plater.cpp:2471 src/slic3r/GUI/PrintHostDialogs.cpp:231
 msgid "Cancelling"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2472
+#: src/slic3r/GUI/Plater.cpp:2488
 msgid "Another export job is currently running."
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2733
+#: src/slic3r/GUI/Plater.cpp:2749
 msgid "Export failed"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2738 src/slic3r/GUI/PrintHostDialogs.cpp:232
+#: src/slic3r/GUI/Plater.cpp:2754 src/slic3r/GUI/PrintHostDialogs.cpp:232
 msgid "Cancelled"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2824 src/slic3r/GUI/Plater.cpp:2836
-#: src/slic3r/GUI/Plater.cpp:2914
+#: src/slic3r/GUI/Plater.cpp:2840 src/slic3r/GUI/Plater.cpp:2852
+#: src/slic3r/GUI/Plater.cpp:2939
 msgid "Increase copies"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2908 src/slic3r/GUI/Plater.cpp:2926
+#: src/slic3r/GUI/Plater.cpp:2933 src/slic3r/GUI/Plater.cpp:2951
 msgid "Remove the selected object"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2914
+#: src/slic3r/GUI/Plater.cpp:2939
 msgid "Place one more copy of the selected object"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2916
+#: src/slic3r/GUI/Plater.cpp:2941
 msgid "Decrease copies"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2916
+#: src/slic3r/GUI/Plater.cpp:2941
 msgid "Remove one copy of the selected object"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2918
+#: src/slic3r/GUI/Plater.cpp:2943
 msgid "Set number of copies"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2918
+#: src/slic3r/GUI/Plater.cpp:2943
 msgid "Change the number of copies of the selected object"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2941
+#: src/slic3r/GUI/Plater.cpp:2966
 msgid "Reload from Disk"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2941
+#: src/slic3r/GUI/Plater.cpp:2966
 msgid "Reload the selected file from Disk"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2944
+#: src/slic3r/GUI/Plater.cpp:2969
 msgid "Export the selected object as STL file"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2956
+#: src/slic3r/GUI/Plater.cpp:2981
 msgid "Along X axis"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2956
+#: src/slic3r/GUI/Plater.cpp:2981
 msgid "Mirror the selected object along the X axis"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2958
+#: src/slic3r/GUI/Plater.cpp:2983
 msgid "Along Y axis"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2958
+#: src/slic3r/GUI/Plater.cpp:2983
 msgid "Mirror the selected object along the Y axis"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2960
+#: src/slic3r/GUI/Plater.cpp:2985
 msgid "Along Z axis"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2960
+#: src/slic3r/GUI/Plater.cpp:2985
 msgid "Mirror the selected object along the Z axis"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2963
+#: src/slic3r/GUI/Plater.cpp:2988
 msgid "Mirror"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2963
+#: src/slic3r/GUI/Plater.cpp:2988
 msgid "Mirror the selected object"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2983
+#: src/slic3r/GUI/Plater.cpp:3008
 msgid "To objects"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2983 src/slic3r/GUI/Plater.cpp:3005
+#: src/slic3r/GUI/Plater.cpp:3008 src/slic3r/GUI/Plater.cpp:3030
 msgid "Split the selected object into individual objects"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2985
+#: src/slic3r/GUI/Plater.cpp:3010
 msgid "To parts"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2985 src/slic3r/GUI/Plater.cpp:3025
+#: src/slic3r/GUI/Plater.cpp:3010 src/slic3r/GUI/Plater.cpp:3050
 msgid "Split the selected object into individual sub-parts"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2988 src/slic3r/GUI/Plater.cpp:3005
-#: src/slic3r/GUI/Plater.cpp:3025 src/libslic3r/PrintConfig.cpp:3108
+#: src/slic3r/GUI/Plater.cpp:3013 src/slic3r/GUI/Plater.cpp:3030
+#: src/slic3r/GUI/Plater.cpp:3050 src/libslic3r/PrintConfig.cpp:3108
 msgid "Split"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:2988
+#: src/slic3r/GUI/Plater.cpp:3013
 msgid "Split the selected object"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3011
+#: src/slic3r/GUI/Plater.cpp:3036
 msgid "Optimize orientation"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3011
+#: src/slic3r/GUI/Plater.cpp:3036
 msgid "Optimize the rotation of the object for better print results."
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3074
+#: src/slic3r/GUI/Plater.cpp:3099
 msgid "3D editor view"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3085 src/slic3r/GUI/Tab.cpp:2289
+#: src/slic3r/GUI/Plater.cpp:3110 src/slic3r/GUI/Tab.cpp:2289
 msgid "Preview"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3316
+#: src/slic3r/GUI/Plater.cpp:3341
 msgid "All objects will be removed, continue ?"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3451
+#: src/slic3r/GUI/Plater.cpp:3476
 msgid "Save G-code file as:"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3451
+#: src/slic3r/GUI/Plater.cpp:3476
 msgid "Save SL1 file as:"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3563
+#: src/slic3r/GUI/Plater.cpp:3588
 #, possible-c-format
 msgid "STL file exported to %s"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3579
+#: src/slic3r/GUI/Plater.cpp:3604
 #, possible-c-format
 msgid "AMF file exported to %s"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3582
+#: src/slic3r/GUI/Plater.cpp:3607
 #, possible-c-format
 msgid "Error exporting AMF file %s"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3608
+#: src/slic3r/GUI/Plater.cpp:3633
 #, possible-c-format
 msgid "3MF file exported to %s"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3611
+#: src/slic3r/GUI/Plater.cpp:3636
 #, possible-c-format
 msgid "Error exporting 3MF file %s"
 msgstr ""
 
-#: src/slic3r/GUI/Plater.cpp:3840
+#: src/slic3r/GUI/Plater.cpp:3865
 msgid "Send G-code"
 msgstr ""
 
@@ -2982,7 +3025,7 @@ msgstr ""
 msgid "Add a new printer"
 msgstr ""
 
-#: src/slic3r/GUI/Preset.cpp:1275
+#: src/slic3r/GUI/Preset.cpp:1275 src/slic3r/GUI/Tab.hpp:333
 msgid "filament"
 msgstr ""
 
@@ -3284,7 +3327,7 @@ msgstr ""
 msgid "default SLA print profile"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:998 src/slic3r/GUI/Tab.cpp:3396
+#: src/slic3r/GUI/Tab.cpp:998 src/slic3r/GUI/Tab.cpp:3409
 msgid "Layers and perimeters"
 msgstr ""
 
@@ -3368,7 +3411,7 @@ msgstr ""
 msgid "Other"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:1169 src/slic3r/GUI/Tab.cpp:3444
+#: src/slic3r/GUI/Tab.cpp:1169 src/slic3r/GUI/Tab.cpp:3457
 msgid "Output options"
 msgstr ""
 
@@ -3380,7 +3423,7 @@ msgstr ""
 msgid "Extruder clearance (mm)"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:1181 src/slic3r/GUI/Tab.cpp:3445
+#: src/slic3r/GUI/Tab.cpp:1181 src/slic3r/GUI/Tab.cpp:3458
 msgid "Output file"
 msgstr ""
 
@@ -3392,19 +3435,19 @@ msgstr ""
 #: src/slic3r/GUI/Tab.cpp:1577 src/slic3r/GUI/Tab.cpp:1578
 #: src/slic3r/GUI/Tab.cpp:1986 src/slic3r/GUI/Tab.cpp:1987
 #: src/slic3r/GUI/Tab.cpp:2080 src/slic3r/GUI/Tab.cpp:2081
-#: src/slic3r/GUI/Tab.cpp:3333 src/slic3r/GUI/Tab.cpp:3334
+#: src/slic3r/GUI/Tab.cpp:3346 src/slic3r/GUI/Tab.cpp:3347
 msgid "Notes"
 msgstr ""
 
 #: src/slic3r/GUI/Tab.cpp:1201 src/slic3r/GUI/Tab.cpp:1585
 #: src/slic3r/GUI/Tab.cpp:1993 src/slic3r/GUI/Tab.cpp:2087
-#: src/slic3r/GUI/Tab.cpp:3341 src/slic3r/GUI/Tab.cpp:3450
+#: src/slic3r/GUI/Tab.cpp:3354 src/slic3r/GUI/Tab.cpp:3463
 msgid "Dependencies"
 msgstr ""
 
 #: src/slic3r/GUI/Tab.cpp:1202 src/slic3r/GUI/Tab.cpp:1586
 #: src/slic3r/GUI/Tab.cpp:1994 src/slic3r/GUI/Tab.cpp:2088
-#: src/slic3r/GUI/Tab.cpp:3342 src/slic3r/GUI/Tab.cpp:3451
+#: src/slic3r/GUI/Tab.cpp:3355 src/slic3r/GUI/Tab.cpp:3464
 msgid "Profile dependencies"
 msgstr ""
 
@@ -3576,7 +3619,7 @@ msgid "Size and coordinates"
 msgstr ""
 
 #: src/slic3r/GUI/Tab.cpp:1819 src/slic3r/GUI/Tab.cpp:2020
-#: src/slic3r/GUI/Tab.cpp:2989
+#: src/slic3r/GUI/Tab.cpp:3002
 msgid " Set "
 msgstr ""
 
@@ -3640,7 +3683,7 @@ msgstr ""
 msgid "Tilt time"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2060 src/slic3r/GUI/Tab.cpp:3315
+#: src/slic3r/GUI/Tab.cpp:2060 src/slic3r/GUI/Tab.cpp:3328
 msgid "Corrections"
 msgstr ""
 
@@ -3719,104 +3762,104 @@ msgid ""
 "setups)"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2430
+#: src/slic3r/GUI/Tab.cpp:2443
 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 ""
 
-#: src/slic3r/GUI/Tab.cpp:2432
+#: src/slic3r/GUI/Tab.cpp:2445
 msgid "Firmware Retraction"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2758
+#: src/slic3r/GUI/Tab.cpp:2771
 #, possible-c-format
 msgid "Default preset (%s)"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2759
+#: src/slic3r/GUI/Tab.cpp:2772
 #, possible-c-format
 msgid "Preset (%s)"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2776
+#: src/slic3r/GUI/Tab.cpp:2789
 msgid "has the following unsaved changes:"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2779
+#: src/slic3r/GUI/Tab.cpp:2792
 msgid "is not compatible with printer"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2780
+#: src/slic3r/GUI/Tab.cpp:2793
 msgid "is not compatible with print profile"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2782
+#: src/slic3r/GUI/Tab.cpp:2795
 msgid "and it has the following unsaved changes:"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2786
+#: src/slic3r/GUI/Tab.cpp:2799
 msgid "Unsaved Changes"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2798
+#: src/slic3r/GUI/Tab.cpp:2811
 msgid "Please check your object list before preset changing."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2901
+#: src/slic3r/GUI/Tab.cpp:2914
 msgid "The supplied name is empty. It can't be saved."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2906
+#: src/slic3r/GUI/Tab.cpp:2919
 msgid "Cannot overwrite a system profile."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2910
+#: src/slic3r/GUI/Tab.cpp:2923
 msgid "Cannot overwrite an external profile."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2936
+#: src/slic3r/GUI/Tab.cpp:2949
 msgid "remove"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2936
+#: src/slic3r/GUI/Tab.cpp:2949
 msgid "delete"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2937
+#: src/slic3r/GUI/Tab.cpp:2950
 msgid "Are you sure you want to "
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2937
+#: src/slic3r/GUI/Tab.cpp:2950
 msgid " the selected preset?"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2938
+#: src/slic3r/GUI/Tab.cpp:2951
 msgid "Remove"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:2939
+#: src/slic3r/GUI/Tab.cpp:2952
 msgid " Preset"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3065
+#: src/slic3r/GUI/Tab.cpp:3078
 msgid "LOCKED LOCK"
 msgstr ""
 
 #. TRN Description for "LOCKED LOCK"
-#: src/slic3r/GUI/Tab.cpp:3067
+#: src/slic3r/GUI/Tab.cpp:3080
 msgid ""
 "indicates that the settings are the same as the system values for the "
 "current option group"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3069
+#: src/slic3r/GUI/Tab.cpp:3082
 msgid "UNLOCKED LOCK"
 msgstr ""
 
 #. TRN Description for "UNLOCKED LOCK"
-#: src/slic3r/GUI/Tab.cpp:3071
+#: src/slic3r/GUI/Tab.cpp:3084
 msgid ""
 "indicates that some settings were changed and are not equal to the system "
 "values for the current option group.\n"
@@ -3824,23 +3867,23 @@ msgid ""
 "to the system values."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3076
+#: src/slic3r/GUI/Tab.cpp:3089
 msgid "WHITE BULLET"
 msgstr ""
 
 #. TRN Description for "WHITE BULLET"
-#: src/slic3r/GUI/Tab.cpp:3078
+#: src/slic3r/GUI/Tab.cpp:3091
 msgid ""
 "for the left button: \tindicates a non-system preset,\n"
 "for the right button: \tindicates that the settings hasn't been modified."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3081
+#: src/slic3r/GUI/Tab.cpp:3094
 msgid "BACK ARROW"
 msgstr ""
 
 #. TRN Description for "BACK ARROW"
-#: src/slic3r/GUI/Tab.cpp:3083
+#: src/slic3r/GUI/Tab.cpp:3096
 msgid ""
 "indicates that the settings were changed and are not equal to the last saved "
 "preset for the current option group.\n"
@@ -3848,30 +3891,30 @@ msgid ""
 "to the last saved preset."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3108
+#: src/slic3r/GUI/Tab.cpp:3121
 msgid ""
 "LOCKED LOCK icon indicates that the settings are the same as the system "
 "values for the current option group"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3110
+#: src/slic3r/GUI/Tab.cpp:3123
 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 ""
 
-#: src/slic3r/GUI/Tab.cpp:3113
+#: src/slic3r/GUI/Tab.cpp:3126
 msgid "WHITE BULLET icon indicates a non system preset."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3116
+#: src/slic3r/GUI/Tab.cpp:3129
 msgid ""
 "WHITE BULLET icon indicates that the settings are the same as in the last "
 "saved preset for the current option group."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3118
+#: src/slic3r/GUI/Tab.cpp:3131
 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"
@@ -3879,84 +3922,84 @@ msgid ""
 "preset."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3124
+#: src/slic3r/GUI/Tab.cpp:3137
 msgid ""
 "LOCKED LOCK icon indicates that the value is the same as the system value."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3125
+#: src/slic3r/GUI/Tab.cpp:3138
 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 ""
 
-#: src/slic3r/GUI/Tab.cpp:3131
+#: src/slic3r/GUI/Tab.cpp:3144
 msgid ""
 "WHITE BULLET icon indicates that the value is the same as in the last saved "
 "preset."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3132
+#: src/slic3r/GUI/Tab.cpp:3145
 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 ""
 
-#: src/slic3r/GUI/Tab.cpp:3244
+#: src/slic3r/GUI/Tab.cpp:3257
 msgid " as:"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3288
+#: src/slic3r/GUI/Tab.cpp:3301
 msgid "the following postfix are not allowed:"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3292
+#: src/slic3r/GUI/Tab.cpp:3305
 msgid "The supplied name is not available."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3305
+#: src/slic3r/GUI/Tab.cpp:3318
 msgid "Material"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3307 src/slic3r/GUI/Tab.cpp:3398
+#: src/slic3r/GUI/Tab.cpp:3320 src/slic3r/GUI/Tab.cpp:3411
 msgid "Layers"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3311
+#: src/slic3r/GUI/Tab.cpp:3324
 msgid "Exposure"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3406
+#: src/slic3r/GUI/Tab.cpp:3419
 msgid "Support head"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3411
+#: src/slic3r/GUI/Tab.cpp:3424
 msgid "Support pillar"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3421
+#: src/slic3r/GUI/Tab.cpp:3434
 msgid "Connection of the support sticks and junctions"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3426
+#: src/slic3r/GUI/Tab.cpp:3439
 msgid "Automatic generation"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3488
+#: src/slic3r/GUI/Tab.cpp:3501
 msgid "Head penetration should not be greater than the head width."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3489
+#: src/slic3r/GUI/Tab.cpp:3502
 msgid "Invalid Head penetration"
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3501
+#: src/slic3r/GUI/Tab.cpp:3514
 msgid "Pinhead diameter should be smaller than the pillar diameter."
 msgstr ""
 
-#: src/slic3r/GUI/Tab.cpp:3502
+#: src/slic3r/GUI/Tab.cpp:3515
 msgid "Invalid pinhead diameter"
 msgstr ""
 
@@ -3976,6 +4019,14 @@ msgstr ""
 msgid "Material Settings"
 msgstr ""
 
+#: src/slic3r/GUI/Tab.hpp:389
+msgid "sla_material"
+msgstr ""
+
+#: src/slic3r/GUI/Tab.hpp:403
+msgid "sla_print"
+msgstr ""
+
 #: src/slic3r/GUI/Tab.hpp:415
 msgid "Save preset"
 msgstr ""
@@ -4803,6 +4854,7 @@ msgstr ""
 #: src/libslic3r/PrintConfig.cpp:1595 src/libslic3r/PrintConfig.cpp:1605
 #: src/libslic3r/PrintConfig.cpp:1833 src/libslic3r/PrintConfig.cpp:1987
 #: src/libslic3r/PrintConfig.cpp:2171 src/libslic3r/PrintConfig.cpp:2488
+#: src/libslic3r/PrintConfig.cpp:2597
 msgid "°"
 msgstr ""
 
@@ -7288,10 +7340,6 @@ msgid ""
 "straight walls."
 msgstr ""
 
-#: src/libslic3r/PrintConfig.cpp:2597
-msgid "degrees"
-msgstr ""
-
 #: src/libslic3r/PrintConfig.cpp:2957
 msgid "Export OBJ"
 msgstr ""
@@ -7545,6 +7593,22 @@ msgid ""
 "loaded instead of the default OpenGL driver."
 msgstr ""
 
+#: src/libslic3r/PrintObject.cpp:110
+msgid "Processing triangulated mesh"
+msgstr ""
+
+#: src/libslic3r/PrintObject.cpp:141
+msgid "Generating perimeters"
+msgstr ""
+
+#: src/libslic3r/PrintObject.cpp:251
+msgid "Preparing infill"
+msgstr ""
+
+#: src/libslic3r/PrintObject.cpp:391
+msgid "Generating support material"
+msgstr ""
+
 #: src/libslic3r/GCode/PreviewData.cpp:176
 msgid "Mixed"
 msgstr ""
diff --git a/resources/localization/list.txt b/resources/localization/list.txt
index cf6ca4c84..fdffaf9d9 100644
--- a/resources/localization/list.txt
+++ b/resources/localization/list.txt
@@ -1,4 +1,5 @@
 src/slic3r/GUI/AboutDialog.cpp
+src/slic3r/GUI/BackgroundSlicingProcess.cpp
 src/slic3r/GUI/BedShapeDialog.cpp
 src/slic3r/GUI/BedShapeDialog.hpp
 src/slic3r/GUI/BonjourDialog.cpp
@@ -47,4 +48,5 @@ src/libslic3r/Print.cpp
 src/libslic3r/SLAPrint.cpp
 src/libslic3r/PrintBase.cpp
 src/libslic3r/PrintConfig.cpp
+src/libslic3r/PrintObject.cpp
 src/libslic3r/GCode/PreviewData.cpp
diff --git a/src/libslic3r/ModelArrange.cpp b/src/libslic3r/ModelArrange.cpp
index c821eef77..18a2d08c4 100644
--- a/src/libslic3r/ModelArrange.cpp
+++ b/src/libslic3r/ModelArrange.cpp
@@ -539,7 +539,7 @@ public:
 // 2D shape from top view.
 using ShapeData2D = std::vector<std::pair<Slic3r::ModelInstance*, Item>>;
 
-ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
+ShapeData2D projectModelFromTop(const Slic3r::Model &model, const WipeTowerInfo& wti) {
     ShapeData2D ret;
 
     // Count all the items on the bin (all the object's instances)
@@ -600,6 +600,28 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
         }
     }
 
+    // The wipe tower is a separate case (in case there is one), let's duplicate the code
+    if (wti.is_wipe_tower) {
+        Points pts;
+        pts.emplace_back(coord_t(scale_(0.)), coord_t(scale_(0.)));
+        pts.emplace_back(coord_t(scale_(wti.bb_size(0))), coord_t(scale_(0.)));
+        pts.emplace_back(coord_t(scale_(wti.bb_size(0))), coord_t(scale_(wti.bb_size(1))));
+        pts.emplace_back(coord_t(scale_(-0.)), coord_t(scale_(wti.bb_size(1))));
+        pts.emplace_back(coord_t(scale_(-0.)), coord_t(scale_(0.)));
+        Polygon p(std::move(pts));
+        ClipperLib::Path clpath = Slic3rMultiPoint_to_ClipperPath(p);
+        ClipperLib::Polygon pn;
+        pn.Contour = clpath;
+        // Efficient conversion to item.
+        Item item(std::move(pn));
+        item.rotation(wti.rotation),
+        item.translation({
+        ClipperLib::cInt(wti.pos(0)/SCALING_FACTOR),
+        ClipperLib::cInt(wti.pos(1)/SCALING_FACTOR)
+        });
+        ret.emplace_back(nullptr, item);
+    }
+
     return ret;
 }
 
@@ -608,7 +630,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
 void applyResult(
         IndexedPackGroup::value_type& group,
         Coord batch_offset,
-        ShapeData2D& shapemap)
+        ShapeData2D& shapemap,
+        WipeTowerInfo& wti)
 {
     for(auto& r : group) {
         auto idx = r.first;     // get the original item index
@@ -617,18 +640,25 @@ void applyResult(
         // Get the model instance from the shapemap using the index
         ModelInstance *inst_ptr = shapemap[idx].first;
 
-        // Get the transformation data from the item object and scale it
-        // appropriately
-        auto off = item.translation();
-        Radians rot = item.rotation();
+            // Get the transformation data from the item object and scale it
+            // appropriately
+            auto off = item.translation();
+            Radians rot = item.rotation();
 
-        Vec3d foff(off.X*SCALING_FACTOR + batch_offset,
-                   off.Y*SCALING_FACTOR,
-                   inst_ptr->get_offset()(Z));
+            Vec3d foff(off.X*SCALING_FACTOR + batch_offset,
+                       off.Y*SCALING_FACTOR,
+                       inst_ptr ? inst_ptr->get_offset()(Z) : 0.);
 
-        // write the transformation data into the model instance
-        inst_ptr->set_rotation(Z, rot);
-        inst_ptr->set_offset(foff);
+        if (inst_ptr) {
+            // write the transformation data into the model instance
+            inst_ptr->set_rotation(Z, rot);
+            inst_ptr->set_offset(foff);
+        }
+        else { // this is the wipe tower - we will modify the struct with the info
+               // and leave it up to the called to actually move the wipe tower
+            wti.pos = Vec2d(foff(0), foff(1));
+            wti.rotation = rot;
+        }
     }
 }
 
@@ -714,6 +744,7 @@ BedShapeHint bedShape(const Polyline &bed) {
 // The final client function to arrange the Model. A progress indicator and
 // a stop predicate can be also be passed to control the process.
 bool arrange(Model &model,              // The model with the geometries
+             WipeTowerInfo& wti,        // Wipe tower info
              coord_t min_obj_distance,  // Has to be in scaled (clipper) measure
              const Polyline &bed,       // The bed geometry.
              BedShapeHint bedhint,      // Hint about the bed geometry type.
@@ -726,7 +757,7 @@ bool arrange(Model &model,              // The model with the geometries
     bool ret = true;
 
     // Get the 2D projected shapes with their 3D model instance pointers
-    auto shapemap = arr::projectModelFromTop(model);
+    auto shapemap = arr::projectModelFromTop(model, wti);
 
     // Copy the references for the shapes only as the arranger expects a
     // sequence of objects convertible to Item or ClipperPolygon
@@ -796,7 +827,7 @@ bool arrange(Model &model,              // The model with the geometries
     if(result.empty() || stopcondition()) return false;
 
     if(first_bin_only) {
-        applyResult(result.front(), 0, shapemap);
+        applyResult(result.front(), 0, shapemap, wti);
     } else {
 
         const auto STRIDE_PADDING = 1.2;
@@ -806,7 +837,7 @@ bool arrange(Model &model,              // The model with the geometries
         Coord batch_offset = 0;
 
         for(auto& group : result) {
-            applyResult(group, batch_offset, shapemap);
+            applyResult(group, batch_offset, shapemap, wti);
 
             // 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
@@ -823,10 +854,11 @@ bool arrange(Model &model,              // The model with the geometries
 void find_new_position(const Model &model,
                        ModelInstancePtrs toadd,
                        coord_t min_obj_distance,
-                       const Polyline &bed)
+                       const Polyline &bed,
+                       WipeTowerInfo& wti)
 {
     // Get the 2D projected shapes with their 3D model instance pointers
-    auto shapemap = arr::projectModelFromTop(model);
+    auto shapemap = arr::projectModelFromTop(model, wti);
 
     // Copy the references for the shapes only as the arranger expects a
     // sequence of objects convertible to Item or ClipperPolygon
diff --git a/src/libslic3r/ModelArrange.hpp b/src/libslic3r/ModelArrange.hpp
index d76769081..b61443da0 100644
--- a/src/libslic3r/ModelArrange.hpp
+++ b/src/libslic3r/ModelArrange.hpp
@@ -40,6 +40,13 @@ struct BedShapeHint {
 
 BedShapeHint bedShape(const Polyline& bed);
 
+struct WipeTowerInfo {
+    bool is_wipe_tower = false;
+    Vec2d pos;
+    Vec2d bb_size;
+    double rotation;
+};
+
 /**
  * \brief Arranges the model objects on the screen.
  *
@@ -66,7 +73,9 @@ BedShapeHint bedShape(const Polyline& bed);
  * packed. The unsigned argument is the number of items remaining to pack.
  * \param stopcondition A predicate returning true if abort is needed.
  */
-bool arrange(Model &model, coord_t min_obj_distance,
+bool arrange(Model &model,
+             WipeTowerInfo& wipe_tower_info,
+             coord_t min_obj_distance,
              const Slic3r::Polyline& bed,
              BedShapeHint bedhint,
              bool first_bin_only,
@@ -78,7 +87,8 @@ bool arrange(Model &model, coord_t min_obj_distance,
 void find_new_position(const Model& model,
                        ModelInstancePtrs instances_to_add,
                        coord_t min_obj_distance,
-                       const Slic3r::Polyline& bed);
+                       const Slic3r::Polyline& bed,
+                       WipeTowerInfo& wti);
 
 }   // arr
 }   // Slic3r
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index 7e312cb23..59480de1c 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -716,12 +716,12 @@ int GLVolumeCollection::load_wipe_tower_preview(
     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();
     v.indexed_vertex_array.load_mesh(mesh, use_VBOs);
     v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
+    v.set_volume_rotation(Vec3d(0., 0., (M_PI/180.) * rotation_angle));
+
     // finalize_geometry() clears the vertex arrays, therefore the bounding box has to be computed before finalize_geometry().
     v.bounding_box = v.indexed_vertex_array.bounding_box();
     v.indexed_vertex_array.finalize_geometry(use_VBOs);
diff --git a/src/slic3r/GUI/ButtonsDescription.cpp b/src/slic3r/GUI/ButtonsDescription.cpp
index f9ab9b89c..0610199f5 100644
--- a/src/slic3r/GUI/ButtonsDescription.cpp
+++ b/src/slic3r/GUI/ButtonsDescription.cpp
@@ -26,9 +26,9 @@ ButtonsDescription::ButtonsDescription(wxWindow* parent, const std::vector<Entry
 	{
 		auto icon = new wxStaticBitmap(this, wxID_ANY, entry.bitmap->bmp());
 		grid_sizer->Add(icon, -1, wxALIGN_CENTRE_VERTICAL);
-		auto description = new wxStaticText(this, wxID_ANY, _utf8(entry.symbol));
+		auto description = new wxStaticText(this, wxID_ANY, _(entry.symbol));
 		grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL);
-		description = new wxStaticText(this, wxID_ANY, _utf8(entry.explanation));
+		description = new wxStaticText(this, wxID_ANY, _(entry.explanation));
 		grid_sizer->Add(description, -1, wxALIGN_CENTRE_VERTICAL | wxEXPAND);
 	}
 
diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp
index edc65aca0..9443f3658 100644
--- a/src/slic3r/GUI/Field.cpp
+++ b/src/slic3r/GUI/Field.cpp
@@ -15,7 +15,31 @@ namespace Slic3r { namespace GUI {
 
 wxString double_to_string(double const value, const int max_precision /*= 4*/)
 {
-	return wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_NoTrailingZeroes);
+// Style_NoTrailingZeroes does not work on OSX. It also does not work correctly with some locales on Windows.
+//	return wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_NoTrailingZeroes);
+
+	wxString s = wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_None);
+
+	// The following code comes from wxNumberFormatter::RemoveTrailingZeroes(wxString& s)
+	// with the exception that here one sets the decimal separator explicitely to dot.
+    // If number is in scientific format, trailing zeroes belong to the exponent and cannot be removed.
+    if (s.find_first_of("eE") == wxString::npos) {
+	    const size_t posDecSep = s.find(".");
+	    // No decimal point => removing trailing zeroes irrelevant for integer number.
+	    if (posDecSep != wxString::npos) {
+		    // Find the last character to keep.
+		    size_t posLastNonZero = s.find_last_not_of("0");
+		    // If it's the decimal separator itself, don't keep it neither.
+		    if (posLastNonZero == posDecSep)
+		        -- posLastNonZero;
+		    s.erase(posLastNonZero + 1);
+		    // Remove sign from orphaned zero.
+		    if (s.compare("-0") == 0)
+		        s = "0";
+		}
+	}
+
+    return s;
 }
 
 void Field::PostInitialize()
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index deb55c986..36581369c 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -16,6 +16,7 @@
 #include "slic3r/GUI/GLShader.hpp"
 #include "slic3r/GUI/GUI.hpp"
 #include "slic3r/GUI/PresetBundle.hpp"
+#include "slic3r/GUI/Tab.hpp"
 #include "GUI_App.hpp"
 #include "GUI_ObjectList.hpp"
 #include "GUI_ObjectManipulation.hpp"
@@ -716,13 +717,13 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool
     std::string text;
     bool red_colored = false;
     switch (m_warnings.back()) {
-        case ObjectOutside      : text = L("Detected object outside print volume"); break;
-        case ToolpathOutside    : text = L("Detected toolpath outside print volume"); break;
-        case SlaSupportsOutside : text = L("Detected support outside print volume"); break;
+        case ObjectOutside      : text = L("An object outside the print area was detected"); break;
+        case ToolpathOutside    : text = L("A toolpath outside the print area was detected"); break;
+        case SlaSupportsOutside : text = L("SLA supports outside the print area were detected"); break;
         case SomethingNotShown  : text = L("Some objects are not visible when editing supports"); break;
         case ObjectClashed: {
-            text = L("Detected object outside print volume\n"
-                     "Resolve a clash to continue slicing/export process correctly"); 
+            text = L("An object outside the print area was detected\n"
+                     "Resolve the current problem to continue slicing");
             red_colored = true;
             break;
         }
@@ -1202,6 +1203,7 @@ wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
 wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
 wxDEFINE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
 wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
+wxDEFINE_EVENT(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3dEvent);
 wxDEFINE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
 wxDEFINE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>);
 wxDEFINE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent);
@@ -2073,6 +2075,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
 	}
 
     m_gizmos.update_data(*this);
+    m_gizmos.refresh_on_off_state(m_selection);
 
     // Update the toolbar
 	if (update_object_list)
@@ -3115,6 +3118,10 @@ void GLCanvas3D::do_rotate()
     for (const GLVolume* v : m_volumes.volumes)
     {
         int object_idx = v->object_idx();
+        if (object_idx == 1000) { // the wipe tower
+            Vec3d offset = v->get_volume_offset();
+            post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset(0), offset(1), v->get_volume_rotation()(2))));
+        }
         if ((object_idx < 0) || ((int)m_model->objects.size() <= object_idx))
             continue;
 
@@ -3311,6 +3318,38 @@ void GLCanvas3D::update_ui_from_settings()
 #endif
 }
 
+
+
+arr::WipeTowerInfo GLCanvas3D::get_wipe_tower_info() const
+{
+    arr::WipeTowerInfo wti;
+    for (const GLVolume* vol : m_volumes.volumes) {
+        if (vol->is_wipe_tower) {
+            wti.is_wipe_tower = true;
+            wti.pos = Vec2d(m_config->opt_float("wipe_tower_x"),
+                            m_config->opt_float("wipe_tower_y"));
+            wti.rotation = (M_PI/180.) * m_config->opt_float("wipe_tower_rotation_angle");
+            const BoundingBoxf3& bb = vol->bounding_box;
+            wti.bb_size = Vec2d(bb.size()(0), bb.size()(1));
+            break;
+        }
+    }
+    return wti;
+}
+
+
+void GLCanvas3D::arrange_wipe_tower(const arr::WipeTowerInfo& wti) const
+{
+    if (wti.is_wipe_tower) {
+        DynamicPrintConfig cfg;
+        cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = wti.pos(0);
+        cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = wti.pos(1);
+        cfg.opt<ConfigOptionFloat>("wipe_tower_rotation_angle", true)->value = (180./M_PI) * wti.rotation;
+        wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg);
+    }
+}
+
+
 Linef3 GLCanvas3D::mouse_ray(const Point& mouse_pos)
 {
     float z0 = 0.0f;
@@ -4314,6 +4353,7 @@ void GLCanvas3D::_render_selection_sidebar_hints() const
         m_shader.stop_using();
 }
 
+
 void GLCanvas3D::_update_volumes_hover_state() const
 {
     for (GLVolume* v : m_volumes.volumes)
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 7edef2466..96b958cbf 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -4,6 +4,7 @@
 #include <stddef.h>
 #include <memory>
 
+#include "libslic3r/ModelArrange.hpp"
 #include "3DScene.hpp"
 #include "GLToolbar.hpp"
 #include "Event.hpp"
@@ -116,6 +117,7 @@ wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_MOVED, SimpleEvent);
 wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_MOVED, Vec3dEvent);
 wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_ROTATED, SimpleEvent);
 wxDECLARE_EVENT(EVT_GLCANVAS_INSTANCE_SCALED, SimpleEvent);
+wxDECLARE_EVENT(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3dEvent);
 wxDECLARE_EVENT(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, Event<bool>);
 wxDECLARE_EVENT(EVT_GLCANVAS_UPDATE_GEOMETRY, Vec3dsEvent<2>);
 wxDECLARE_EVENT(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, SimpleEvent);
@@ -608,6 +610,9 @@ public:
     int get_move_volume_id() const { return m_mouse.drag.move_volume_idx; }
     int get_first_hover_volume_idx() const { return m_hover_volume_idxs.empty() ? -1 : m_hover_volume_idxs.front(); }
 
+    arr::WipeTowerInfo get_wipe_tower_info() const;
+    void arrange_wipe_tower(const arr::WipeTowerInfo& wti) const;
+
     // Returns the view ray line, in world coordinate, at the given mouse position.
     Linef3 mouse_ray(const Point& mouse_pos);
 
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 79b24fe1a..04ea99505 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -798,7 +798,7 @@ bool GUI_App::check_unsaved_changes()
         return true;
     // Ask the user.
     wxMessageDialog dialog(mainframe,
-        _(L("The following presets were modified: ")) + dirty + "\n" + _(L("Discard changes and continue anyway?")),
+        _(L("The following presets were modified")) + ": " + dirty + "\n" + _(L("Discard changes and continue anyway?")),
         wxString(SLIC3R_APP_NAME) + " - " + _(L("Unsaved Presets")),
         wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT);
     return dialog.ShowModal() == wxID_YES;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
index f5946aa56..c65dee4d8 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
@@ -102,7 +102,7 @@ protected:
             m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
         }
     }
-    virtual bool on_is_activable(const Selection& selection) const { return !selection.is_wipe_tower(); }
+    virtual bool on_is_activable(const Selection& selection) const { return true; }
     virtual void on_enable_grabber(unsigned int id)
     {
         if ((0 <= id) && (id < 3))
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
index 64c8a73b0..7e978e2a3 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
@@ -4,6 +4,7 @@
 #include "slic3r/GUI/3DScene.hpp"
 #include "slic3r/GUI/GUI_App.hpp"
 #include "slic3r/GUI/GUI_ObjectManipulation.hpp"
+#include "slic3r/GUI/PresetBundle.hpp"
 
 #include <GL/glew.h>
 #include <wx/glcanvas.h>
@@ -264,8 +265,11 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
 
     const Selection& selection = canvas.get_selection();
 
-    bool enable_move_z = !selection.is_wipe_tower();
-    enable_grabber(Move, 2, enable_move_z);
+    bool is_wipe_tower = selection.is_wipe_tower();
+    enable_grabber(Move, 2, !is_wipe_tower);
+    enable_grabber(Rotate, 0, !is_wipe_tower);
+    enable_grabber(Rotate, 1, !is_wipe_tower);
+
     bool enable_scale_xyz = selection.is_single_full_instance() || selection.is_single_volume() || selection.is_single_modifier();
     for (int i = 0; i < 6; ++i)
     {
@@ -290,6 +294,14 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
         set_flattening_data(nullptr);
         set_sla_support_data(nullptr, selection);
     }
+    else if (is_wipe_tower)
+    {
+        DynamicPrintConfig& config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
+        set_scale(Vec3d::Ones());
+        set_rotation(Vec3d(0., 0., (M_PI/180.) * dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value));
+        set_flattening_data(nullptr);
+        set_sla_support_data(nullptr, selection);
+    }
     else
     {
         set_scale(Vec3d::Ones());
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index fa2c166d2..27f5795b2 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1314,6 +1314,7 @@ struct Plater::priv
     void on_object_select(SimpleEvent&);
     void on_right_click(Vec2dEvent&);
     void on_wipetower_moved(Vec3dEvent&);
+    void on_wipetower_rotated(Vec3dEvent&);
     void on_update_geometry(Vec3dsEvent<2>&);
     void on_3dcanvas_mouse_dragging_finished(SimpleEvent&);
 
@@ -1448,6 +1449,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
         { if (evt.data == 1) this->q->increase_instances(); else if (this->can_decrease_instances()) this->q->decrease_instances(); });
     view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_MOVED, [this](SimpleEvent&) { update(); });
     view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_MOVED, &priv::on_wipetower_moved, this);
+    view3D_canvas->Bind(EVT_GLCANVAS_WIPETOWER_ROTATED, &priv::on_wipetower_rotated, this);
     view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_ROTATED, [this](SimpleEvent&) { update(); });
     view3D_canvas->Bind(EVT_GLCANVAS_INSTANCE_SCALED, [this](SimpleEvent&) { update(); });
     view3D_canvas->Bind(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, [this](Event<bool> &evt) { this->sidebar->enable_buttons(evt.data); });
@@ -1455,6 +1457,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
     view3D_canvas->Bind(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED, &priv::on_3dcanvas_mouse_dragging_finished, this);
     view3D_canvas->Bind(EVT_GLCANVAS_TAB, [this](SimpleEvent&) { select_next_view_3D(); });
     view3D_canvas->Bind(EVT_GLCANVAS_RESETGIZMOS, [this](SimpleEvent&) { reset_all_gizmos(); });
+
     // 3DScene/Toolbar:
     view3D_canvas->Bind(EVT_GLTOOLBAR_ADD, &priv::on_action_add, this);
     view3D_canvas->Bind(EVT_GLTOOLBAR_DELETE, [q](SimpleEvent&) { q->remove_selected(); });
@@ -1877,7 +1880,13 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode
     Polyline bed; bed.points.reserve(bedpoints.size());
     for(auto& v : bedpoints) bed.append(Point::new_scale(v(0), v(1)));
 
-    arr::find_new_position(model, new_instances, min_obj_distance, bed);
+    arr::WipeTowerInfo wti = view3D->get_canvas3d()->get_wipe_tower_info();
+
+    arr::find_new_position(model, new_instances, min_obj_distance, bed, wti);
+
+    // it remains to move the wipe tower:
+    view3D->get_canvas3d()->arrange_wipe_tower(wti);
+
 #endif /* AUTOPLACEMENT_ON_LOAD */
 
     if (scaled_down) {
@@ -2134,6 +2143,8 @@ void Plater::priv::arrange()
 
     statusfn(0, arrangestr);
 
+    arr::WipeTowerInfo wti = view3D->get_canvas3d()->get_wipe_tower_info();
+
     try {
         arr::BedShapeHint hint;
 
@@ -2141,6 +2152,7 @@ void Plater::priv::arrange()
         hint.type = arr::BedShapeType::WHO_KNOWS;
 
         arr::arrange(model,
+                     wti,
                      min_obj_distance,
                      bed,
                      hint,
@@ -2152,6 +2164,9 @@ void Plater::priv::arrange()
                                    "Some geometries may be invalid."));
     }
 
+    // it remains to move the wipe tower:
+    view3D->get_canvas3d()->arrange_wipe_tower(wti);
+
     statusfn(0, L("Arranging done."));
     statusbar()->set_range(prev_range);
     statusbar()->set_cancel_callback(); // remove cancel button
@@ -2254,7 +2269,8 @@ void Plater::priv::sla_optimize_rotation() {
         oi->set_rotation(rt);
     }
 
-    arr::find_new_position(model, o->instances, coord_t(mindist/SCALING_FACTOR), bed);
+    arr::WipeTowerInfo wti; // useless in SLA context
+    arr::find_new_position(model, o->instances, coord_t(mindist/SCALING_FACTOR), bed, wti);
 
     // Correct the z offset of the object which was corrupted be the rotation
     o->ensure_on_bed();
@@ -2862,6 +2878,15 @@ void Plater::priv::on_wipetower_moved(Vec3dEvent &evt)
     wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg);
 }
 
+void Plater::priv::on_wipetower_rotated(Vec3dEvent& evt)
+{
+    DynamicPrintConfig cfg;
+    cfg.opt<ConfigOptionFloat>("wipe_tower_x", true)->value = evt.data(0);
+    cfg.opt<ConfigOptionFloat>("wipe_tower_y", true)->value = evt.data(1);
+    cfg.opt<ConfigOptionFloat>("wipe_tower_rotation_angle", true)->value = Geometry::rad2deg(evt.data(2));
+    wxGetApp().get_tab(Preset::TYPE_PRINT)->load_config(cfg);
+}
+
 void Plater::priv::on_update_geometry(Vec3dsEvent<2>&)
 {
     // TODO
diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp
index eaa00bf6f..ee47446cf 100644
--- a/src/slic3r/GUI/Selection.cpp
+++ b/src/slic3r/GUI/Selection.cpp
@@ -499,100 +499,111 @@ void Selection::rotate(const Vec3d& rotation, TransformationType transformation_
     // Only relative rotation values are allowed in the world coordinate system.
     assert(!transformation_type.world() || transformation_type.relative());
 
-    int rot_axis_max = 0;
-    if (rotation.isApprox(Vec3d::Zero()))
-    {
-        for (unsigned int i : m_list)
+    if (!is_wipe_tower()) {
+        int rot_axis_max = 0;
+        if (rotation.isApprox(Vec3d::Zero()))
         {
-            GLVolume &volume = *(*m_volumes)[i];
-            if (m_mode == Instance)
-            {
-                volume.set_instance_rotation(m_cache.volumes_data[i].get_instance_rotation());
-                volume.set_instance_offset(m_cache.volumes_data[i].get_instance_position());
-            }
-            else if (m_mode == Volume)
-            {
-                volume.set_volume_rotation(m_cache.volumes_data[i].get_volume_rotation());
-                volume.set_volume_offset(m_cache.volumes_data[i].get_volume_position());
-            }
-        }
-    }
-    else
-    {
-        //FIXME this does not work for absolute rotations (transformation_type.absolute() is true)
-        rotation.cwiseAbs().maxCoeff(&rot_axis_max);
-
-        // For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it.
-        std::vector<int> object_instance_first(m_model->objects.size(), -1);
-        auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, transformation_type](GLVolume &volume, int i) {
-            int first_volume_idx = object_instance_first[volume.object_idx()];
-            if (rot_axis_max != 2 && first_volume_idx != -1) {
-                // Generic rotation, but no rotation around the Z axis.
-                // Always do a local rotation (do not consider the selection to be a rigid body).
-                assert(is_approx(rotation.z(), 0.0));
-                const GLVolume &first_volume = *(*m_volumes)[first_volume_idx];
-                const Vec3d    &rotation = first_volume.get_instance_rotation();
-                double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
-                volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
-            }
-            else {
-                // extracts rotations from the composed transformation
-                Vec3d new_rotation = transformation_type.world() ?
-                    Geometry::extract_euler_angles(Geometry::assemble_transform(Vec3d::Zero(), rotation) * m_cache.volumes_data[i].get_instance_rotation_matrix()) :
-                    transformation_type.absolute() ? rotation : rotation + m_cache.volumes_data[i].get_instance_rotation();
-                if (rot_axis_max == 2 && transformation_type.joint()) {
-                    // Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis.
-                    Vec3d offset = Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, 0.0, new_rotation(2) - m_cache.volumes_data[i].get_instance_rotation()(2))) * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
-                    volume.set_instance_offset(m_cache.dragging_center + offset);
-                }
-                volume.set_instance_rotation(new_rotation);
-                object_instance_first[volume.object_idx()] = i;
-            }
-        };
-
-        for (unsigned int i : m_list)
-        {
-            GLVolume &volume = *(*m_volumes)[i];
-            if (is_single_full_instance())
-                rotate_instance(volume, i);
-            else if (is_single_volume() || is_single_modifier())
-            {
-                if (transformation_type.independent())
-                    volume.set_volume_rotation(volume.get_volume_rotation() + rotation);
-                else
-                {
-                    Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
-                    Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
-                    volume.set_volume_rotation(new_rotation);
-                }
-            }
-            else
+            for (unsigned int i : m_list)
             {
+                GLVolume &volume = *(*m_volumes)[i];
                 if (m_mode == Instance)
-                    rotate_instance(volume, i);
+                {
+                    volume.set_instance_rotation(m_cache.volumes_data[i].get_instance_rotation());
+                    volume.set_instance_offset(m_cache.volumes_data[i].get_instance_position());
+                }
                 else if (m_mode == Volume)
                 {
-                    // extracts rotations from the composed transformation
-                    Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
-                    Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
-                    if (transformation_type.joint())
-                    {
-                        Vec3d local_pivot = m_cache.volumes_data[i].get_instance_full_matrix().inverse() * m_cache.dragging_center;
-                        Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() - local_pivot);
-                        volume.set_volume_offset(local_pivot + offset);
-                    }
-                    volume.set_volume_rotation(new_rotation);
+                    volume.set_volume_rotation(m_cache.volumes_data[i].get_volume_rotation());
+                    volume.set_volume_offset(m_cache.volumes_data[i].get_volume_position());
                 }
             }
         }
-    }
+        else { // this is not the wipe tower
+            //FIXME this does not work for absolute rotations (transformation_type.absolute() is true)
+            rotation.cwiseAbs().maxCoeff(&rot_axis_max);
 
-#if !DISABLE_INSTANCES_SYNCH
-    if (m_mode == Instance)
-        synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL);
-    else if (m_mode == Volume)
-        synchronize_unselected_volumes();
-#endif // !DISABLE_INSTANCES_SYNCH
+            // For generic rotation, we want to rotate the first volume in selection, and then to synchronize the other volumes with it.
+            std::vector<int> object_instance_first(m_model->objects.size(), -1);
+            auto rotate_instance = [this, &rotation, &object_instance_first, rot_axis_max, transformation_type](GLVolume &volume, int i) {
+                int first_volume_idx = object_instance_first[volume.object_idx()];
+                if (rot_axis_max != 2 && first_volume_idx != -1) {
+                    // Generic rotation, but no rotation around the Z axis.
+                    // Always do a local rotation (do not consider the selection to be a rigid body).
+                    assert(is_approx(rotation.z(), 0.0));
+                    const GLVolume &first_volume = *(*m_volumes)[first_volume_idx];
+                    const Vec3d    &rotation = first_volume.get_instance_rotation();
+                    double z_diff = Geometry::rotation_diff_z(m_cache.volumes_data[first_volume_idx].get_instance_rotation(), m_cache.volumes_data[i].get_instance_rotation());
+                    volume.set_instance_rotation(Vec3d(rotation(0), rotation(1), rotation(2) + z_diff));
+                }
+                else {
+                    // extracts rotations from the composed transformation
+                    Vec3d new_rotation = transformation_type.world() ?
+                        Geometry::extract_euler_angles(Geometry::assemble_transform(Vec3d::Zero(), rotation) * m_cache.volumes_data[i].get_instance_rotation_matrix()) :
+                        transformation_type.absolute() ? rotation : rotation + m_cache.volumes_data[i].get_instance_rotation();
+                    if (rot_axis_max == 2 && transformation_type.joint()) {
+                        // Only allow rotation of multiple instances as a single rigid body when rotating around the Z axis.
+                        Vec3d offset = Geometry::assemble_transform(Vec3d::Zero(), Vec3d(0.0, 0.0, new_rotation(2) - m_cache.volumes_data[i].get_instance_rotation()(2))) * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center);
+                        volume.set_instance_offset(m_cache.dragging_center + offset);
+                    }
+                    volume.set_instance_rotation(new_rotation);
+                    object_instance_first[volume.object_idx()] = i;
+                }
+            };
+
+            for (unsigned int i : m_list)
+            {
+                GLVolume &volume = *(*m_volumes)[i];
+                if (is_single_full_instance())
+                    rotate_instance(volume, i);
+                else if (is_single_volume() || is_single_modifier())
+                {
+                    if (transformation_type.independent())
+                        volume.set_volume_rotation(volume.get_volume_rotation() + rotation);
+                    else
+                    {
+                        Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
+                        Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
+                        volume.set_volume_rotation(new_rotation);
+                    }
+                }
+                else
+                {
+                    if (m_mode == Instance)
+                        rotate_instance(volume, i);
+                    else if (m_mode == Volume)
+                    {
+                        // extracts rotations from the composed transformation
+                        Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), rotation);
+                        Vec3d new_rotation = Geometry::extract_euler_angles(m * m_cache.volumes_data[i].get_volume_rotation_matrix());
+                        if (transformation_type.joint())
+                        {
+                            Vec3d local_pivot = m_cache.volumes_data[i].get_instance_full_matrix().inverse() * m_cache.dragging_center;
+                            Vec3d offset = m * (m_cache.volumes_data[i].get_volume_position() - local_pivot);
+                            volume.set_volume_offset(local_pivot + offset);
+                        }
+                        volume.set_volume_rotation(new_rotation);
+                    }
+                }
+            }
+        }
+
+    #if !DISABLE_INSTANCES_SYNCH
+        if (m_mode == Instance)
+            synchronize_unselected_instances((rot_axis_max == 2) ? SYNC_ROTATION_NONE : SYNC_ROTATION_GENERAL);
+        else if (m_mode == Volume)
+            synchronize_unselected_volumes();
+    #endif // !DISABLE_INSTANCES_SYNCH
+    }
+    else { // it's the wipe tower that's selected and being rotated
+        GLVolume& volume = *((*m_volumes)[*m_list.begin()]); // the wipe tower is always alone in the selection
+
+        // make sure the wipe tower rotates around its center, not origin
+        // we can assume that only Z rotation changes
+        Vec3d center_local = volume.transformed_bounding_box().center() - volume.get_volume_offset();
+        Vec3d center_local_new = Eigen::AngleAxisd(rotation(2)-volume.get_volume_rotation()(2), Vec3d(0, 0, 1)) * center_local;
+        volume.set_volume_rotation(rotation);
+        volume.set_volume_offset(volume.get_volume_offset() + center_local - center_local_new);
+    }
 
     this->set_bounding_boxes_dirty();
 }
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 3a1b5d37d..4e2403914 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -2333,7 +2333,20 @@ void TabPrinter::update_pages()
     // set m_pages_(technology after changing) to m_pages
     // m_printer_technology will be set by Tab::load_current_preset()
     if (new_printer_technology == ptFFF)
-        m_pages_fff.empty() ? build_fff() : m_pages.swap(m_pages_fff);
+    {
+        if (m_pages_fff.empty())
+        {
+            build_fff();
+            if (m_extruders_count > 1)
+            {
+                m_preset_bundle->update_multi_material_filament_presets();
+                on_value_change("extruders_count", m_extruders_count);
+                wxGetApp().sidebar().update_objects_list_extruder_column(m_extruders_count);
+            }
+        }
+        else
+            m_pages.swap(m_pages_fff);
+    }
     else 
         m_pages_sla.empty() ? build_sla() : m_pages.swap(m_pages_sla);
 
diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp
index 58bd3cfb5..5f01988f5 100644
--- a/src/slic3r/GUI/Tab.hpp
+++ b/src/slic3r/GUI/Tab.hpp
@@ -312,7 +312,7 @@ class TabPrint : public Tab
     bool is_msg_dlg_already_exist {false};
 public:
 	TabPrint(wxNotebook* parent) : 
-		Tab(parent, _(L("Print Settings")), "print") {}
+		Tab(parent, _(L("Print Settings")), L("print")) {}
 	~TabPrint() {}
 
 	ogStaticText*	m_recommended_thin_wall_thickness_description_line;
@@ -330,7 +330,7 @@ class TabFilament : public Tab
 	ogStaticText*	m_cooling_description_line;
 public:
 	TabFilament(wxNotebook* parent) : 
-		Tab(parent, _(L("Filament Settings")), "filament") {}
+		Tab(parent, _(L("Filament Settings")), L("filament")) {}
 	~TabFilament() {}
 
 	void		build() override;
@@ -363,7 +363,7 @@ public:
 
     PrinterTechnology               m_printer_technology = ptFFF;
 
-	TabPrinter(wxNotebook* parent) : Tab(parent, _(L("Printer Settings")), "printer") {}
+	TabPrinter(wxNotebook* parent) : Tab(parent, _(L("Printer Settings")), L("printer")) {}
 	~TabPrinter() {}
 
 	void		build() override;
@@ -386,7 +386,7 @@ class TabSLAMaterial : public Tab
 {
 public:
     TabSLAMaterial(wxNotebook* parent) :
-		Tab(parent, _(L("Material Settings")), "sla_material") {}
+		Tab(parent, _(L("Material Settings")), L("sla_material")) {}
     ~TabSLAMaterial() {}
 
 	void		build() override;
@@ -400,7 +400,7 @@ class TabSLAPrint : public Tab
 {
 public:
     TabSLAPrint(wxNotebook* parent) :
-        Tab(parent, _(L("Print Settings")), "sla_print") {}
+        Tab(parent, _(L("Print Settings")), L("sla_print")) {}
     ~TabSLAPrint() {}
     void		build() override;
 	void		reload_config() override;