diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index 111f9a471..f08281d93 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -312,11 +312,11 @@ bool GCode::do_export(FILE *file, Print &print)
         initial_extruder_id = 0;
 
     // Set extruder(s) temperature before and after start G-code.
-    this->_print_first_layer_extruder_temperatures(file, print, false);
+    this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, false);
     // Let the start-up script prime the 1st printing tool.
     m_placeholder_parser.set("initial_tool", initial_extruder_id);
     fprintf(file, "%s\n", m_placeholder_parser.process(print.config.start_gcode.value).c_str());
-    this->_print_first_layer_extruder_temperatures(file, print, true);
+    this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, true);
     
     // Set other general things.
     write(file, this->preamble());
@@ -414,7 +414,7 @@ bool GCode::do_export(FILE *file, Print &print)
                     if (print.config.first_layer_bed_temperature.value > 0)
                         write(file, m_writer.set_bed_temperature(print.config.first_layer_bed_temperature));
                     // Set first layer extruder.
-                    this->_print_first_layer_extruder_temperatures(file, print, false);
+                    this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, false);
                 }
                 // Pair the object layers with the support layers by z, extrude them.
                 size_t idx_object_layer  = 0;
@@ -567,16 +567,26 @@ bool GCode::do_export(FILE *file, Print &print)
 // FIXME this does not work correctly for multi-extruder, single heater configuration as it emits multiple preheat commands for the same heater.
 // M104 - Set Extruder Temperature
 // M109 - Set Extruder Temperature and Wait
-void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, bool wait)
+void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, unsigned int first_printing_extruder_id, bool wait)
 {
     if (boost::ifind_first(print.config.start_gcode.value, std::string("M104")).empty() &&
         boost::ifind_first(print.config.start_gcode.value, std::string("M109")).empty()) {
-        for (unsigned int tool_id : print.extruders()) {
-            int temp = print.config.first_layer_temperature.get_at(tool_id);
+        if (print.config.single_extruder_multi_material.value) {
+            // Set temperature of the first printing extruder only.
+            int temp = print.config.first_layer_temperature.get_at(first_printing_extruder_id);
             if (print.config.ooze_prevention.value)
                 temp += print.config.standby_temperature_delta.value;
             if (temp > 0)
-                write(file, m_writer.set_temperature(temp, wait, tool_id));
+                write(file, m_writer.set_temperature(temp, wait, first_printing_extruder_id));
+        } else {
+            // Set temperatures of all the printing extruders.
+            for (unsigned int tool_id : print.extruders()) {
+                int temp = print.config.first_layer_temperature.get_at(tool_id);
+                if (print.config.ooze_prevention.value)
+                    temp += print.config.standby_temperature_delta.value;
+                if (temp > 0)
+                    write(file, m_writer.set_temperature(temp, wait, tool_id));
+            }
         }
     }
 }
@@ -668,20 +678,6 @@ void GCode::process_layer(
     
     std::string gcode;
 
-    if (! first_layer && ! m_second_layer_things_done) {
-        // Transition from 1st to 2nd layer. Adjust nozzle temperatures as prescribed by the nozzle dependent
-        // first_layer_temperature vs. temperature settings.
-        for (const Extruder &extruder : m_writer.extruders) {
-            int temperature = print.config.temperature.get_at(extruder.id);
-            if (temperature > 0 && temperature != print.config.first_layer_temperature.get_at(extruder.id))
-                gcode += m_writer.set_temperature(temperature, false, extruder.id);
-        }
-        if (print.config.bed_temperature.value > 0 && print.config.bed_temperature != print.config.first_layer_bed_temperature.value)
-            gcode += m_writer.set_bed_temperature(print.config.bed_temperature);
-        // Mark the temperature transition from 1st to 2nd layer to be finished.
-        m_second_layer_things_done = true;
-    }
-    
     // Set new layer - this will change Z and force a retraction if retract_layer_change is enabled.
     if (! print.config.before_layer_gcode.value.empty()) {
         PlaceholderParser pp(m_placeholder_parser);
@@ -698,9 +694,33 @@ void GCode::process_layer(
         gcode += pp.process(print.config.layer_gcode.value) + "\n";
     }
 
-    if (m_wipe_tower && ! m_wipe_tower->finished() && layer.id() == 0 && m_writer.extruder()->id == layer_tools.extruders.front())
-        // Trigger the tool change explicitely to draw the wipe tower brim always.
-        gcode += this->wipe_tower_tool_change(layer_tools.extruders.front());
+    // Trigger the tool change explicitely to draw the wipe tower brim always.
+    bool wipe_tower_extrude_brim_explicit = m_wipe_tower && ! m_wipe_tower->finished() && first_layer && m_writer.extruder()->id == first_extruder_id;
+
+    if (! first_layer && ! m_second_layer_things_done) {
+        // Transition from 1st to 2nd layer. Adjust nozzle temperatures as prescribed by the nozzle dependent
+        // first_layer_temperature vs. temperature settings.
+        if (print.config.single_extruder_multi_material.value) {
+            // Switch the extruder before setting the 2nd layer temperature.
+            this->set_extruder(first_extruder_id);
+            int temperature = print.config.temperature.get_at(first_extruder_id);
+            if (temperature > 0 && temperature != print.config.first_layer_temperature.get_at(m_writer.extruder()->id))
+                gcode += m_writer.set_temperature(temperature, false, first_extruder_id);
+        } else {
+            for (const Extruder &extruder : m_writer.extruders) {
+                int temperature = print.config.temperature.get_at(extruder.id);
+                if (temperature > 0 && temperature != print.config.first_layer_temperature.get_at(extruder.id))
+                    gcode += m_writer.set_temperature(temperature, false, extruder.id);
+            }
+        }
+        if (print.config.bed_temperature.value > 0 && print.config.bed_temperature != print.config.first_layer_bed_temperature.value)
+            gcode += m_writer.set_bed_temperature(print.config.bed_temperature);
+        // Mark the temperature transition from 1st to 2nd layer to be finished.
+        m_second_layer_things_done = true;
+    }
+
+    if (wipe_tower_extrude_brim_explicit)
+        gcode += this->wipe_tower_tool_change(first_extruder_id);
 
     // Extrude skirt at the print_z of the raft layers and normal object layers
     // not at the print_z of the interlaced support material layers.
diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp
index 4bba6866f..96b1360f1 100644
--- a/xs/src/libslic3r/GCode.hpp
+++ b/xs/src/libslic3r/GCode.hpp
@@ -234,7 +234,7 @@ private:
     std::pair<const PrintObject*, Point> m_last_obj_copy;
 
     std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1);
-    void _print_first_layer_extruder_temperatures(FILE *file, Print &print, bool wait);
+    void _print_first_layer_extruder_temperatures(FILE *file, Print &print, unsigned int first_printing_extruder_id, bool wait);
     // this flag triggers first layer speeds
     bool                                on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; }
 
diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
index bce5e0247..50f41c94f 100644
--- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
+++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
@@ -98,7 +98,7 @@ public:
 		{ return extrude_explicit(x, m_current_pos.y, e, f); }
 
 	Writer& retract(float e, float f = 0.f)
-		{ return retract(-e, f); }
+		{ return deretract(-e, f); }
 
 	Writer& z_hop(float hop, float f = 0.f) { 
 		m_gcode += std::string("G1") + set_format_Z(m_current_z + hop);
@@ -277,7 +277,7 @@ std::pair<std::string, WipeTower::xy> WipeTowerPrusaMM::tool_change(int tool)
 	// or there must be a nonzero wipe tower partitions available.
 	assert(tool < 0 || it_layer_tools->wipe_tower_partitions > 0);
 
-	if (m_layer_change_in_layer == size_t(-1))
+	if (m_layer_change_in_layer == (unsigned int)(-1))
 		// First layer, prime the extruder.
 		return toolchange_Brim(tool);
 
diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
index 6e804a725..6c517c5e7 100644
--- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
+++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
@@ -2,6 +2,7 @@
 #define WipeTowerPrusaMM_hpp_
 
 #include <algorithm>
+#include <cmath>
 #include <string>
 #include <utility>
 
@@ -84,10 +85,10 @@ public:
 		m_is_first_layer 		= is_first_layer;
 		m_is_last_layer			= is_last_layer;
 		// Start counting the color changes from zero.
-		m_layer_change_in_layer = is_first_layer ? size_t(-1) : 0;
+		m_layer_change_in_layer = is_first_layer ? (unsigned int)(-1) : 0;
 		m_current_wipe_start_y  = 0.f;
 
-		int layer_idx = int(floor(layer_height * 100) + 0.5f);
+		int layer_idx = int(std::floor(layer_height * 100) + 0.5f);
 		switch (layer_idx)
 		{
 		case 15:
diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp
index b4d79f91a..eb8220208 100644
--- a/xs/src/libslic3r/Print.cpp
+++ b/xs/src/libslic3r/Print.cpp
@@ -148,6 +148,9 @@ Print::invalidate_state_by_config_options(const std::vector<t_config_option_key>
             || *opt_key == "fan_always_on"
             || *opt_key == "fan_below_layer_time"
             || *opt_key == "filament_diameter"
+            || *opt_key == "filament_notes"
+            || *opt_key == "filament_type"
+            || *opt_key == "filament_soluble"
             || *opt_key == "first_layer_acceleration"
             || *opt_key == "first_layer_bed_temperature"
             || *opt_key == "first_layer_speed"
@@ -175,6 +178,7 @@ Print::invalidate_state_by_config_options(const std::vector<t_config_option_key>
             || *opt_key == "retract_restart_extra"
             || *opt_key == "retract_restart_extra_toolchange"
             || *opt_key == "retract_speed"
+            || *opt_key == "single_extruder_multi_material"
             || *opt_key == "slowdown_below_layer_time"
             || *opt_key == "spiral_vase"
             || *opt_key == "standby_temperature_delta"
@@ -186,6 +190,11 @@ Print::invalidate_state_by_config_options(const std::vector<t_config_option_key>
             || *opt_key == "use_firmware_retraction"
             || *opt_key == "use_relative_e_distances"
             || *opt_key == "wipe"
+            || *opt_key == "wipe_tower"
+            || *opt_key == "wipe_tower_x"
+            || *opt_key == "wipe_tower_y"
+            || *opt_key == "wipe_tower_width"
+            || *opt_key == "wipe_tower_per_color_wipe"
             || *opt_key == "z_offset"
             || *opt_key == "max_volumetric_extrusion_rate_slope_negative"
             || *opt_key == "max_volumetric_extrusion_rate_slope_positive") {