diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm
index db21b3409..0bef735e3 100644
--- a/lib/Slic3r/GUI/3DScene.pm
+++ b/lib/Slic3r/GUI/3DScene.pm
@@ -240,11 +240,13 @@ sub layer_editing_allowed {
     return ! (defined($self->{layer_editing_initialized}) && $self->{layer_editing_initialized} == 2);
 }
 
-sub _first_selected_object_id {
+sub _first_selected_object_id_for_variable_layer_height_editing {
     my ($self) = @_;
     for my $i (0..$#{$self->volumes}) {
         if ($self->volumes->[$i]->selected) {
-            return int($self->volumes->[$i]->select_group_id / 1000000);
+            my $object_id = int($self->volumes->[$i]->select_group_id / 1000000);
+            # Objects with object_id >= 1000 have a specific meaning, for example the wipe tower proxy.
+            return $object_id if $object_id < 10000;
         }
     }
     return -1;
@@ -332,7 +334,7 @@ sub mouse_event {
     my ($self, $e) = @_;
     
     my $pos = Slic3r::Pointf->new($e->GetPositionXY);
-    my $object_idx_selected = $self->{layer_height_edit_last_object_id} = ($self->layer_editing_enabled && $self->{print}) ? $self->_first_selected_object_id : -1;
+    my $object_idx_selected = $self->{layer_height_edit_last_object_id} = ($self->layer_editing_enabled && $self->{print}) ? $self->_first_selected_object_id_for_variable_layer_height_editing : -1;
 
     if ($e->Entering && &Wx::wxMSW) {
         # wxMSW needs focus in order to catch mouse wheel events
@@ -502,7 +504,7 @@ sub mouse_wheel_event {
     my ($self, $e) = @_;
     
     if ($self->layer_editing_enabled && $self->{print}) {
-        my $object_idx_selected = $self->_first_selected_object_id;
+        my $object_idx_selected = $self->_first_selected_object_id_for_variable_layer_height_editing;
         if ($object_idx_selected != -1) {
             # A volume is selected. Test, whether hovering over a layer thickness bar.
             if ($self->_variable_layer_thickness_bar_rect_mouse_inside($e)) {
diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index 1446c5023..9c75f99ae 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -53,6 +53,8 @@ sub new {
     $self->{config} = Slic3r::Config->new_from_defaults(qw(
         bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
         serial_port serial_speed octoprint_host octoprint_apikey
+        nozzle_diameter single_extruder_multi_material 
+        wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe 
     ));
     # C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm
     $self->{model} = Slic3r::Model->new;
@@ -77,7 +79,8 @@ sub new {
     # Initialize handlers for canvases
     my $on_select_object = sub {
         my ($obj_idx) = @_;
-        $self->select_object($obj_idx);
+        # Ignore the special objects (the wipe tower proxy and such).
+        $self->select_object((defined($obj_idx) && $obj_idx < 1000) ? $obj_idx : undef);
     };
     my $on_double_click = sub {
         $self->object_settings_dialog if $self->selected_object;
@@ -538,7 +541,8 @@ sub on_layer_editing_toggled {
             $self->{"btn_layer_editing"}->SetValue(0);
         }
     }
-    $self->{canvas3D}->update;
+    $self->{canvas3D}->Refresh;
+    $self->{canvas3D}->Update;
 }
 
 sub GetFrame {
@@ -1700,6 +1704,7 @@ sub on_config_change {
     my $self = shift;
     my ($config) = @_;
     
+    my $update_scheduled;
     foreach my $opt_key (@{$self->{config}->diff($config)}) {
         $self->{config}->set($opt_key, $config->get($opt_key));
         if ($opt_key eq 'bed_shape') {
@@ -1707,7 +1712,10 @@ sub on_config_change {
             $self->{canvas3D}->update_bed_size if $self->{canvas3D};
             $self->{preview3D}->set_bed_shape($self->{config}->bed_shape)
                 if $self->{preview3D};
-            $self->update;
+            $update_scheduled = 1;
+        } elsif ($opt_key =~ '^wipe_tower' || $opt_key == 'single_extruder_multi_material') {
+            #$self->{canvas3D}->reload_scene if $self->{canvas3D};
+            $update_scheduled = 1;
         } elsif ($opt_key eq 'serial_port') {
             if ($config->get('serial_port')) {
                 $self->{btn_print}->Show;
@@ -1732,7 +1740,8 @@ sub on_config_change {
                     $self->{"btn_layer_editing"}->SetValue(0);
                 }
                 $self->{canvas3D}->layer_editing_enabled(0);
-                $self->{canvas3D}->update;
+                $self->{canvas3D}->Refresh;
+                $self->{canvas3D}->Update;
             } elsif ($self->{canvas3D}->layer_editing_allowed) {
                 # Want to allow the layer editing, but do it only if the OpenGL supports it.
                 if ($self->{htoolbar}) {
@@ -1743,6 +1752,8 @@ sub on_config_change {
             }
         }
     }
+
+    $self->update if $update_scheduled;
     
     return if !$self->GetFrame->is_loaded;
     
@@ -1955,7 +1966,7 @@ sub refresh_canvases {
     my ($self) = @_;
     
     $self->{canvas}->Refresh;
-    $self->{canvas3D}->update if $self->{canvas3D};
+    $self->{canvas3D}->reload_scene if $self->{canvas3D};
     $self->{preview3D}->reload_print if $self->{preview3D};
 }
 
diff --git a/lib/Slic3r/GUI/Plater/3D.pm b/lib/Slic3r/GUI/Plater/3D.pm
index 2e108ff46..40bfb9935 100644
--- a/lib/Slic3r/GUI/Plater/3D.pm
+++ b/lib/Slic3r/GUI/Plater/3D.pm
@@ -29,13 +29,8 @@ sub new {
     
     $self->on_select(sub {
         my ($volume_idx) = @_;
-        
-        my $obj_idx = undef;
-        if ($volume_idx != -1) {
-            $obj_idx = $self->volumes->[$volume_idx]->object_idx;
-        }
-        $self->{on_select_object}->($obj_idx)
-            if $self->{on_select_object};
+        $self->{on_select_object}->(($volume_idx == -1) ? undef : $self->volumes->[$volume_idx]->object_idx)
+            if ($self->{on_select_object});
     });
     $self->on_move(sub {
         my @volume_idxs = @_;
@@ -47,13 +42,17 @@ sub new {
             my $instance_idx = $volume->instance_idx;
             next if $done{"${obj_idx}_${instance_idx}"};
             $done{"${obj_idx}_${instance_idx}"} = 1;
-            
-            my $model_object = $self->{model}->get_object($obj_idx);
-            $model_object
-                ->instances->[$instance_idx]
-                ->offset
-                ->translate($volume->origin->x, $volume->origin->y); #))
-            $model_object->invalidate_bounding_box;
+            if ($obj_idx < 1000) {
+                # Move a regular object.
+                my $model_object = $self->{model}->get_object($obj_idx);
+                $model_object
+                    ->instances->[$instance_idx]
+                    ->offset
+                    ->translate($volume->origin->x, $volume->origin->y); #))
+                $model_object->invalidate_bounding_box;
+            } elsif ($obj_idx == 1000) {
+                # Move a wipe tower proxy.
+            }
         }
         
         $self->{on_instances_moved}->()
@@ -88,19 +87,45 @@ sub set_on_model_update {
     $self->on_model_update($cb);
 }
 
-sub update {
+sub reload_scene {
     my ($self) = @_;
+
+    if (0) {
+        my $i = 1;
+        print STDERR "3D::reload_scene - Stack Trace:\n";
+        while ( (my @call_details = (caller($i++))) ){
+            print STDERR $call_details[1].":".$call_details[2]." in function ".$call_details[3]."\n";
+        }
+    }
     
     $self->reset_objects;
     $self->update_bed_size;
     
     foreach my $obj_idx (0..$#{$self->{model}->objects}) {
         my @volume_idxs = $self->load_object($self->{model}, $self->{print}, $obj_idx);
-        
         if ($self->{objects}[$obj_idx]->selected) {
             $self->select_volume($_) for @volume_idxs;
         }
     }
+    if (0) {
+        print "Config: $self->{config}\n";
+        $self->{config}->save('d:\temp\cfg.ini');
+    }
+    if (defined $self->{config}->nozzle_diameter) {
+        # Should the wipe tower be visualized?
+        my $extruders_count = scalar @{ $self->{config}->nozzle_diameter };
+        # Height of a print.
+        my $height = $self->{model}->bounding_box->z_max;
+        # Show at least a slab.
+        $height = 10 if $height < 10;
+        if ($extruders_count > 1 && $self->{config}->single_extruder_multi_material && $self->{config}->wipe_tower &&
+            ! $self->{config}->complete_objects) {
+            $self->volumes->load_wipe_tower_preview(1000, 
+                $self->{config}->wipe_tower_x, $self->{config}->wipe_tower_y, 
+                $self->{config}->wipe_tower_width, $self->{config}->wipe_tower_per_color_wipe * ($extruders_count - 1),
+                $self->{model}->bounding_box->z_max, $self->UseVBOs);
+        }
+    }
 }
 
 sub update_bed_size {
diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm
index b87249501..3f246a845 100644
--- a/lib/Slic3r/GUI/Tab.pm
+++ b/lib/Slic3r/GUI/Tab.pm
@@ -997,8 +997,6 @@ sub build {
             $optgroup->append_single_option_line('filament_colour', 0);
             $optgroup->append_single_option_line('filament_diameter', 0);
             $optgroup->append_single_option_line('extrusion_multiplier', 0);
-            $optgroup->append_single_option_line('filament_type', 0);
-            $optgroup->append_single_option_line('filament_soluble', 0);
             $optgroup->append_single_option_line('filament_density', 0);
             $optgroup->append_single_option_line('filament_cost', 0);
         }
@@ -1071,7 +1069,11 @@ sub build {
     {
         my $page = $self->add_options_page('Advanced', 'wrench.png');
         {
-            my $optgroup = $page->new_optgroup('Print speed override');
+            my $optgroup = $page->new_optgroup('Filament properties');
+            $optgroup->append_single_option_line('filament_type', 0);
+            $optgroup->append_single_option_line('filament_soluble', 0);
+            
+            $optgroup = $page->new_optgroup('Print speed override');
             $optgroup->append_single_option_line('filament_max_volumetric_speed', 0);
         }
     }
diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp
index 8cccbd212..2f14bce2c 100644
--- a/xs/src/slic3r/GUI/3DScene.cpp
+++ b/xs/src/slic3r/GUI/3DScene.cpp
@@ -299,6 +299,25 @@ 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, bool use_VBOs)
+{
+    float color[4] = { 1.0f, 1.0f, 0.0f, 0.5f };
+    this->volumes.emplace_back(new GLVolume(color));
+    GLVolume &v = *this->volumes.back();
+    auto mesh = make_cube(width, depth, height);
+    v.indexed_vertex_array.load_mesh_flat_shading(mesh);
+    v.origin = Pointf3(pos_x, pos_y, 0.);
+    // 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);
+    v.composite_id = obj_idx * 1000000;
+    v.select_group_id = obj_idx * 1000000;
+    v.drag_group_id = obj_idx * 1000;
+    return int(this->volumes.size() - 1);
+}
+
 void GLVolumeCollection::render_VBOs() const
 {
 //    glEnable(GL_BLEND);
@@ -453,18 +472,19 @@ static void thick_lines_to_indexed_vertex_array(
             idx_a[TOP] = idx_prev[TOP];
         }
         if (ii == 0 || bottom_z_different) {
+            // Start of the 1st line segment or a change of the layer thickness while maintaining the print_z.
             idx_a[BOTTOM] = idx_last ++;
             volume.push_geometry(a.x, a.y, bottom_z, 0., 0., -1.);
+            idx_a[LEFT ] = idx_last ++;
+            volume.push_geometry(a2.x, a2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z);
+            idx_a[RIGHT] = idx_last ++;
+            volume.push_geometry(a1.x, a1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z);
         } else {
             idx_a[BOTTOM] = idx_prev[BOTTOM];
         }
 
         if (ii == 0) {
             // Start of the 1st line segment.
-            idx_a[LEFT ] = idx_last ++;
-            volume.push_geometry(a2.x, a2.y, middle_z, -xy_right_normal.x, -xy_right_normal.y, -xy_right_normal.z);
-            idx_a[RIGHT] = idx_last ++;
-            volume.push_geometry(a1.x, a1.y, middle_z, xy_right_normal.x, xy_right_normal.y, xy_right_normal.z);
             width_initial    = width;
             bottom_z_initial = bottom_z;
             memcpy(idx_initial, idx_a, sizeof(int) * 4);
@@ -721,8 +741,7 @@ void _3DScene::_load_print_toolpaths(
     //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));
-    std::sort(print_zs.begin(), print_zs.end());
-    print_zs.erase(std::unique(print_zs.begin(), print_zs.end()), print_zs.end());
+    sort_remove_duplicates(print_zs);
     if (print_zs.size() > skirt_height)
         print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
     
diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp
index ed992754d..607dff831 100644
--- a/xs/src/slic3r/GUI/3DScene.hpp
+++ b/xs/src/slic3r/GUI/3DScene.hpp
@@ -224,6 +224,9 @@ public:
         const std::string        &select_by,
         const std::string        &drag_by);
 
+    int load_wipe_tower_preview(
+        int obj_idx, float pos_x, float pos_y, float width, float depth, float height, bool use_VBOs);
+
     // Bounding box of this volume, in unscaled coordinates.
     BoundingBoxf3       bounding_box;
     // Offset of the volume to be rendered.
@@ -310,6 +313,9 @@ public:
         const 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, bool use_VBOs);
+
     // Render the volumes by OpenGL.
     void render_VBOs() const;
     void render_legacy() const;
diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp
index 06b042f3b..77e93a73c 100644
--- a/xs/xsp/GUI_3DScene.xsp
+++ b/xs/xsp/GUI_3DScene.xsp
@@ -29,8 +29,7 @@
 
     std::vector<double> color()
         %code%{ RETVAL.reserve(4); RETVAL.push_back(THIS->color[0]); RETVAL.push_back(THIS->color[1]); RETVAL.push_back(THIS->color[2]); RETVAL.push_back(THIS->color[3]); %};
-    int                 composite_id()
-        %code%{ RETVAL = THIS->composite_id; %};
+
     int                 select_group_id()
         %code%{ RETVAL = THIS->select_group_id; %};
     int                 drag_group_id()
@@ -77,6 +76,8 @@
 
     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, bool use_VBOs);
+
     void erase()
         %code{% THIS->clear(); %};