diff --git a/src/libslic3r/CustomGCode.cpp b/src/libslic3r/CustomGCode.cpp
index 824bcdd93..72c5c20de 100644
--- a/src/libslic3r/CustomGCode.cpp
+++ b/src/libslic3r/CustomGCode.cpp
@@ -1,6 +1,10 @@
 #include "CustomGCode.hpp"
 #include "Config.hpp"
+#if ENABLE_GCODE_VIEWER
+#include "GCode.hpp"
+#else
 #include "GCode/PreviewData.hpp"
+#endif // ENABLE_GCODE_VIEWER
 #include "GCodeWriter.hpp"
 
 namespace Slic3r {
@@ -17,8 +21,12 @@ extern void update_custom_gcode_per_print_z_from_config(Info& info, DynamicPrint
         return;
     if (info.gcodes.empty() && ! colorprint_heights->values.empty()) {
 		// Convert the old colorprint_heighs only if there is no equivalent data in a new format.
-	    const std::vector<std::string>& colors = GCodePreviewData::ColorPrintColors();
-	    const auto& colorprint_values = colorprint_heights->values;
+#if ENABLE_GCODE_VIEWER
+        const std::vector<std::string>& colors = ColorPrintColors::get();
+#else
+        const std::vector<std::string>& colors = GCodePreviewData::ColorPrintColors();
+#endif // ENABLE_GCODE_VIEWER
+        const auto& colorprint_values = colorprint_heights->values;
         info.gcodes.clear();
         info.gcodes.reserve(colorprint_values.size());
         int i = 0;
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 10636082b..584d1a1e3 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -572,6 +572,10 @@ std::string WipeTowerIntegration::finalize(GCode &gcodegen)
     return gcode;
 }
 
+#if ENABLE_GCODE_VIEWER
+const std::vector<std::string> ColorPrintColors::Colors = { "#C0392B", "#E67E22", "#F1C40F", "#27AE60", "#1ABC9C", "#2980B9", "#9B59B6" };
+#endif // ENABLE_GCODE_VIEWER
+
 #define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_writer.extruder()->id())
 
 // Collect pairs of object_layer + support_layer sorted by print_z.
@@ -699,7 +703,7 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
 }
 
 #if ENABLE_GCODE_VIEWER
-void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb)
+void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb)
 #else
 void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb)
 #endif // ENABLE_GCODE_VIEWER
@@ -724,7 +728,9 @@ void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_
     if (file == nullptr)
         throw std::runtime_error(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n");
 
+#if !ENABLE_GCODE_VIEWER
     m_enable_analyzer = preview_data != nullptr;
+#endif // !ENABLE_GCODE_VIEWER
 
     try {
         m_placeholder_parser_failed_templates.clear();
@@ -778,16 +784,14 @@ void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_
             m_silent_time_estimator.reset();
     }
 
+#if !ENABLE_GCODE_VIEWER
     // starts analyzer calculations
     if (m_enable_analyzer) {
-#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-        m_analyzer.close_debug_output_file();
-#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-
         BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data" << log_memory_info();
         m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); });
         m_analyzer.reset();
     }
+#endif // !ENABLE_GCODE_VIEWER
 
     if (rename_file(path_tmp, path))
         throw std::runtime_error(
@@ -877,7 +881,14 @@ namespace DoExport {
 	    }
 	}
 
-	static void init_gcode_analyzer(const PrintConfig &config, GCodeAnalyzer &analyzer)
+#if ENABLE_GCODE_VIEWER
+    static void init_gcode_processor(const PrintConfig& config, GCodeProcessor& processor)
+    {
+        processor.reset();
+        processor.apply_config(config);
+    }
+#else
+    static void init_gcode_analyzer(const PrintConfig &config, GCodeAnalyzer &analyzer)
 	{
 	    // resets analyzer
 	    analyzer.reset();
@@ -901,17 +912,6 @@ namespace DoExport {
 
 	    // tell analyzer about the gcode flavor
 	    analyzer.set_gcode_flavor(config.gcode_flavor);
-
-#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-        analyzer.open_debug_output_file();
-#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-    }
-
-#if ENABLE_GCODE_VIEWER
-    static void init_gcode_processor(const PrintConfig& config, GCodeProcessor& processor)
-    {
-        processor.reset();
-        processor.apply_config(config);
     }
 #endif // ENABLE_GCODE_VIEWER
 
@@ -1145,15 +1145,22 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
     DoExport::init_time_estimators(print.config(), 
     	// modifies the following:
     	m_normal_time_estimator, m_silent_time_estimator, m_silent_time_estimator_enabled);
-    DoExport::init_gcode_analyzer(print.config(), m_analyzer);
 #if ENABLE_GCODE_VIEWER
     DoExport::init_gcode_processor(print.config(), m_processor);
+#else
+    DoExport::init_gcode_analyzer(print.config(), m_analyzer);
 #endif // ENABLE_GCODE_VIEWER
 
     // resets analyzer's tracking data
+#if ENABLE_GCODE_VIEWER
+    m_last_mm3_per_mm = 0.0f;
+    m_last_width = 0.0f;
+    m_last_height = 0.0f;
+#else
     m_last_mm3_per_mm = GCodeAnalyzer::Default_mm3_per_mm;
     m_last_width = GCodeAnalyzer::Default_Width;
     m_last_height = GCodeAnalyzer::Default_Height;
+#endif // ENABLE_GCODE_VIEWER
 
     // How many times will be change_layer() called?
     // change_layer() in turn increments the progress bar status.
@@ -1333,13 +1340,13 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
     // Set extruder(s) temperature before and after start G-code.
     this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, false);
 
-    if (m_enable_analyzer)
-        // adds tag for analyzer
-        _write_format(file, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erCustom);
-
 #if ENABLE_GCODE_VIEWER
     // adds tag for processor
     _write_format(file, ";%s%d\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), erCustom);
+#else
+    if (m_enable_analyzer)
+        // adds tag for analyzer
+        _write_format(file, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erCustom);
 #endif // ENABLE_GCODE_VIEWER
 
     // Write the custom start G-code
@@ -1491,13 +1498,13 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
     _write(file, this->retract());
     _write(file, m_writer.set_fan(false));
 
-    if (m_enable_analyzer)
-        // adds tag for analyzer
-        _write_format(file, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erCustom);
-
 #if ENABLE_GCODE_VIEWER
     // adds tag for processor
     _write_format(file, ";%s%d\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), erCustom);
+#else
+    if (m_enable_analyzer)
+        // adds tag for analyzer
+        _write_format(file, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erCustom);
 #endif // ENABLE_GCODE_VIEWER
 
     // Process filament-specific gcode in extruder order.
@@ -1821,11 +1828,12 @@ namespace ProcessLayer
 	        {
                 assert(m600_extruder_before_layer >= 0);
 		        // Color Change or Tool Change as Color Change.
-	            // add tag for analyzer
-	            gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
 #if ENABLE_GCODE_VIEWER
                 // add tag for processor
                 gcode += "; " + GCodeProcessor::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
+#else
+                // add tag for analyzer
+                gcode += "; " + GCodeAnalyzer::Color_Change_Tag + ",T" + std::to_string(m600_extruder_before_layer) + "\n";
 #endif // ENABLE_GCODE_VIEWER
                 // add tag for time estimator
 	            gcode += "; " + GCodeTimeEstimator::Color_Change_Tag + "\n";
@@ -1846,11 +1854,12 @@ namespace ProcessLayer
 	        {
 	            if (custom_code == PausePrintCode) // Pause print
 	            {
-	                // add tag for analyzer
-	                gcode += "; " + GCodeAnalyzer::Pause_Print_Tag + "\n";
 #if ENABLE_GCODE_VIEWER
                     // add tag for processor
                     gcode += "; " + GCodeProcessor::Pause_Print_Tag + "\n";
+#else
+                    // add tag for analyzer
+                    gcode += "; " + GCodeAnalyzer::Pause_Print_Tag + "\n";
 #endif // ENABLE_GCODE_VIEWER
                     //! FIXME_in_fw show message during print pause
 	                if (!pause_print_msg.empty())
@@ -1860,11 +1869,12 @@ namespace ProcessLayer
 	            }
 	            else // custom Gcode
 	            {
-	                // add tag for analyzer
-	                gcode += "; " + GCodeAnalyzer::Custom_Code_Tag + "\n";
 #if ENABLE_GCODE_VIEWER
                     // add tag for processor
                     gcode += "; " + GCodeProcessor::Custom_Code_Tag + "\n";
+#else
+                    // add tag for analyzer
+                    gcode += "; " + GCodeAnalyzer::Custom_Code_Tag + "\n";
 #endif // ENABLE_GCODE_VIEWER
                     // add tag for time estimator
 	                //gcode += "; " + GCodeTimeEstimator::Custom_Code_Tag + "\n";
@@ -2218,9 +2228,15 @@ void GCode::process_layer(
             m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back()) :
             this->set_extruder(extruder_id, print_z);
 
+#if ENABLE_GCODE_VIEWER
+        // let analyzer tag generator aware of a role type change
+        if (layer_tools.has_wipe_tower && m_wipe_tower)
+            m_last_processor_extrusion_role = erWipeTower;
+#else
         // let analyzer tag generator aware of a role type change
         if (m_enable_analyzer && layer_tools.has_wipe_tower && m_wipe_tower)
             m_last_analyzer_extrusion_role = erWipeTower;
+#endif // ENABLE_GCODE_VIEWER
 
         if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) {
             const std::pair<size_t, size_t> loops = loops_it->second;
@@ -2324,11 +2340,13 @@ void GCode::process_layer(
     if (m_cooling_buffer)
         gcode = m_cooling_buffer->process_layer(gcode, layer.id());
 
+#if !ENABLE_GCODE_VIEWER
     // add tag for analyzer
     if (gcode.find(GCodeAnalyzer::Pause_Print_Tag) != gcode.npos)
         gcode += "\n; " + GCodeAnalyzer::End_Pause_Print_Or_Custom_Code_Tag + "\n";
     else if (gcode.find(GCodeAnalyzer::Custom_Code_Tag) != gcode.npos)
         gcode += "\n; " + GCodeAnalyzer::End_Pause_Print_Or_Custom_Code_Tag + "\n";
+#endif // !ENABLE_GCODE_VIEWER
 
 #ifdef HAS_PRESSURE_EQUALIZER
     // Apply pressure equalization if enabled;
@@ -2342,9 +2360,11 @@ void GCode::process_layer(
     BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z << 
         ", time estimator memory: " <<
             format_memsize_MB(m_normal_time_estimator.memory_used() + (m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0)) <<
-        ", analyzer memory: " <<
+#if !ENABLE_GCODE_VIEWER
+            ", analyzer memory: " <<
             format_memsize_MB(m_analyzer.memory_used()) <<
-        log_memory_info();
+#endif // !ENABLE_GCODE_VIEWER
+            log_memory_info();
 }
 
 void GCode::apply_print_config(const PrintConfig &print_config)
@@ -2984,8 +3004,12 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
 void GCode::_write(FILE* file, const char *what)
 {
     if (what != nullptr) {
+#if ENABLE_GCODE_VIEWER
+        const char* gcode = what;
+#else
         // apply analyzer, if enabled
         const char* gcode = m_enable_analyzer ? m_analyzer.process_gcode(what).c_str() : what;
+#endif // !ENABLE_GCODE_VIEWER
 
         // writes string to file
         fwrite(gcode, 1, ::strlen(gcode), file);
@@ -3132,57 +3156,73 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
     }
 
     // adds analyzer tags and updates analyzer's tracking data
+#if !ENABLE_GCODE_VIEWER
     if (m_enable_analyzer)
     {
+#endif // !ENABLE_GCODE_VIEWER
         // PrusaMultiMaterial::Writer may generate GCodeAnalyzer::Height_Tag and GCodeAnalyzer::Width_Tag lines without updating m_last_height and m_last_width
         // so, if the last role was erWipeTower we force export of GCodeAnalyzer::Height_Tag and GCodeAnalyzer::Width_Tag lines
+#if ENABLE_GCODE_VIEWER
+        bool last_was_wipe_tower = (m_last_processor_extrusion_role == erWipeTower);
+#else
         bool last_was_wipe_tower = (m_last_analyzer_extrusion_role == erWipeTower);
+#endif // ENABLE_GCODE_VIEWER
         char buf[64];
 
+#if ENABLE_GCODE_VIEWER
+        if (path.role() != m_last_processor_extrusion_role)
+        {
+            m_last_processor_extrusion_role = path.role();
+            sprintf(buf, ";%s%d\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), int(m_last_processor_extrusion_role));
+            gcode += buf;
+        }
+#else
         if (path.role() != m_last_analyzer_extrusion_role)
         {
             m_last_analyzer_extrusion_role = path.role();
             sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), int(m_last_analyzer_extrusion_role));
-#if ENABLE_GCODE_VIEWER
-            gcode += buf;
-            sprintf(buf, ";%s%d\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), int(m_last_analyzer_extrusion_role));
-#endif // ENABLE_GCODE_VIEWER
             gcode += buf;
         }
+#endif // ENABLE_GCODE_VIEWER
 
         if (last_was_wipe_tower || (m_last_mm3_per_mm != path.mm3_per_mm))
         {
             m_last_mm3_per_mm = path.mm3_per_mm;
-            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Mm3_Per_Mm_Tag.c_str(), m_last_mm3_per_mm);
-            gcode += buf;
 #if ENABLE_GCODE_VIEWER
             sprintf(buf, ";%s%f\n", GCodeProcessor::Mm3_Per_Mm_Tag.c_str(), m_last_mm3_per_mm);
             gcode += buf;
+#else
+            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Mm3_Per_Mm_Tag.c_str(), m_last_mm3_per_mm);
+            gcode += buf;
 #endif // ENABLE_GCODE_VIEWER
         }
 
         if (last_was_wipe_tower || (m_last_width != path.width))
         {
             m_last_width = path.width;
-            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Width_Tag.c_str(), m_last_width);
-            gcode += buf;
 #if ENABLE_GCODE_VIEWER
             sprintf(buf, ";%s%f\n", GCodeProcessor::Width_Tag.c_str(), m_last_width);
             gcode += buf;
+#else
+            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Width_Tag.c_str(), m_last_width);
+            gcode += buf;
 #endif // ENABLE_GCODE_VIEWER
         }
 
         if (last_was_wipe_tower || (m_last_height != path.height))
         {
             m_last_height = path.height;
-            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Height_Tag.c_str(), m_last_height);
-            gcode += buf;
 #if ENABLE_GCODE_VIEWER
             sprintf(buf, ";%s%f\n", GCodeProcessor::Height_Tag.c_str(), m_last_height);
             gcode += buf;
+#else
+            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Height_Tag.c_str(), m_last_height);
+            gcode += buf;
 #endif // ENABLE_GCODE_VIEWER
         }
+#if !ENABLE_GCODE_VIEWER
     }
+#endif // !ENABLE_GCODE_VIEWER
 
     std::string comment;
     if (m_enable_cooling_markers) {
diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp
index f6668ad3d..546c42575 100644
--- a/src/libslic3r/GCode.hpp
+++ b/src/libslic3r/GCode.hpp
@@ -16,10 +16,11 @@
 #include "GCode/WipeTower.hpp"
 #if ENABLE_GCODE_VIEWER
 #include "GCode/GCodeProcessor.hpp"
+#else
+#include "GCode/Analyzer.hpp"
 #endif // ENABLE_GCODE_VIEWER
 #include "GCodeTimeEstimator.hpp"
 #include "EdgeGrid.hpp"
-#include "GCode/Analyzer.hpp"
 #include "GCode/ThumbnailData.hpp"
 
 #include <memory>
@@ -33,7 +34,9 @@ namespace Slic3r {
 
 // Forward declarations.
 class GCode;
+#if !ENABLE_GCODE_VIEWER
 class GCodePreviewData;
+#endif // !ENABLE_GCODE_VIEWER
 
 class AvoidCrossingPerimeters {
 public:
@@ -138,6 +141,15 @@ private:
     double                                                       m_last_wipe_tower_print_z = 0.f;
 };
 
+#if ENABLE_GCODE_VIEWER
+class ColorPrintColors
+{
+    static const std::vector<std::string> Colors;
+public:
+    static const std::vector<std::string>& get() { return Colors; }
+};
+#endif // ENABLE_GCODE_VIEWER
+
 class GCode {
 public:        
     GCode() : 
@@ -145,17 +157,27 @@ public:
         m_enable_loop_clipping(true), 
         m_enable_cooling_markers(false), 
         m_enable_extrusion_role_markers(false), 
+#if ENABLE_GCODE_VIEWER
+        m_last_processor_extrusion_role(erNone),
+#else
         m_enable_analyzer(false),
         m_last_analyzer_extrusion_role(erNone),
+#endif // ENABLE_GCODE_VIEWER
         m_layer_count(0),
         m_layer_index(-1), 
         m_layer(nullptr), 
         m_volumetric_speed(0),
         m_last_pos_defined(false),
         m_last_extrusion_role(erNone),
+#if ENABLE_GCODE_VIEWER
+        m_last_mm3_per_mm(0.0f),
+        m_last_width(0.0f),
+        m_last_height(0.0f),
+#else
         m_last_mm3_per_mm(GCodeAnalyzer::Default_mm3_per_mm),
         m_last_width(GCodeAnalyzer::Default_Width),
         m_last_height(GCodeAnalyzer::Default_Height),
+#endif // ENABLE_GCODE_VIEWER
         m_brim_done(false),
         m_second_layer_things_done(false),
         m_normal_time_estimator(GCodeTimeEstimator::Normal),
@@ -168,7 +190,7 @@ public:
     // throws std::runtime_exception on error,
     // throws CanceledException through print->throw_if_canceled().
 #if ENABLE_GCODE_VIEWER
-    void            do_export(Print* print, const char* path, GCodePreviewData* preview_data = nullptr, GCodeProcessor::Result* result = nullptr, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
+    void            do_export(Print* print, const char* path, GCodeProcessor::Result* result = nullptr, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
 #else
     void            do_export(Print* print, const char* path, GCodePreviewData* preview_data = nullptr, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
 #endif // ENABLE_GCODE_VIEWER
@@ -331,11 +353,16 @@ private:
     // Markers for the Pressure Equalizer to recognize the extrusion type.
     // The Pressure Equalizer removes the markers from the final G-code.
     bool                                m_enable_extrusion_role_markers;
+#if ENABLE_GCODE_VIEWER
+    // Keeps track of the last extrusion role passed to the processor
+    ExtrusionRole                       m_last_processor_extrusion_role;
+#else
     // Enableds the G-code Analyzer.
     // Extended markers will be added during G-code generation.
     // The G-code Analyzer will remove these comments from the final G-code.
     bool                                m_enable_analyzer;
     ExtrusionRole                       m_last_analyzer_extrusion_role;
+#endif // ENABLE_GCODE_VIEWER
     // How many times will change_layer() be called?
     // change_layer() will update the progress bar.
     unsigned int                        m_layer_count;
@@ -377,12 +404,12 @@ private:
     GCodeTimeEstimator m_silent_time_estimator;
     bool m_silent_time_estimator_enabled;
 
-    // Analyzer
-    GCodeAnalyzer m_analyzer;
-
 #if ENABLE_GCODE_VIEWER
     // Processor
     GCodeProcessor m_processor;
+#else
+    // Analyzer
+    GCodeAnalyzer m_analyzer;
 #endif // ENABLE_GCODE_VIEWER
 
     // Write a string into a file.
diff --git a/src/libslic3r/GCode/Analyzer.cpp b/src/libslic3r/GCode/Analyzer.cpp
index 974176dbd..d022b3798 100644
--- a/src/libslic3r/GCode/Analyzer.cpp
+++ b/src/libslic3r/GCode/Analyzer.cpp
@@ -8,19 +8,11 @@
 #include "Print.hpp"
 
 #include <boost/log/trivial.hpp>
-#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-#include <boost/filesystem/path.hpp>
-#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
 
 #include "Analyzer.hpp"
 #include "PreviewData.hpp"
 
-#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-#include <boost/nowide/fstream.hpp>
-
-// don't worry, this is just temporary
-static boost::nowide::ofstream g_debug_output;
-#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
+#if !ENABLE_GCODE_VIEWER
 
 static const std::string AXIS_STR = "XYZE";
 static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
@@ -184,19 +176,6 @@ bool GCodeAnalyzer::is_valid_extrusion_role(ExtrusionRole role)
     return ((erPerimeter <= role) && (role < erMixed));
 }
 
-#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-void GCodeAnalyzer::open_debug_output_file()
-{
-    boost::filesystem::path path("d:/analyzer.output");
-    g_debug_output.open(path.string());
-}
-
-void GCodeAnalyzer::close_debug_output_file()
-{
-    g_debug_output.close();
-}
-#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-
 void GCodeAnalyzer::_process_gcode_line(GCodeReader&, const GCodeReader::GCodeLine& line)
 {
     // processes 'special' comments contained in line
@@ -945,23 +924,6 @@ void GCodeAnalyzer::_store_move(GCodeAnalyzer::GCodeMove::EType type)
     Vec3f start_position = _get_start_position() + extruder_offset;
     Vec3f end_position = _get_end_position() + extruder_offset;
     it->second.emplace_back(type, _get_extrusion_role(), extruder_id, _get_mm3_per_mm(), _get_width(), _get_height(), _get_feedrate(), start_position, end_position, _get_delta_extrusion(), _get_fan_speed(), _get_cp_color_id());
-
-#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-    if (g_debug_output.good())
-    {
-        g_debug_output << std::to_string(static_cast<int>(type));
-        g_debug_output << ", " << std::to_string(static_cast<int>(_get_extrusion_role()));
-        g_debug_output << ", " << Slic3r::to_string(static_cast<Vec3d>(end_position.cast<double>()));
-        g_debug_output << ", " << std::to_string(extruder_id);
-        g_debug_output << ", " << std::to_string(_get_cp_color_id());
-        g_debug_output << ", " << std::to_string(_get_feedrate());
-        g_debug_output << ", " << std::to_string(_get_width());
-        g_debug_output << ", " << std::to_string(_get_height());
-        g_debug_output << ", " << std::to_string(_get_mm3_per_mm());
-        g_debug_output << ", " << std::to_string(_get_fan_speed());
-        g_debug_output << "\n";
-    }
-#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
 }
 
 bool GCodeAnalyzer::_is_valid_extrusion_role(int value) const
@@ -1231,3 +1193,5 @@ size_t GCodeAnalyzer::memory_used() const
 }
 
 } // namespace Slic3r
+
+#endif // !ENABLE_GCODE_VIEWER
diff --git a/src/libslic3r/GCode/Analyzer.hpp b/src/libslic3r/GCode/Analyzer.hpp
index 9d16ab494..37d907259 100644
--- a/src/libslic3r/GCode/Analyzer.hpp
+++ b/src/libslic3r/GCode/Analyzer.hpp
@@ -1,6 +1,8 @@
 #ifndef slic3r_GCode_Analyzer_hpp_
 #define slic3r_GCode_Analyzer_hpp_
 
+#if !ENABLE_GCODE_VIEWER
+
 #include "../libslic3r.h"
 #include "../PrintConfig.hpp"
 #include "../ExtrusionEntity.hpp"
@@ -147,11 +149,6 @@ public:
 
     static bool is_valid_extrusion_role(ExtrusionRole role);
 
-#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-    void open_debug_output_file();
-    void close_debug_output_file();
-#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-
 private:
     // Processes the given gcode line
     void _process_gcode_line(GCodeReader& reader, const GCodeReader::GCodeLine& line);
@@ -307,4 +304,6 @@ private:
 
 } // namespace Slic3r
 
+#endif // !ENABLE_GCODE_VIEWER
+
 #endif /* slic3r_GCode_Analyzer_hpp_ */
diff --git a/src/libslic3r/GCode/PreviewData.cpp b/src/libslic3r/GCode/PreviewData.cpp
index 3aae15748..58b15e9a4 100644
--- a/src/libslic3r/GCode/PreviewData.cpp
+++ b/src/libslic3r/GCode/PreviewData.cpp
@@ -5,6 +5,8 @@
 
 #include <boost/format.hpp>
 
+#if !ENABLE_GCODE_VIEWER
+
 //! macro used to mark string used at localization, 
 #define L(s) (s)
 
@@ -515,3 +517,5 @@ Color operator * (float f, const Color& color)
 }
 
 } // namespace Slic3r
+
+#endif // !ENABLE_GCODE_VIEWER
diff --git a/src/libslic3r/GCode/PreviewData.hpp b/src/libslic3r/GCode/PreviewData.hpp
index c0f768088..930c1659e 100644
--- a/src/libslic3r/GCode/PreviewData.hpp
+++ b/src/libslic3r/GCode/PreviewData.hpp
@@ -1,6 +1,8 @@
 #ifndef slic3r_GCode_PreviewData_hpp_
 #define slic3r_GCode_PreviewData_hpp_
 
+#if !ENABLE_GCODE_VIEWER
+
 #include "../libslic3r.h"
 #include "../ExtrusionEntity.hpp"
 #include "../Point.hpp"
@@ -391,4 +393,6 @@ public:
 
 } // namespace Slic3r
 
+#endif // !ENABLE_GCODE_VIEWER
+
 #endif /* slic3r_GCode_PreviewData_hpp_ */
diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp
index d5d060f77..3b5c2a159 100644
--- a/src/libslic3r/GCode/WipeTower.cpp
+++ b/src/libslic3r/GCode/WipeTower.cpp
@@ -21,9 +21,10 @@ TODO LIST
 #include <vector>
 #include <numeric>
 
-#include "Analyzer.hpp"
 #if ENABLE_GCODE_VIEWER
 #include "GCodeProcessor.hpp"
+#else
+#include "Analyzer.hpp"
 #endif // ENABLE_GCODE_VIEWER
 #include "BoundingBox.hpp"
 
@@ -56,16 +57,16 @@ public:
         {
             // adds tag for analyzer:
             char buf[64];
-            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Height_Tag.c_str(), m_layer_height); // don't rely on GCodeAnalyzer knowing the layer height - it knows nothing at priming
-            m_gcode += buf;
 #if ENABLE_GCODE_VIEWER
             sprintf(buf, ";%s%f\n", GCodeProcessor::Height_Tag.c_str(), m_layer_height); // don't rely on GCodeAnalyzer knowing the layer height - it knows nothing at priming
-            m_gcode += buf;
+#else
+            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Height_Tag.c_str(), m_layer_height); // don't rely on GCodeAnalyzer knowing the layer height - it knows nothing at priming
 #endif // ENABLE_GCODE_VIEWER
-            sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower);
-#if ENABLE_GCODE_VIEWER
             m_gcode += buf;
+#if ENABLE_GCODE_VIEWER
             sprintf(buf, ";%s%d\n", GCodeProcessor::Extrusion_Role_Tag.c_str(), erWipeTower);
+#else
+            sprintf(buf, ";%s%d\n", GCodeAnalyzer::Extrusion_Role_Tag.c_str(), erWipeTower);
 #endif // ENABLE_GCODE_VIEWER
             m_gcode += buf;
             change_analyzer_line_width(line_width);
@@ -74,12 +75,12 @@ public:
     WipeTowerWriter&              change_analyzer_line_width(float line_width) {
             // adds tag for analyzer:
             char buf[64];
-            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Width_Tag.c_str(), line_width);
-            m_gcode += buf;
 #if ENABLE_GCODE_VIEWER
             sprintf(buf, ";%s%f\n", GCodeProcessor::Width_Tag.c_str(), line_width);
-            m_gcode += buf;
+#else
+            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Width_Tag.c_str(), line_width);
 #endif // ENABLE_GCODE_VIEWER
+            m_gcode += buf;
             return *this;
     }
 
@@ -88,12 +89,12 @@ public:
             float mm3_per_mm = (len == 0.f ? 0.f : area * e / len);
             // adds tag for analyzer:
             char buf[64];
-            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Mm3_Per_Mm_Tag.c_str(), mm3_per_mm);
-            m_gcode += buf;
 #if ENABLE_GCODE_VIEWER
             sprintf(buf, ";%s%f\n", GCodeProcessor::Mm3_Per_Mm_Tag.c_str(), mm3_per_mm);
-            m_gcode += buf;
+#else
+            sprintf(buf, ";%s%f\n", GCodeAnalyzer::Mm3_Per_Mm_Tag.c_str(), mm3_per_mm);
 #endif // ENABLE_GCODE_VIEWER
+            m_gcode += buf;
             return *this;
     }
 
diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp
index 98f595d91..90c9d0357 100644
--- a/src/libslic3r/Model.cpp
+++ b/src/libslic3r/Model.cpp
@@ -20,7 +20,9 @@
 #include "SVG.hpp"
 #include <Eigen/Dense>
 #include "GCodeWriter.hpp"
+#if !ENABLE_GCODE_VIEWER
 #include "GCode/PreviewData.hpp"
+#endif // !ENABLE_GCODE_VIEWER
 
 namespace Slic3r {
 
diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp
index 6bc049412..0ffb5472c 100644
--- a/src/libslic3r/Print.cpp
+++ b/src/libslic3r/Print.cpp
@@ -1628,7 +1628,7 @@ void Print::process()
 // write error into the G-code, cannot execute post-processing scripts).
 // It is up to the caller to show an error message.
 #if ENABLE_GCODE_VIEWER
-std::string Print::export_gcode(const std::string& path_template, GCodePreviewData* preview_data, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb)
+std::string Print::export_gcode(const std::string& path_template, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb)
 #else
 std::string Print::export_gcode(const std::string& path_template, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb)
 #endif // ENABLE_GCODE_VIEWER
@@ -1637,7 +1637,11 @@ std::string Print::export_gcode(const std::string& path_template, GCodePreviewDa
     // The following call may die if the output_filename_format template substitution fails.
     std::string path = this->output_filepath(path_template);
     std::string message;
+#if ENABLE_GCODE_VIEWER
+    if (!path.empty() && result == nullptr) {
+#else
     if (! path.empty() && preview_data == nullptr) {
+#endif // ENABLE_GCODE_VIEWER
         // Only show the path if preview_data is not set -> running from command line.
         message = L("Exporting G-code");
         message += " to ";
@@ -1649,7 +1653,7 @@ std::string Print::export_gcode(const std::string& path_template, GCodePreviewDa
     // The following line may die for multiple reasons.
     GCode gcode;
 #if ENABLE_GCODE_VIEWER
-    gcode.do_export(this, path.c_str(), preview_data, result, thumbnail_cb);
+    gcode.do_export(this, path.c_str(), result, thumbnail_cb);
 #else
     gcode.do_export(this, path.c_str(), preview_data, thumbnail_cb);
 #endif // ENABLE_GCODE_VIEWER
diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp
index 9ae0f1394..c358cd918 100644
--- a/src/libslic3r/Print.hpp
+++ b/src/libslic3r/Print.hpp
@@ -372,7 +372,7 @@ public:
     // Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
     // If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
 #if ENABLE_GCODE_VIEWER
-    std::string         export_gcode(const std::string& path_template, GCodePreviewData* preview_data, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
+    std::string         export_gcode(const std::string& path_template, GCodeProcessor::Result* result, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
 #else
     std::string         export_gcode(const std::string& path_template, GCodePreviewData* preview_data, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
 #endif // ENABLE_GCODE_VIEWER
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index a648bb244..c22e504df 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -55,7 +55,6 @@
 
 // Enable G-Code viewer
 #define ENABLE_GCODE_VIEWER (1 && ENABLE_2_3_0_ALPHA1)
-#define ENABLE_GCODE_VIEWER_DEBUG_OUTPUT (0 && ENABLE_GCODE_VIEWER)
 #define ENABLE_GCODE_VIEWER_STATISTICS (0 && ENABLE_GCODE_VIEWER)
 
 #endif // _prusaslicer_technologies_h_
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index ca2f0389d..6aaf0b500 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -5,11 +5,15 @@
 #include "libslic3r/ExtrusionEntity.hpp"
 #include "libslic3r/ExtrusionEntityCollection.hpp"
 #include "libslic3r/Geometry.hpp"
+#if !ENABLE_GCODE_VIEWER
 #include "libslic3r/GCode/PreviewData.hpp"
+#endif // !ENABLE_GCODE_VIEWER
 #include "libslic3r/Print.hpp"
 #include "libslic3r/SLAPrint.hpp"
 #include "libslic3r/Slicing.hpp"
+#if !ENABLE_GCODE_VIEWER
 #include "libslic3r/GCode/Analyzer.hpp"
+#endif // !ENABLE_GCODE_VIEWER
 #include "slic3r/GUI/BitmapCache.hpp"
 #include "libslic3r/Format/STL.hpp"
 #include "libslic3r/Utils.hpp"
diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp
index c8c344caa..32b7b8365 100644
--- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp
+++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp
@@ -18,7 +18,9 @@
 #include "libslic3r/SLAPrint.hpp"
 #include "libslic3r/Utils.hpp"
 #include "libslic3r/GCode/PostProcessor.hpp"
+#if !ENABLE_GCODE_VIEWER
 #include "libslic3r/GCode/PreviewData.hpp"
+#endif // !ENABLE_GCODE_VIEWER
 #include "libslic3r/Format/SL1.hpp"
 #include "libslic3r/libslic3r.h"
 
@@ -89,7 +91,7 @@ void BackgroundSlicingProcess::process_fff()
     m_print->process();
 	wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_slicing_completed_id));
 #if ENABLE_GCODE_VIEWER
-	m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data, m_gcode_result, m_thumbnail_cb);
+	m_fff_print->export_gcode(m_temp_output_path, m_gcode_result, m_thumbnail_cb);
 #else
     m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data, m_thumbnail_cb);
 #endif // ENABLE_GCODE_VIEWER
@@ -385,9 +387,7 @@ Print::ApplyStatus BackgroundSlicingProcess::apply(const Model &model, const Dyn
 		// Some FFF status was invalidated, and the G-code was not exported yet.
 		// Let the G-code preview UI know that the final G-code preview is not valid.
 		// In addition, this early memory deallocation reduces memory footprint.
-		if (m_gcode_preview_data != nullptr)
-			m_gcode_preview_data->reset();
-		else if (m_gcode_result != nullptr)
+		if (m_gcode_result != nullptr)
 			m_gcode_result->reset();
 	}
 #else
diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp
index d3fca88fc..91ebc1372 100644
--- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp
+++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp
@@ -50,10 +50,11 @@ public:
 
 	void set_fff_print(Print *print) { m_fff_print = print; }
     void set_sla_print(SLAPrint *print) { m_sla_print = print; m_sla_print->set_printer(&m_sla_archive); }
-	void set_gcode_preview_data(GCodePreviewData *gpd) { m_gcode_preview_data = gpd; }
-    void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; }
+	void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; }
 #if ENABLE_GCODE_VIEWER
 	void set_gcode_result(GCodeProcessor::Result* result) { m_gcode_result = result; }
+#else
+	void set_gcode_preview_data(GCodePreviewData* gpd) { m_gcode_preview_data = gpd; }
 #endif // ENABLE_GCODE_VIEWER
 
 	// The following wxCommandEvent will be sent to the UI thread / Plater window, when the slicing is finished
@@ -156,15 +157,17 @@ private:
 	// Non-owned pointers to Print instances.
 	Print 					   *m_fff_print 		 = nullptr;
 	SLAPrint 				   *m_sla_print			 = nullptr;
+#if ENABLE_GCODE_VIEWER
+	// Data structure, to which the G-code export writes its annotations.
+	GCodeProcessor::Result     *m_gcode_result = nullptr;
+#else
 	// Data structure, to which the G-code export writes its annotations.
 	GCodePreviewData 		   *m_gcode_preview_data = nullptr;
-    // Callback function, used to write thumbnails into gcode.
+#endif // ENABLE_GCODE_VIEWER
+	// Callback function, used to write thumbnails into gcode.
 	ThumbnailsGeneratorCallback m_thumbnail_cb = nullptr;
 	SL1Archive                  m_sla_archive;
-#if ENABLE_GCODE_VIEWER
-	GCodeProcessor::Result* m_gcode_result = nullptr;
-#endif // ENABLE_GCODE_VIEWER
-	// Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID.
+		// Temporary G-code, there is one defined for the BackgroundSlicingProcess, differentiated from the other processes by a process ID.
 	std::string 				m_temp_output_path;
 	// Output path provided by the user. The output path may be set even if the slicing is running,
 	// but once set, it cannot be re-set.
diff --git a/src/slic3r/GUI/DoubleSlider.cpp b/src/slic3r/GUI/DoubleSlider.cpp
index 4c4c1aa8d..0a8933371 100644
--- a/src/slic3r/GUI/DoubleSlider.cpp
+++ b/src/slic3r/GUI/DoubleSlider.cpp
@@ -1,5 +1,9 @@
 #include "wxExtensions.hpp"
+#if ENABLE_GCODE_VIEWER
+#include "libslic3r/GCode.hpp"
+#else
 #include "libslic3r/GCode/PreviewData.hpp"
+#endif // ENABLE_GCODE_VIEWER
 #include "GUI.hpp"
 #include "GUI_App.hpp"
 #include "I18N.hpp"
@@ -1945,7 +1949,11 @@ std::string TickCodeInfo::get_color_for_tick(TickCode tick, const std::string& c
 {
     if (mode == t_mode::SingleExtruder && code == ColorChangeCode && m_use_default_colors)
     {
+#if ENABLE_GCODE_VIEWER
+        const std::vector<std::string>& colors = ColorPrintColors::get();
+#else
         const std::vector<std::string>& colors = GCodePreviewData::ColorPrintColors();
+#endif // ENABLE_GCODE_VIEWER
         if (ticks.empty())
             return colors[0];
         m_default_color_idx++;
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index d4cd84088..0893a7d46 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -167,7 +167,7 @@ const std::vector<GCodeViewer::Color> GCodeViewer::Extrusion_Role_Colors{ {
     { 0.69f, 0.19f, 0.16f },   // erInternalInfill
     { 0.84f, 0.20f, 0.84f },   // erSolidInfill
     { 1.00f, 0.10f, 0.10f },   // erTopSolidInfill
-    { 0.00f, 1.00f, 1.00f },   // erIroning    
+    { 1.00f, 0.55f, 0.41f },   // erIroning    
     { 0.60f, 0.60f, 1.00f },   // erBridgeInfill
     { 1.00f, 1.00f, 1.00f },   // erGapFill
     { 0.52f, 0.48f, 0.13f },   // erSkirt
@@ -404,7 +404,8 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
     std::vector<float> vertices_data(m_vertices.vertices_count * 3);
     for (size_t i = 0; i < m_vertices.vertices_count; ++i) {
         const GCodeProcessor::MoveVertex& move = gcode_result.moves[i];
-        m_bounding_box.merge(move.position.cast<double>());
+        if (move.type == GCodeProcessor::EMoveType::Extrude)
+            m_bounding_box.merge(move.position.cast<double>());
         ::memcpy(static_cast<void*>(&vertices_data[i * 3]), static_cast<const void*>(move.position.data()), 3 * sizeof(float));
     }
 
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 8859a0746..8be8f8b37 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -5,7 +5,9 @@
 #include "polypartition.h"
 #include "libslic3r/ClipperUtils.hpp"
 #include "libslic3r/PrintConfig.hpp"
+#if !ENABLE_GCODE_VIEWER
 #include "libslic3r/GCode/PreviewData.hpp"
+#endif // !ENABLE_GCODE_VIEWER
 #include "libslic3r/GCode/ThumbnailData.hpp"
 #include "libslic3r/Geometry.hpp"
 #include "libslic3r/ExtrusionEntity.hpp"
@@ -56,10 +58,6 @@
 #include <boost/log/trivial.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 
-#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-#include <boost/nowide/fstream.hpp>
-#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-
 #include <iostream>
 #include <float.h>
 #include <algorithm>
@@ -2747,22 +2745,8 @@ static void load_gcode_retractions(const GCodePreviewData::Retraction& retractio
 #if ENABLE_GCODE_VIEWER
 void GLCanvas3D::load_gcode_preview(const GCodeProcessor::Result& gcode_result)
 {
-#if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
-    static unsigned int last_result_id = 0;
-    if (last_result_id != gcode_result.id)
-    {
-        last_result_id = gcode_result.id;
-        boost::filesystem::path path("d:/processor.output");
-        boost::nowide::ofstream out;
-        out.open(path.string());
-        for (const GCodeProcessor::MoveVertex& v : gcode_result.moves)
-        {
-            out << v.to_string() << "\n";
-        }
-        out.close();
-    }
-#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
     m_gcode_viewer.load(gcode_result, *this->fff_print(), m_initialized);
+    _show_warning_texture_if_needed(WarningTexture::ToolpathOutside);
 }
 
 void GLCanvas3D::refresh_gcode_preview(const GCodeProcessor::Result& gcode_result, const std::vector<std::string>& str_tool_colors)
@@ -2771,9 +2755,7 @@ void GLCanvas3D::refresh_gcode_preview(const GCodeProcessor::Result& gcode_resul
     set_as_dirty();
     request_extra_frame();
 }
-#endif // ENABLE_GCODE_VIEWER
-
-#if !ENABLE_GCODE_VIEWER
+#else
 void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors)
 {
     const Print *print = this->fff_print();
@@ -2842,7 +2824,7 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
             _generate_legend_texture(preview_data, tool_colors);
     }
 }
-#endif // !ENABLE_GCODE_VIEWER
+#endif // ENABLE_GCODE_VIEWER
 
 void GLCanvas3D::load_sla_preview()
 {
@@ -3144,7 +3126,24 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
         }
 #endif // ENABLE_RENDER_PICKING_PASS
         case 'Z':
+#if ENABLE_GCODE_VIEWER
+        case 'z':
+        {
+            if (!m_selection.is_empty())
+                zoom_to_selection();
+            else
+            {
+                if (!m_volumes.empty())
+                    zoom_to_volumes();
+                else
+                    _zoom_to_box(m_gcode_viewer.get_bounding_box());
+            }
+
+            break;
+        }
+#else
         case 'z': { m_selection.is_empty() ? zoom_to_volumes() : zoom_to_selection(); break; }
+#endif // ENABLE_GCODE_VIEWER
         default:  { evt.Skip(); break; }
         }
     }
@@ -5467,8 +5466,39 @@ void GLCanvas3D::_rectangular_selection_picking_pass() const
     _update_volumes_hover_state();
 }
 
+#if ENABLE_GCODE_VIEWER
+static BoundingBoxf3 print_volume(const DynamicPrintConfig& config)
+{
+    // tolerance to avoid false detection at bed edges
+    const double tolerance_x = 0.05;
+    const double tolerance_y = 0.05;
+
+    BoundingBoxf3 ret;
+    const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config.option("bed_shape"));
+    if (opt != nullptr)
+    {
+        BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
+        ret = BoundingBoxf3(Vec3d(unscale<double>(bed_box_2D.min(0)) - tolerance_x, unscale<double>(bed_box_2D.min(1)) - tolerance_y, 0.0), Vec3d(unscale<double>(bed_box_2D.max(0)) + tolerance_x, unscale<double>(bed_box_2D.max(1)) + tolerance_y, config.opt_float("max_print_height")));
+        // Allow the objects to protrude below the print bed
+        ret.min(2) = -1e10;
+    }
+    return ret;
+}
+#endif // ENABLE_GCODE_VIEWER
+
 void GLCanvas3D::_render_background() const
 {
+#if ENABLE_GCODE_VIEWER
+    bool use_error_color = m_dynamic_background_enabled;
+    if (!m_volumes.empty())
+        use_error_color &= _is_any_volume_outside();
+    else
+    {
+        BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3();
+        use_error_color &= (test_volume.radius() > 0.0) ? !test_volume.contains(m_gcode_viewer.get_bounding_box()) : false;
+    }
+#endif // ENABLE_GCODE_VIEWER
+
     glsafe(::glPushMatrix());
     glsafe(::glLoadIdentity());
     glsafe(::glMatrixMode(GL_PROJECTION));
@@ -5479,7 +5509,11 @@ void GLCanvas3D::_render_background() const
     glsafe(::glDisable(GL_DEPTH_TEST));
 
     ::glBegin(GL_QUADS);
+#if ENABLE_GCODE_VIEWER
+    if (use_error_color)
+#else
     if (m_dynamic_background_enabled && _is_any_volume_outside())
+#endif // ENABLE_GCODE_VIEWER
         ::glColor3fv(ERROR_BG_DARK_COLOR);
     else
         ::glColor3fv(DEFAULT_BG_DARK_COLOR);
@@ -5487,8 +5521,12 @@ void GLCanvas3D::_render_background() const
     ::glVertex2f(-1.0f, -1.0f);
     ::glVertex2f(1.0f, -1.0f);
 
+#if ENABLE_GCODE_VIEWER
+    if (use_error_color)
+#else
     if (m_dynamic_background_enabled && _is_any_volume_outside())
-        ::glColor3fv(ERROR_BG_LIGHT_COLOR);
+#endif // ENABLE_GCODE_VIEWER
+::glColor3fv(ERROR_BG_LIGHT_COLOR);
     else
         ::glColor3fv(DEFAULT_BG_LIGHT_COLOR);
 
@@ -6991,6 +7029,7 @@ void GLCanvas3D::_load_sla_shells()
     update_volumes_colors_by_extruder();
 }
 
+#if !ENABLE_GCODE_VIEWER
 void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& preview_data)
 {
     unsigned int size = (unsigned int)m_gcode_preview_volume_index.first_volumes.size();
@@ -7048,9 +7087,13 @@ void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& previe
         }
     }
 }
+#endif // !ENABLE_GCODE_VIEWER
 
 void GLCanvas3D::_update_toolpath_volumes_outside_state()
 {
+#if ENABLE_GCODE_VIEWER
+    BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3();
+#else
     // tolerance to avoid false detection at bed edges
     static const double tolerance_x = 0.05;
     static const double tolerance_y = 0.05;
@@ -7067,15 +7110,23 @@ void GLCanvas3D::_update_toolpath_volumes_outside_state()
             print_volume.min(2) = -1e10;
         }
     }
+#endif // ENABLE_GCODE_VIEWER
 
     for (GLVolume* volume : m_volumes.volumes)
     {
+#if ENABLE_GCODE_VIEWER
+        volume->is_outside = ((test_volume.radius() > 0.0) && volume->is_extrusion_path) ? !test_volume.contains(volume->bounding_box()) : false;
+#else
         volume->is_outside = ((print_volume.radius() > 0.0) && volume->is_extrusion_path) ? !print_volume.contains(volume->bounding_box()) : false;
+#endif // ENABLE_GCODE_VIEWER
     }
 }
 
 void GLCanvas3D::_update_sla_shells_outside_state()
 {
+#if ENABLE_GCODE_VIEWER
+    BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3();
+#else
     // tolerance to avoid false detection at bed edges
     static const double tolerance_x = 0.05;
     static const double tolerance_y = 0.05;
@@ -7092,17 +7143,34 @@ void GLCanvas3D::_update_sla_shells_outside_state()
             print_volume.min(2) = -1e10;
         }
     }
+#endif // ENABLE_GCODE_VIEWER
 
     for (GLVolume* volume : m_volumes.volumes)
     {
+#if ENABLE_GCODE_VIEWER
+        volume->is_outside = ((test_volume.radius() > 0.0) && volume->shader_outside_printer_detection_enabled) ? !test_volume.contains(volume->transformed_convex_hull_bounding_box()) : false;
+#else
         volume->is_outside = ((print_volume.radius() > 0.0) && volume->shader_outside_printer_detection_enabled) ? !print_volume.contains(volume->transformed_convex_hull_bounding_box()) : false;
+#endif // ENABLE_GCODE_VIEWER
     }
 }
 
 void GLCanvas3D::_show_warning_texture_if_needed(WarningTexture::Warning warning)
 {
     _set_current();
+#if ENABLE_GCODE_VIEWER
+    bool show = false;
+    if (!m_volumes.empty())
+        show = _is_any_volume_outside();
+    else
+    {
+        BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3();
+        show = (test_volume.radius() > 0.0) ? !test_volume.contains(m_gcode_viewer.get_bounding_box()) : false;
+    }
+    _set_warning_texture(warning, show);
+#else
     _set_warning_texture(warning, _is_any_volume_outside());
+#endif // ENABLE_GCODE_VIEWER
 }
 
 std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& colors)
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index ed034bd28..5684901f3 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -846,8 +846,10 @@ private:
 #endif // !ENABLE_GCODE_VIEWER
     // Load SLA objects and support structures for objects, for which the slaposSliceSupports step has been finished.
 	void _load_sla_shells();
+#if !ENABLE_GCODE_VIEWER
     // sets gcode geometry visibility according to user selection
     void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
+#endif // !ENABLE_GCODE_VIEWER
     void _update_toolpath_volumes_outside_state();
     void _update_sla_shells_outside_state();
     void _show_warning_texture_if_needed(WarningTexture::Warning warning);
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 05d607109..4f47c2d18 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -1,5 +1,7 @@
 #include "libslic3r/libslic3r.h"
+#if !ENABLE_GCODE_VIEWER
 #include "libslic3r/GCode/PreviewData.hpp"
+#endif // !ENABLE_GCODE_VIEWER
 #include "GUI_Preview.hpp"
 #include "GUI_App.hpp"
 #include "GUI.hpp"
@@ -172,8 +174,8 @@ void View3D::render()
 
 #if ENABLE_GCODE_VIEWER
 Preview::Preview(
-    wxWindow * parent, Model * model, DynamicPrintConfig * config,
-    BackgroundSlicingProcess * process, GCodePreviewData * gcode_preview_data, GCodeProcessor::Result * gcode_result, std::function<void()> schedule_background_process_func)
+    wxWindow* parent, Model* model, DynamicPrintConfig* config,
+    BackgroundSlicingProcess* process, GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process_func)
 #else
 Preview::Preview(
     wxWindow* parent, Model* model, DynamicPrintConfig* config,
@@ -200,9 +202,10 @@ Preview::Preview(
 #endif // ENABLE_GCODE_VIEWER
     , m_config(config)
     , m_process(process)
-    , m_gcode_preview_data(gcode_preview_data)
 #if ENABLE_GCODE_VIEWER
     , m_gcode_result(gcode_result)
+#else
+    , m_gcode_preview_data(gcode_preview_data)
 #endif // ENABLE_GCODE_VIEWER
     , m_number_extruders(1)
     , m_preferred_color_mode("feature")
@@ -401,8 +404,13 @@ void Preview::set_number_extruders(unsigned int number_extruders)
         int tool_idx = m_choice_view_type->FindString(_(L("Tool")));
         int type = (number_extruders > 1) ? tool_idx /* color by a tool number */  : 0; // color by a feature type
         m_choice_view_type->SetSelection(type);
+#if ENABLE_GCODE_VIEWER
+        if ((0 <= type) && (type < static_cast<int>(GCodeViewer::EViewType::Count)))
+            m_canvas->set_gcode_view_preview_type(static_cast<GCodeViewer::EViewType>(type));
+#else
         if ((0 <= type) && (type < (int)GCodePreviewData::Extrusion::Num_View_Types))
             m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
+#endif // ENABLE_GCODE_VIEWER
 
         m_preferred_color_mode = (type == tool_idx) ? "tool_or_feature" : "feature";
     }
@@ -679,8 +687,13 @@ void Preview::update_view_type(bool slice_completed)
     int type = m_choice_view_type->FindString(choice);
     if (m_choice_view_type->GetSelection() != type) {
         m_choice_view_type->SetSelection(type);
+#if ENABLE_GCODE_VIEWER
+        if ((0 <= type) && (type < static_cast<int>(GCodeViewer::EViewType::Count)))
+            m_canvas->set_gcode_view_preview_type(static_cast<GCodeViewer::EViewType>(type));
+#else
         if (0 <= type && type < (int)GCodePreviewData::Extrusion::Num_View_Types)
             m_gcode_preview_data->extrusion.view_type = (GCodePreviewData::Extrusion::EViewType)type;
+#endif // ENABLE_GCODE_VIEWER
         m_preferred_color_mode = "feature";
     }
 }
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index 90943de00..a11a474cc 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -124,8 +124,8 @@ class Preview : public wxPanel
 
 public:
 #if ENABLE_GCODE_VIEWER
-Preview(wxWindow * parent, Model * model, DynamicPrintConfig * config,
-    BackgroundSlicingProcess * process, GCodePreviewData * gcode_preview_data, GCodeProcessor::Result * gcode_result, std::function<void()> schedule_background_process = []() {});
+Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process, 
+    GCodeProcessor::Result* gcode_result, std::function<void()> schedule_background_process = []() {});
 #else
 Preview(wxWindow* parent, Model* model, DynamicPrintConfig* config,
         BackgroundSlicingProcess* process, GCodePreviewData* gcode_preview_data, std::function<void()> schedule_background_process = []() {});
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 7d6497731..c4a43fbb0 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -33,7 +33,9 @@
 #include "libslic3r/Format/STL.hpp"
 #include "libslic3r/Format/AMF.hpp"
 #include "libslic3r/Format/3mf.hpp"
+#if !ENABLE_GCODE_VIEWER
 #include "libslic3r/GCode/PreviewData.hpp"
+#endif // !ENABLE_GCODE_VIEWER
 #include "libslic3r/GCode/ThumbnailData.hpp"
 #include "libslic3r/Model.hpp"
 #include "libslic3r/SLA/Hollowing.hpp"
@@ -1528,9 +1530,10 @@ struct Plater::priv
     Slic3r::SLAPrint            sla_print;
     Slic3r::Model               model;
     PrinterTechnology           printer_technology = ptFFF;
-    Slic3r::GCodePreviewData    gcode_preview_data;
 #if ENABLE_GCODE_VIEWER
     Slic3r::GCodeProcessor::Result gcode_result;
+#else
+    Slic3r::GCodePreviewData    gcode_preview_data;
 #endif // ENABLE_GCODE_VIEWER
 
     // GUI elements
@@ -1840,9 +1843,10 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
 
     background_process.set_fff_print(&fff_print);
     background_process.set_sla_print(&sla_print);
-    background_process.set_gcode_preview_data(&gcode_preview_data);
 #if ENABLE_GCODE_VIEWER
     background_process.set_gcode_result(&gcode_result);
+#else
+    background_process.set_gcode_preview_data(&gcode_preview_data);
 #endif // ENABLE_GCODE_VIEWER
     background_process.set_thumbnail_cb([this](ThumbnailsList& thumbnails, const Vec2ds& sizes, bool printable_only, bool parts_only, bool show_bed, bool transparent_background)
         {
@@ -1868,7 +1872,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
 
     view3D = new View3D(q, &model, config, &background_process);
 #if ENABLE_GCODE_VIEWER
-    preview = new Preview(q, &model, config, &background_process, &gcode_preview_data, &gcode_result, [this]() { schedule_background_process(); });
+    preview = new Preview(q, &model, config, &background_process, &gcode_result, [this]() { schedule_background_process(); });
 #else
     preview = new Preview(q, &model, config, &background_process, &gcode_preview_data, [this]() { schedule_background_process(); });
 #endif // ENABLE_GCODE_VIEWER