From 2fef16c39aea81831ac376caae472b51082d6582 Mon Sep 17 00:00:00 2001
From: Lukas Matena <lukasmatena@seznam.cz>
Date: Tue, 10 Sep 2019 12:49:20 +0200
Subject: [PATCH] Fix of #1266 and #2258 In case there were empty object layers
 supposed to be floating on supports which were set to use a specific
 extruder, wipe tower was missing layer required to do the toolchange, leading
 to a crash Such cases are now detected and layers that need it are
 additionally assigned as wipe tower layers

Also tracked as SPE-526
---
 src/libslic3r/GCode/ToolOrdering.cpp | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp
index 677d6b868..0a9ec320e 100644
--- a/src/libslic3r/GCode/ToolOrdering.cpp
+++ b/src/libslic3r/GCode/ToolOrdering.cpp
@@ -329,6 +329,28 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
         }
     }
 
+    // If the model contains empty layers (such as https://github.com/prusa3d/Slic3r/issues/1266), there might be layers
+    // that were not marked as has_wipe_tower, even when they should have been. This produces a crash with soluble supports
+    // and maybe other problems. We will therefore go through layer_tools and detect and fix this.
+    // So, if there is a non-object layer starting with different extruder than the last one ended with (or containing more than one extruder),
+    // we'll mark it with has_wipe tower.
+    for (unsigned int i=0; i+1<m_layer_tools.size(); ++i) {
+        LayerTools& lt = m_layer_tools[i];
+        LayerTools& lt_next = m_layer_tools[i+1];
+        if (lt.extruders.empty() || lt_next.extruders.empty())
+            break;
+        if (!lt_next.has_wipe_tower && (lt_next.extruders.front() != lt.extruders.back() || lt_next.extruders.size() > 1))
+            lt_next.has_wipe_tower = true;
+        // We should also check that the next wipe tower layer is no further than max_layer_height:
+        unsigned int j = i+1;
+        double last_wipe_tower_print_z = lt_next.print_z;
+        while (++j < m_layer_tools.size()-1 && !m_layer_tools[j].has_wipe_tower)
+            if (m_layer_tools[j+1].print_z - last_wipe_tower_print_z > max_layer_height) {
+                m_layer_tools[j].has_wipe_tower = true;
+                last_wipe_tower_print_z = m_layer_tools[j].print_z;
+            }
+    }
+
     // Calculate the wipe_tower_layer_height values.
     coordf_t wipe_tower_print_z_last = 0.;
     for (LayerTools &lt : m_layer_tools)