diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index 0c631904a..dc7c0d973 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -10,6 +10,7 @@
 #include "GUI_Utils.hpp"
 #include "DoubleSlider.hpp"
 #include "GLCanvas3D.hpp"
+#include "GLToolbar.hpp"
 #include "libslic3r/Model.hpp"
 #if ENABLE_GCODE_VIEWER_STATISTICS
 #include <imgui/imgui_internal.h>
@@ -33,10 +34,10 @@ static GCodeProcessor::EMoveType buffer_type(unsigned char id) {
     return static_cast<GCodeProcessor::EMoveType>(static_cast<unsigned char>(GCodeProcessor::EMoveType::Retract) + id);
 }
 
-std::vector<std::array<float, 3>> decode_colors(const std::vector<std::string>& colors) {
+std::vector<std::array<float, 3>> decode_colors(const std::vector<std::string> & colors) {
     static const float INV_255 = 1.0f / 255.0f;
 
-    std::vector<std::array<float, 3>> output(colors.size(), {0.0f, 0.0f, 0.0f} );
+    std::vector<std::array<float, 3>> output(colors.size(), { 0.0f, 0.0f, 0.0f });
     for (size_t i = 0; i < colors.size(); ++i)
     {
         const std::string& color = colors[i];
@@ -102,6 +103,7 @@ void GCodeViewer::IBuffer::reset()
     data = std::vector<unsigned int>();
     data_size = 0;
     paths = std::vector<Path>();
+    render_paths = std::vector<RenderPath>();
 }
 
 bool GCodeViewer::IBuffer::init_shader(const std::string& vertex_shader_src, const std::string& fragment_shader_src)
@@ -114,13 +116,13 @@ bool GCodeViewer::IBuffer::init_shader(const std::string& vertex_shader_src, con
     return true;
 }
 
-void GCodeViewer::IBuffer::add_path(const GCodeProcessor::MoveVertex& move)
+void GCodeViewer::IBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsigned int v_id)
 {
-    Path::Endpoint endpoint = { static_cast<unsigned int>(data.size()), move.position };
+    Path::Endpoint endpoint = { static_cast<unsigned int>(data.size()), v_id, move.position };
     paths.push_back({ move.type, move.extrusion_role, endpoint, endpoint, move.delta_extruder, move.height, move.width, move.feedrate, move.fan_speed, move.volumetric_rate(), move.extruder_id, move.cp_color_id });
 }
 
-std::array<float, 3> GCodeViewer::Extrusions::Range::get_color_at(float value) const
+GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value) const
 {
     // Input value scaled to the colors range
     const float step = step_size();
@@ -136,14 +138,14 @@ std::array<float, 3> GCodeViewer::Extrusions::Range::get_color_at(float value) c
     const float local_t = std::clamp(global_t - static_cast<float>(color_low_idx), 0.0f, 1.0f);
 
     // Interpolate between the low and high colors to find exactly which color the input value should get
-    std::array<float, 3> ret;
+    Color ret;
     for (unsigned int i = 0; i < 3; ++i) {
         ret[i] = lerp(Range_Colors[color_low_idx][i], Range_Colors[color_high_idx][i], local_t);
     }
     return ret;
 }
 
-const std::vector<std::array<float, 3>> GCodeViewer::Extrusion_Role_Colors {{
+const std::vector<GCodeViewer::Color> GCodeViewer::Extrusion_Role_Colors{ {
     { 0.50f, 0.50f, 0.50f },   // erNone
     { 1.00f, 1.00f, 0.40f },   // erPerimeter
     { 1.00f, 0.65f, 0.00f },   // erExternalPerimeter
@@ -162,13 +164,13 @@ const std::vector<std::array<float, 3>> GCodeViewer::Extrusion_Role_Colors {{
     { 0.00f, 0.00f, 0.00f }    // erMixed
 }};
 
-const std::vector<std::array<float, 3>> GCodeViewer::Travel_Colors {{
+const std::vector<GCodeViewer::Color> GCodeViewer::Travel_Colors{ {
     { 0.0f, 0.0f, 0.5f }, // Move
     { 0.0f, 0.5f, 0.0f }, // Extrude
     { 0.5f, 0.0f, 0.0f }  // Retract
 }};
 
-const std::vector<std::array<float, 3>> GCodeViewer::Range_Colors {{
+const std::vector<GCodeViewer::Color> GCodeViewer::Range_Colors{ {
     { 0.043f, 0.173f, 0.478f }, // bluish
     { 0.075f, 0.349f, 0.522f },
     { 0.110f, 0.533f, 0.569f },
@@ -240,7 +242,7 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std:
     }
 
     // update buffers' render paths
-    refresh_render_paths();
+    refresh_render_paths(false);
 
 #if ENABLE_GCODE_VIEWER_STATISTICS
     m_statistics.refresh_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
@@ -256,7 +258,7 @@ void GCodeViewer::reset()
     }
 
     m_bounding_box = BoundingBoxf3();
-    m_tool_colors = std::vector<std::array<float, 3>>();
+    m_tool_colors = std::vector<Color>();
     m_extruder_ids = std::vector<unsigned char>();
     m_extrusions.reset_role_visibility_flags();
     m_extrusions.reset_ranges();
@@ -280,6 +282,7 @@ void GCodeViewer::render() const
     render_toolpaths();
     render_shells();
     render_legend();
+    render_sequential_dlg();
 #if ENABLE_GCODE_VIEWER_STATISTICS
     render_statistics();
 #endif // ENABLE_GCODE_VIEWER_STATISTICS
@@ -425,7 +428,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
         case GCodeProcessor::EMoveType::Retract:
         case GCodeProcessor::EMoveType::Unretract:
         {
-            buffer.add_path(curr);
+            buffer.add_path(curr, static_cast<unsigned int>(i));
             buffer.data.push_back(static_cast<unsigned int>(i));
             break;
         }
@@ -433,12 +436,14 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
         case GCodeProcessor::EMoveType::Travel:
         {
             if (prev.type != curr.type || !buffer.paths.back().matches(curr)) {
-                buffer.add_path(curr);
-                buffer.paths.back().first.position = prev.position;
+                buffer.add_path(curr, static_cast<unsigned int>(i));
+                Path& last_path = buffer.paths.back();
+                last_path.first.position = prev.position;
+                last_path.first.s_id = static_cast<unsigned int>(i - 1);
                 buffer.data.push_back(static_cast<unsigned int>(i - 1));
             }
             
-            buffer.paths.back().last = { static_cast<unsigned int>(buffer.data.size()), curr.position };
+            buffer.paths.back().last = { static_cast<unsigned int>(buffer.data.size()), static_cast<unsigned int>(i), curr.position };
             buffer.data.push_back(static_cast<unsigned int>(i));
             break;
         }
@@ -568,10 +573,10 @@ void GCodeViewer::load_shells(const Print& print, bool initialized)
     }
 }
 
-void GCodeViewer::refresh_render_paths() const
+void GCodeViewer::refresh_render_paths(bool keep_sequential_current) const
 {
     auto extrusion_color = [this](const Path& path) {
-        std::array<float, 3> color;
+        Color color;
         switch (m_view_type)
         {
         case EViewType::FeatureType:    { color = Extrusion_Role_Colors[static_cast<unsigned int>(path.role)]; break; }
@@ -593,26 +598,86 @@ void GCodeViewer::refresh_render_paths() const
                 Travel_Colors[0] /* Move */);
     };
 
+    auto is_valid_path = [this](const Path& path, size_t id) {
+        if (path.type == GCodeProcessor::EMoveType::Travel) {
+            if (!is_travel_in_z_range(id))
+                return false;
+        }
+        else if (!is_in_z_range(path))
+            return false;
+
+        if (path.type == GCodeProcessor::EMoveType::Extrude && !is_visible(path))
+            return false;
+
+        return true;
+    };
+
+#if ENABLE_GCODE_VIEWER_STATISTICS
+    m_statistics.render_paths_size = 0;
+#endif // ENABLE_GCODE_VIEWER_STATISTICS
+
+    m_sequential_view.first = m_vertices.vertices_count;
+    m_sequential_view.last = 0;
+    if (!keep_sequential_current)
+        m_sequential_view.current = m_vertices.vertices_count;
+
+    // first, detect current values for the sequential view
+    // to be used later to filter the paths
+    for (IBuffer& buffer : m_buffers) {
+        if (!buffer.visible)
+            continue;
+
+        for (size_t i = 0; i < buffer.paths.size(); ++i) {
+            const Path& path = buffer.paths[i];
+            if (!is_valid_path(path, i))
+                continue;
+//            if (path.type == GCodeProcessor::EMoveType::Travel) {
+//                if (!is_travel_in_z_range(i))
+//                    continue;
+//            }
+//            else if (!is_in_z_range(path))
+//                continue;
+//
+//            if (path.type == GCodeProcessor::EMoveType::Extrude && !is_visible(path))
+//                continue;
+
+            m_sequential_view.first = std::min(m_sequential_view.first, path.first.s_id);
+            m_sequential_view.last = std::max(m_sequential_view.last, path.last.s_id);
+        }
+    }
+
+    if (keep_sequential_current)
+        m_sequential_view.clamp_current();
+    else
+        m_sequential_view.current = m_sequential_view.last;
 
     for (IBuffer& buffer : m_buffers) {
         buffer.render_paths = std::vector<RenderPath>();
+        if (!buffer.visible)
+            continue;
         for (size_t i = 0; i < buffer.paths.size(); ++i) {
             const Path& path = buffer.paths[i];
-            if (path.type == GCodeProcessor::EMoveType::Travel) {
-                if (!is_travel_in_z_range(i))
-                    continue;
-            }
-            else if (!is_in_z_range(path))
+            if (!is_valid_path(path, i))
+                continue;
+//            if (path.type == GCodeProcessor::EMoveType::Travel) {
+//                if (!is_travel_in_z_range(i))
+//                    continue;
+//            }
+//            else if (!is_in_z_range(path))
+//                continue;
+//
+//            if (path.type == GCodeProcessor::EMoveType::Extrude && !is_visible(path))
+//                continue;
+
+            if ((m_sequential_view.current < path.first.s_id) || (path.last.s_id < m_sequential_view.first))
                 continue;
 
-            if (path.type == GCodeProcessor::EMoveType::Extrude && !is_visible(path))
-                continue;
-
-            std::array<float, 3> color = { 0.0f, 0.0f, 0.0f };
+            Color color;
             switch (path.type)
             {
             case GCodeProcessor::EMoveType::Extrude: { color = extrusion_color(path); break; }
             case GCodeProcessor::EMoveType::Travel:  { color = (m_view_type == EViewType::Feedrate || m_view_type == EViewType::Tool || m_view_type == EViewType::ColorPrint) ? extrusion_color(path) : travel_color(path); break; }
+            default:                                 { color = { 0.0f, 0.0f, 0.0f }; break; }
             }
 
             auto it = std::find_if(buffer.render_paths.begin(), buffer.render_paths.end(), [color](const RenderPath& path) { return path.color == color; });
@@ -621,15 +686,25 @@ void GCodeViewer::refresh_render_paths() const
                 it->color = color;
             }
 
-            it->sizes.push_back(path.last.id - path.first.id + 1);
-            it->offsets.push_back(static_cast<size_t>(path.first.id * sizeof(unsigned int)));
+            it->sizes.push_back(std::min(m_sequential_view.current, path.last.s_id) - path.first.s_id + 1);
+            it->offsets.push_back(static_cast<size_t>(path.first.i_id * sizeof(unsigned int)));
         }
     }
+
+#if ENABLE_GCODE_VIEWER_STATISTICS
+    for (const IBuffer& buffer : m_buffers) {
+        m_statistics.render_paths_size += SLIC3R_STDVEC_MEMSIZE(buffer.render_paths, RenderPath);
+        for (const RenderPath& path : buffer.render_paths) {
+            m_statistics.render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int);
+            m_statistics.render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t);
+        }
+    }
+#endif // ENABLE_GCODE_VIEWER_STATISTICS
 }
 
 void GCodeViewer::render_toolpaths() const
 {
-    auto set_color = [](GLint current_program_id, const std::array<float, 3>& color) {
+    auto set_color = [](GLint current_program_id, const Color& color) {
         if (current_program_id > 0) {
             GLint color_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "uniform_color") : -1;
             if (color_id >= 0) {
@@ -672,7 +747,7 @@ void GCodeViewer::render_toolpaths() const
             {
             case GCodeProcessor::EMoveType::Tool_change:
             {
-                std::array<float, 3> color = { 1.0f, 1.0f, 1.0f };
+                Color color = { 1.0f, 1.0f, 1.0f };
                 set_color(current_program_id, color);
                 for (const RenderPath& path : buffer.render_paths)
                 {
@@ -688,7 +763,7 @@ void GCodeViewer::render_toolpaths() const
             }
             case GCodeProcessor::EMoveType::Color_change:
             {
-                std::array<float, 3> color = { 1.0f, 0.0f, 0.0f };
+                Color color = { 1.0f, 0.0f, 0.0f };
                 set_color(current_program_id, color);
                 for (const RenderPath& path : buffer.render_paths)
                 {
@@ -704,7 +779,7 @@ void GCodeViewer::render_toolpaths() const
             }
             case GCodeProcessor::EMoveType::Pause_Print:
             {
-                std::array<float, 3> color = { 0.0f, 1.0f, 0.0f };
+                Color color = { 0.0f, 1.0f, 0.0f };
                 set_color(current_program_id, color);
                 for (const RenderPath& path : buffer.render_paths)
                 {
@@ -720,7 +795,7 @@ void GCodeViewer::render_toolpaths() const
             }
             case GCodeProcessor::EMoveType::Custom_GCode:
             {
-                std::array<float, 3> color = { 0.0f, 0.0f, 1.0f };
+                Color color = { 0.0f, 0.0f, 1.0f };
                 set_color(current_program_id, color);
                 for (const RenderPath& path : buffer.render_paths)
                 {
@@ -736,7 +811,7 @@ void GCodeViewer::render_toolpaths() const
             }
             case GCodeProcessor::EMoveType::Retract:
             {
-                std::array<float, 3> color = { 1.0f, 0.0f, 1.0f };
+                Color color = { 1.0f, 0.0f, 1.0f };
                 set_color(current_program_id, color);
                 for (const RenderPath& path : buffer.render_paths)
                 {
@@ -752,7 +827,7 @@ void GCodeViewer::render_toolpaths() const
             }
             case GCodeProcessor::EMoveType::Unretract:
             {
-                std::array<float, 3> color = { 0.0f, 1.0f, 1.0f };
+                Color color = { 0.0f, 1.0f, 1.0f };
                 set_color(current_program_id, color);
                 for (const RenderPath& path : buffer.render_paths)
                 {
@@ -827,13 +902,14 @@ void GCodeViewer::render_legend() const
 
     ImGuiWrapper& imgui = *wxGetApp().imgui();
 
-    imgui.set_next_window_pos(0, 0, ImGuiCond_Always);
+    imgui.set_next_window_pos(0.0f, 0.0f, ImGuiCond_Always);
     ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
+    ImGui::SetNextWindowBgAlpha(0.6f);
     imgui.begin(std::string("Legend"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
 
     ImDrawList* draw_list = ImGui::GetWindowDrawList();
 
-    auto add_item = [draw_list, &imgui](const std::array<float, 3>& color, const std::string& label, std::function<void()> callback = nullptr) {
+    auto add_item = [draw_list, &imgui](const Color& color, const std::string& label, std::function<void()> callback = nullptr) {
         float icon_size = ImGui::GetTextLineHeight();
         ImVec2 pos = ImGui::GetCursorPos();
         draw_list->AddRect({ pos.x, pos.y }, { pos.x + icon_size, pos.y + icon_size }, ICON_BORDER_COLOR, 0.0f, 0);
@@ -903,7 +979,7 @@ void GCodeViewer::render_legend() const
                 {
                     m_extrusions.role_visibility_flags = is_visible(role) ? m_extrusions.role_visibility_flags & ~(1 << role) : m_extrusions.role_visibility_flags | (1 << role);
                     // update buffers' render paths
-                    refresh_render_paths();
+                    refresh_render_paths(false);
                     wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
                     wxGetApp().plater()->update_preview_bottom_toolbar();
                 }
@@ -1044,6 +1120,51 @@ void GCodeViewer::render_legend() const
     ImGui::PopStyleVar();
 }
 
+void GCodeViewer::render_sequential_dlg() const
+{
+    static const float margin = 125.0f;
+
+    if (m_roles.empty())
+        return;
+
+    if (m_sequential_view.last <= m_sequential_view.first)
+        return;
+
+    ImGuiWrapper& imgui = *wxGetApp().imgui();
+    const ImGuiStyle& style = ImGui::GetStyle();
+
+    const GLToolbar& view_toolbar = wxGetApp().plater()->get_view_toolbar();
+    Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size();
+
+    float left = view_toolbar.get_width();
+    float width = static_cast<float>(cnv_size.get_width()) - left;
+
+    ImGui::SetNextWindowBgAlpha(0.5f);
+    imgui.set_next_window_pos(left, static_cast<float>(cnv_size.get_height()), ImGuiCond_Always, 0.0f, 1.0f);
+    ImGui::SetNextWindowSize({ width, -1.0f }, ImGuiCond_Always);
+    ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
+    imgui.begin(std::string("Sequential"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove);
+
+    std::string low_str = std::to_string(m_sequential_view.first);
+    ImGui::SetCursorPosX(margin - style.ItemSpacing.x - ImGui::CalcTextSize(low_str.c_str()).x);
+    ImGui::AlignTextToFramePadding();
+    imgui.text(low_str);
+    ImGui::SameLine(margin);
+    ImGui::PushItemWidth(-margin);
+    int index = static_cast<int>(m_sequential_view.current);
+    if (ImGui::SliderInt("##slider int", &index, static_cast<int>(m_sequential_view.first), static_cast<int>(m_sequential_view.last)))
+    {
+        m_sequential_view.current = static_cast<unsigned int>(index);
+        refresh_render_paths(true);
+    }
+    ImGui::PopItemWidth();
+    ImGui::SameLine();
+    imgui.text(std::to_string(m_sequential_view.last));
+
+    imgui.end();
+    ImGui::PopStyleVar();
+}
+
 #if ENABLE_GCODE_VIEWER_STATISTICS
 void GCodeViewer::render_statistics() const
 {
@@ -1055,6 +1176,7 @@ void GCodeViewer::render_statistics() const
 
     ImGuiWrapper& imgui = *wxGetApp().imgui();
 
+    imgui.set_next_window_pos(0.5f * wxGetApp().plater()->get_current_canvas3D()->get_canvas_size().get_width(), 0.0f, ImGuiCond_Once, 0.5f, 0.0f);
     imgui.begin(std::string("Statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
     ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow());
 
@@ -1113,10 +1235,10 @@ void GCodeViewer::render_statistics() const
     imgui.text(std::to_string(m_statistics.paths_size) + " bytes");
 
     ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
-    imgui.text(std::string("TOTAL CPU:"));
+    imgui.text(std::string("Render paths CPU:"));
     ImGui::PopStyleColor();
     ImGui::SameLine(offset);
-    imgui.text(std::to_string(m_statistics.vertices_size + m_statistics.indices_size + m_statistics.paths_size) + " bytes");
+    imgui.text(std::to_string(m_statistics.render_paths_size) + " bytes");
 
     ImGui::Separator();
 
@@ -1132,12 +1254,6 @@ void GCodeViewer::render_statistics() const
     ImGui::SameLine(offset);
     imgui.text(std::to_string(m_statistics.indices_gpu_size) + " bytes");
 
-    ImGui::PushStyleColor(ImGuiCol_Text, ORANGE);
-    imgui.text(std::string("TOTAL GPU:"));
-    ImGui::PopStyleColor();
-    ImGui::SameLine(offset);
-    imgui.text(std::to_string(m_statistics.vertices_gpu_size + m_statistics.indices_gpu_size) + " bytes");
-
     imgui.end();
 }
 #endif // ENABLE_GCODE_VIEWER_STATISTICS
diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp
index aa024a742..5e4ea5396 100644
--- a/src/slic3r/GUI/GCodeViewer.hpp
+++ b/src/slic3r/GUI/GCodeViewer.hpp
@@ -14,9 +14,10 @@ namespace GUI {
 
 class GCodeViewer
 {
-    static const std::vector<std::array<float, 3>> Extrusion_Role_Colors;
-    static const std::vector<std::array<float, 3>> Travel_Colors;
-    static const std::vector<std::array<float, 3>> Range_Colors;
+    using Color = std::array<float, 3>;
+    static const std::vector<Color> Extrusion_Role_Colors;
+    static const std::vector<Color> Travel_Colors;
+    static const std::vector<Color> Range_Colors;
 
     // buffer containing vertices data
     struct VBuffer
@@ -37,7 +38,10 @@ class GCodeViewer
     {
         struct Endpoint
         {
-            unsigned int id{ 0u };
+            // index into the ibo
+            unsigned int i_id{ 0u };
+            // sequential id
+            unsigned int s_id{ 0u };
             Vec3f position{ Vec3f::Zero() };
         };
 
@@ -55,12 +59,14 @@ class GCodeViewer
         unsigned char cp_color_id{ 0 };
 
         bool matches(const GCodeProcessor::MoveVertex& move) const;
+
+        unsigned int size() const { return last.i_id - first.i_id + 1; }
     };
 
     // Used to batch the indices needed to render paths
     struct RenderPath
     {
-        std::array<float, 3> color;
+        Color color;
         std::vector<unsigned int> sizes;
         std::vector<size_t> offsets; // use size_t because we need the pointer's size (used in the call glMultiDrawElements())
     };
@@ -78,9 +84,10 @@ class GCodeViewer
 
         void reset();
         bool init_shader(const std::string& vertex_shader_src, const std::string& fragment_shader_src);
-        void add_path(const GCodeProcessor::MoveVertex& move);
+        void add_path(const GCodeProcessor::MoveVertex& move, unsigned int s_id);
     };
 
+
     struct Shells
     {
         GLVolumeCollection volumes;
@@ -102,7 +109,7 @@ class GCodeViewer
             void reset() { min = FLT_MAX; max = -FLT_MAX; }
 
             float step_size() const { return (max - min) / (static_cast<float>(Range_Colors.size()) - 1.0f); }
-            std::array<float, 3> get_color_at(float value) const;
+            Color get_color_at(float value) const;
         };
 
         struct Ranges
@@ -141,6 +148,15 @@ class GCodeViewer
         void reset_ranges() { ranges.reset(); }
     };
 
+    struct SequentialView
+    {
+        unsigned int first{ 0 };
+        unsigned int last{ 0 };
+        unsigned int current{ 0 };
+
+        void clamp_current() { current = std::clamp(current, first, last); }
+    };
+
 #if ENABLE_GCODE_VIEWER_STATISTICS
     struct Statistics
     {
@@ -154,6 +170,7 @@ class GCodeViewer
         long long indices_size{ 0 };
         long long indices_gpu_size{ 0 };
         long long paths_size{ 0 };
+        long long render_paths_size{ 0 };
 
         void reset_all() {
             reset_times();
@@ -178,6 +195,7 @@ class GCodeViewer
             indices_size = 0;
             indices_gpu_size = 0;
             paths_size =  0;
+            render_paths_size = 0;
         }
     };
 #endif // ENABLE_GCODE_VIEWER_STATISTICS
@@ -201,12 +219,13 @@ private:
     VBuffer m_vertices;
     mutable std::vector<IBuffer> m_buffers{ static_cast<size_t>(GCodeProcessor::EMoveType::Extrude) };
     BoundingBoxf3 m_bounding_box;
-    std::vector<std::array<float, 3>> m_tool_colors;
+    std::vector<Color> m_tool_colors;
     std::vector<double> m_layers_zs;
     std::array<double, 2> m_layers_z_range;
     std::vector<ExtrusionRole> m_roles;
     std::vector<unsigned char> m_extruder_ids;
     mutable Extrusions m_extrusions;
+    mutable SequentialView m_sequential_view;
     Shells m_shells;
     EViewType m_view_type{ EViewType::FeatureType };
     bool m_legend_enabled{ true };
@@ -231,6 +250,8 @@ public:
     void reset();
     void render() const;
 
+    bool has_data() const { return !m_roles.empty(); }
+
     const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; }
     const std::vector<double>& get_layers_zs() const { return m_layers_zs; };
 
@@ -250,8 +271,9 @@ public:
     void set_options_visibility_from_flags(unsigned int flags);
     void set_layers_z_range(const std::array<double, 2>& layers_z_range)
     {
+        bool keep_sequential_current = layers_z_range[1] <= m_layers_z_range[1];
         m_layers_z_range = layers_z_range;
-        refresh_render_paths();
+        refresh_render_paths(keep_sequential_current);
     }
 
     bool is_legend_enabled() const { return m_legend_enabled; }
@@ -261,10 +283,11 @@ private:
     bool init_shaders();
     void load_toolpaths(const GCodeProcessor::Result& gcode_result);
     void load_shells(const Print& print, bool initialized);
-    void refresh_render_paths() const;
+    void refresh_render_paths(bool keep_sequential_current) const;
     void render_toolpaths() const;
     void render_shells() const;
     void render_legend() const;
+    void render_sequential_dlg() const;
 #if ENABLE_GCODE_VIEWER_STATISTICS
     void render_statistics() const;
 #endif // ENABLE_GCODE_VIEWER_STATISTICS
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 6881e86fd..875e4fd52 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -2363,8 +2363,9 @@ void GLCanvas3D::set_toolpath_view_type(GCodeViewer::EViewType type)
 
 void GLCanvas3D::set_toolpaths_z_range(const std::array<double, 2>& range)
 {
-    m_gcode_viewer.set_layers_z_range(range);
     m_volumes.set_range(range[0] - 1e-6, range[1] + 1e-6);
+    if (m_gcode_viewer.has_data())
+        m_gcode_viewer.set_layers_z_range(range);
 }
 #else
 std::vector<double> GLCanvas3D::get_current_print_zs(bool active_only) const