diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index a401cabba..9e05f60ad 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1719,7 +1719,7 @@ void GLCanvas3D::deselect_all()
     m_selection.set_mode(Selection::Instance);
     wxGetApp().obj_manipul()->set_dirty();
     m_gizmos.reset_all_states();
-    m_gizmos.update_data(*this);
+    m_gizmos.update_data();
     post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
 }
 
@@ -2082,8 +2082,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
             m_selection.volumes_changed(map_glvolume_old_to_new);
 	}
 
-    m_gizmos.update_data(*this);
-    m_gizmos.refresh_on_off_state(m_selection);
+    m_gizmos.update_data();
+    m_gizmos.refresh_on_off_state();
 
     // Update the toolbar
 	if (update_object_list)
@@ -2323,7 +2323,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
     if ((keyCode == WXK_ESCAPE) && _deactivate_undo_redo_toolbar_items())
         return;
 
-    if (m_gizmos.on_char(evt, *this))
+    if (m_gizmos.on_char(evt))
         return;
 
 //#ifdef __APPLE__
@@ -2450,7 +2450,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
     }
     else
     {
-        if (!m_gizmos.on_key(evt, *this))
+        if (!m_gizmos.on_key(evt))
         {
             if (evt.GetEventType() == wxEVT_KEY_UP) {
                 if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) {
@@ -2560,7 +2560,7 @@ void GLCanvas3D::on_mouse_wheel(wxMouseEvent& evt)
     }
 
     // Inform gizmos about the event so they have the opportunity to react.
-    if (m_gizmos.on_mouse_wheel(evt, *this))
+    if (m_gizmos.on_mouse_wheel(evt))
         return;
 
     // Calculate the zoom delta and apply it to the current zoom factor
@@ -2688,7 +2688,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
         return;
     }
 
-    if (m_gizmos.on_mouse(evt, *this))
+    if (m_gizmos.on_mouse(evt))
     {
         if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp())
             mouse_up_cleanup();
@@ -2815,9 +2815,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                         if (m_selection.is_empty())
                             m_gizmos.reset_all_states();
                         else
-                            m_gizmos.refresh_on_off_state(m_selection);
+                            m_gizmos.refresh_on_off_state();
 
-                        m_gizmos.update_data(*this);
+                        m_gizmos.update_data();
                         post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
                         m_dirty = true;
                     }
@@ -2985,9 +2985,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                 {
                     // forces the selection of the volume
                     m_selection.add(volume_idx);
-                    m_gizmos.refresh_on_off_state(m_selection);
+                    m_gizmos.refresh_on_off_state();
                     post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
-                    m_gizmos.update_data(*this);
+                    m_gizmos.update_data();
                     wxGetApp().obj_manipul()->set_dirty();
                     // forces a frame render to update the view before the context menu is shown
                     render();
@@ -3355,8 +3355,8 @@ void GLCanvas3D::set_camera_zoom(double zoom)
 void GLCanvas3D::update_gizmos_on_off_state()
 {
     set_as_dirty();
-    m_gizmos.update_data(*this);
-    m_gizmos.refresh_on_off_state(get_selection());
+    m_gizmos.update_data();
+    m_gizmos.refresh_on_off_state();
 }
 
 void GLCanvas3D::handle_sidebar_focus_event(const std::string& opt_key, bool focus_on)
@@ -3762,7 +3762,7 @@ void GLCanvas3D::_picking_pass() const
         if (m_camera_clipping_plane.is_active())
             ::glDisable(GL_CLIP_PLANE0);
 
-        m_gizmos.render_current_gizmo_for_picking_pass(m_selection);
+        m_gizmos.render_current_gizmo_for_picking_pass();
 
         if (m_multisample_allowed)
             glsafe(::glEnable(GL_MULTISAMPLE));
@@ -4072,7 +4072,7 @@ void GLCanvas3D::_render_volumes_for_picking() const
 
 void GLCanvas3D::_render_current_gizmo() const
 {
-    m_gizmos.render_current_gizmo(m_selection);
+    m_gizmos.render_current_gizmo();
 }
 
 void GLCanvas3D::_render_gizmos_overlay() const
@@ -4088,7 +4088,7 @@ void GLCanvas3D::_render_gizmos_overlay() const
     m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment
 #endif /* __WXMSW__ */
 
-    m_gizmos.render_overlay(*this, m_selection);
+    m_gizmos.render_overlay();
 }
 
 void GLCanvas3D::_render_toolbar() const
@@ -5661,9 +5661,9 @@ void GLCanvas3D::_update_selection_from_hover()
     if (m_selection.is_empty())
         m_gizmos.reset_all_states();
     else
-        m_gizmos.refresh_on_off_state(m_selection);
+        m_gizmos.refresh_on_off_state();
 
-    m_gizmos.update_data(*this);
+    m_gizmos.update_data();
     post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
     m_dirty = true;
 }
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index f5a53c6a5..6bb17da4a 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -517,6 +517,9 @@ public:
     const Selection& get_selection() const { return m_selection; }
     Selection& get_selection() { return m_selection; }
 
+    const GLGizmosManager& get_gizmos_manager() const { return m_gizmos; }
+    GLGizmosManager& get_gizmos_manager() { return m_gizmos; }
+
     void bed_shape_changed();
 
     void set_clipping_plane(unsigned int id, const ClippingPlane& plane)
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
index 7da3dec8a..ba0ea4825 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
@@ -132,6 +132,7 @@ void GLGizmoBase::Grabber::render_face(float half_size) const
     glsafe(::glEnd());
 }
 
+
 GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
     : m_parent(parent)
     , m_group_id(-1)
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
index 73c73a2c9..88927aee2 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
@@ -6,6 +6,7 @@
 #include "slic3r/GUI/I18N.hpp"
 #include "slic3r/GUI/Selection.hpp"
 
+#include <cereal/archives/binary.hpp>
 
 class wxWindow;
 class GLUquadric;
@@ -105,6 +106,9 @@ public:
 
     bool init() { return on_init(); }
 
+    void load(cereal::BinaryInputArchive& ar) { m_state = On; on_load(ar); }
+    void save(cereal::BinaryOutputArchive& ar) const { on_save(ar); }
+
     std::string get_name() const { return on_get_name(); }
 
     int get_group_id() const { return m_group_id; }
@@ -144,6 +148,8 @@ public:
 
 protected:
     virtual bool on_init() = 0;
+    virtual void on_load(cereal::BinaryInputArchive& ar) {}
+    virtual void on_save(cereal::BinaryOutputArchive& ar) const {}
     virtual std::string on_get_name() const = 0;
     virtual void on_set_state() {}
     virtual void on_set_hover_id() {}
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
index b1c295098..52174d2d6 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
@@ -28,7 +28,6 @@ GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, uns
     , m_rotate_lower(false)
 {}
 
-
 bool GLGizmoCut::on_init()
 {
     m_grabbers.emplace_back();
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
index 79a7c58e2..628bcf508 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp
@@ -27,6 +27,8 @@ public:
 
 protected:
     virtual bool on_init();
+    virtual void on_load(cereal::BinaryInputArchive& ar) { ar(m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); }
+    virtual void on_save(cereal::BinaryOutputArchive& ar) const { ar(m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); }
     virtual std::string on_get_name() const;
     virtual void on_set_state();
     virtual bool on_is_activable(const Selection& selection) const;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
index 602235d4a..5922f9600 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
@@ -15,7 +15,8 @@ namespace GUI {
 const float GLGizmosManager::Default_Icons_Size = 64;
 
 GLGizmosManager::GLGizmosManager()
-    : m_enabled(false)
+    : m_parent(nullptr)
+    , m_enabled(false)
     , m_icons_texture_dirty(true)
     , m_current(Undefined)
     , m_overlay_icons_size(Default_Icons_Size)
@@ -23,6 +24,7 @@ GLGizmosManager::GLGizmosManager()
     , m_overlay_border(5.0f)
     , m_overlay_gap_y(5.0f)
     , m_tooltip("")
+    , m_serializing(false)
 {
 }
 
@@ -33,6 +35,8 @@ GLGizmosManager::~GLGizmosManager()
 
 bool GLGizmosManager::init(GLCanvas3D& parent)
 {
+    m_parent = &parent;
+
     m_background_texture.metadata.filename = "toolbar_background.png";
     m_background_texture.metadata.left = 16;
     m_background_texture.metadata.top = 16;
@@ -135,12 +139,18 @@ void GLGizmosManager::set_overlay_scale(float scale)
     }
 }
 
-void GLGizmosManager::refresh_on_off_state(const Selection& selection)
+void GLGizmosManager::refresh_on_off_state()
 {
+    if (m_parent == nullptr)
+        return;
+
+    if (m_serializing)
+        return;
+
     GizmosMap::iterator it = m_gizmos.find(m_current);
     if ((it != m_gizmos.end()) && (it->second != nullptr))
     {
-        if (!it->second->is_activable(selection))
+        if (!it->second->is_activable(m_parent->get_selection()))
         {
             it->second->set_state(GLGizmoBase::Off);
             m_current = Undefined;
@@ -153,6 +163,9 @@ void GLGizmosManager::reset_all_states()
     if (!m_enabled)
         return;
 
+    if (m_serializing)
+        return;
+
     for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
     {
         if (it->second != nullptr)
@@ -192,22 +205,22 @@ void GLGizmosManager::enable_grabber(EType type, unsigned int id, bool enable)
     }
 }
 
-void GLGizmosManager::update(const Linef3& mouse_ray, const Selection& selection, const Point* mouse_pos)
+void GLGizmosManager::update(const Linef3& mouse_ray, const Point* mouse_pos)
 {
-    if (!m_enabled)
+    if (!m_enabled || (m_parent == nullptr))
         return;
 
     GLGizmoBase* curr = get_current();
     if (curr != nullptr)
-        curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos), selection);
+        curr->update(GLGizmoBase::UpdateData(mouse_ray, mouse_pos), m_parent->get_selection());
 }
 
-void GLGizmosManager::update_data(GLCanvas3D& canvas)
+void GLGizmosManager::update_data()
 {
-    if (!m_enabled)
+    if (!m_enabled || (m_parent == nullptr))
         return;
 
-    const Selection& selection = canvas.get_selection();
+    const Selection& selection = m_parent->get_selection();
 
     bool is_wipe_tower = selection.is_wipe_tower();
     enable_grabber(Move, 2, !is_wipe_tower);
@@ -228,7 +241,7 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
         set_rotation(Vec3d::Zero());
         ModelObject* model_object = selection.get_model()->objects[selection.get_object_idx()];
         set_flattening_data(model_object);
-        set_sla_support_data(model_object, selection);
+        set_sla_support_data(model_object);
     }
     else if (selection.is_single_volume() || selection.is_single_modifier())
     {
@@ -236,7 +249,7 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
         set_scale(volume->get_volume_scaling_factor());
         set_rotation(Vec3d::Zero());
         set_flattening_data(nullptr);
-        set_sla_support_data(nullptr, selection);
+        set_sla_support_data(nullptr);
     }
     else if (is_wipe_tower)
     {
@@ -244,14 +257,14 @@ void GLGizmosManager::update_data(GLCanvas3D& canvas)
         set_scale(Vec3d::Ones());
         set_rotation(Vec3d(0., 0., (M_PI/180.) * dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value));
         set_flattening_data(nullptr);
-        set_sla_support_data(nullptr, selection);
+        set_sla_support_data(nullptr);
     }
     else
     {
         set_scale(Vec3d::Ones());
         set_rotation(Vec3d::Zero());
         set_flattening_data(selection.is_from_single_object() ? selection.get_model()->objects[selection.get_object_idx()] : nullptr);
-        set_sla_support_data(nullptr, selection);
+        set_sla_support_data(nullptr);
     }
 }
 
@@ -264,9 +277,13 @@ bool GLGizmosManager::is_running() const
     return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false;
 }
 
-bool GLGizmosManager::handle_shortcut(int key, const Selection& selection)
+bool GLGizmosManager::handle_shortcut(int key)
 {
-    if (!m_enabled || selection.is_empty())
+    if (!m_enabled || (m_parent == nullptr))
+        return false;
+
+    const Selection& selection = m_parent->get_selection();
+    if (selection.is_empty())
         return false;
 
     EType old_current = m_current;
@@ -314,14 +331,14 @@ bool GLGizmosManager::is_dragging() const
     return (curr != nullptr) ? curr->is_dragging() : false;
 }
 
-void GLGizmosManager::start_dragging(const Selection& selection)
+void GLGizmosManager::start_dragging()
 {
-    if (!m_enabled)
+    if (!m_enabled || (m_parent == nullptr))
         return;
 
     GLGizmoBase* curr = get_current();
     if (curr != nullptr)
-        curr->start_dragging(selection);
+        curr->start_dragging(m_parent->get_selection());
 }
 
 void GLGizmosManager::stop_dragging()
@@ -409,14 +426,14 @@ void GLGizmosManager::set_flattening_data(const ModelObject* model_object)
         reinterpret_cast<GLGizmoFlatten*>(it->second)->set_flattening_data(model_object);
 }
 
-void GLGizmosManager::set_sla_support_data(ModelObject* model_object, const Selection& selection)
+void GLGizmosManager::set_sla_support_data(ModelObject* model_object)
 {
-    if (!m_enabled)
+    if (!m_enabled || (m_parent == nullptr))
         return;
 
     GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
     if (it != m_gizmos.end())
-        reinterpret_cast<GLGizmoSlaSupports*>(it->second)->set_sla_support_data(model_object, selection);
+        reinterpret_cast<GLGizmoSlaSupports*>(it->second)->set_sla_support_data(model_object, m_parent->get_selection());
 }
 
 // Returns true if the gizmo used the event to do something, false otherwise.
@@ -445,39 +462,42 @@ ClippingPlane GLGizmosManager::get_sla_clipping_plane() const
 }
 
 
-void GLGizmosManager::render_current_gizmo(const Selection& selection) const
+void GLGizmosManager::render_current_gizmo() const
 {
-    if (!m_enabled)
+    if (!m_enabled || (m_parent == nullptr))
         return;
 
     GLGizmoBase* curr = get_current();
     if (curr != nullptr)
-        curr->render(selection);
+        curr->render(m_parent->get_selection());
 }
 
-void GLGizmosManager::render_current_gizmo_for_picking_pass(const Selection& selection) const
+void GLGizmosManager::render_current_gizmo_for_picking_pass() const
 {
-    if (!m_enabled)
+    if (!m_enabled || (m_parent == nullptr))
         return;
 
     GLGizmoBase* curr = get_current();
     if (curr != nullptr)
-        curr->render_for_picking(selection);
+        curr->render_for_picking(m_parent->get_selection());
 }
 
-void GLGizmosManager::render_overlay(const GLCanvas3D& canvas, const Selection& selection) const
+void GLGizmosManager::render_overlay() const
 {
-    if (!m_enabled)
+    if (!m_enabled || (m_parent == nullptr))
         return;
 
     if (m_icons_texture_dirty)
         generate_icons_texture();
 
-    do_render_overlay(canvas, selection);
+    do_render_overlay();
 }
 
-bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt, GLCanvas3D& canvas)
+bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt)
 {
+    if (m_parent == nullptr)
+        return false;
+
     bool processed = false;
 
     if (m_current == SlaSupports) {
@@ -489,14 +509,15 @@ bool GLGizmosManager::on_mouse_wheel(wxMouseEvent& evt, GLCanvas3D& canvas)
     return processed;
 }
 
-
-
-bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
+bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
 {
+    if (m_parent == nullptr)
+        return false;
+
     Point pos(evt.GetX(), evt.GetY());
     Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
 
-    Selection& selection = canvas.get_selection();
+    Selection& selection = m_parent->get_selection();
     int selected_object_idx = selection.get_object_idx();
     bool processed = false;
 
@@ -512,7 +533,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
 
     // mouse anywhere
     if (evt.Moving())
-        m_tooltip = update_hover_state(canvas, mouse_pos);
+        m_tooltip = update_hover_state(mouse_pos);
     else if (evt.LeftUp())
         m_mouse_capture.left = false;
     else if (evt.MiddleUp())
@@ -523,7 +544,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
         // if the button down was done on this toolbar, prevent from dragging into the scene
         processed = true;
 
-    if (!overlay_contains_mouse(canvas, mouse_pos))
+    if (!overlay_contains_mouse(mouse_pos))
     {
         // mouse is outside the toolbar
         m_tooltip = "";
@@ -535,40 +556,40 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
                 processed = true;
             else if (!selection.is_empty() && grabber_contains_mouse())
             {
-                update_data(canvas);
+                update_data();
                 selection.start_dragging();
-                start_dragging(selection);
+                start_dragging();
 
                 if (m_current == Flatten)
                 {
                     // Rotate the object so the normal points downward:
-                    canvas.do_flatten(get_flattening_normal(), "Place on Face");
+                    m_parent->do_flatten(get_flattening_normal(), "Gizmo - Place on Face");
                     wxGetApp().obj_manipul()->set_dirty();
                 }
 
-                canvas.set_as_dirty();
+                m_parent->set_as_dirty();
                 processed = true;
             }
         }
         else if (evt.RightDown() && (selected_object_idx != -1) && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::RightDown))
             // event was taken care of by the SlaSupports gizmo
             processed = true;
-        else if (evt.Dragging() && (canvas.get_move_volume_id() != -1) && (m_current == SlaSupports))
+        else if (evt.Dragging() && (m_parent->get_move_volume_id() != -1) && (m_current == SlaSupports))
             // don't allow dragging objects with the Sla gizmo on
             processed = true;
         else if (evt.Dragging() && (m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::Dragging, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
         {
             // the gizmo got the event and took some action, no need to do anything more here
-            canvas.set_as_dirty();
+            m_parent->set_as_dirty();
             processed = true;
         }
         else if (evt.Dragging() && is_dragging())
         {
-            if (!canvas.get_wxglcanvas()->HasCapture())
-                canvas.get_wxglcanvas()->CaptureMouse();
+            if (!m_parent->get_wxglcanvas()->HasCapture())
+                m_parent->get_wxglcanvas()->CaptureMouse();
 
-            canvas.set_mouse_as_dragging();
-            update(canvas.mouse_ray(pos), selection, &pos);
+            m_parent->set_mouse_as_dragging();
+            update(m_parent->mouse_ray(pos), &pos);
 
             switch (m_current)
             {
@@ -605,7 +626,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
                 break;
             }
 
-            canvas.set_as_dirty();
+            m_parent->set_as_dirty();
             processed = true;
         }
         else if (evt.LeftUp() && is_dragging())
@@ -614,18 +635,18 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
             {
             case Move:
             {
-                canvas.disable_regenerate_volumes();
-                canvas.do_move("Gizmo-Move Object");
+                m_parent->disable_regenerate_volumes();
+                m_parent->do_move("Gizmo-Move Object");
                 break;
             }
             case Scale:
             {
-                canvas.do_scale("Gizmo-Scale Object");
+                m_parent->do_scale("Gizmo-Scale Object");
                 break;
             }
             case Rotate:
             {
-                canvas.do_rotate("Gizmo-Rotate Object");
+                m_parent->do_rotate("Gizmo-Rotate Object");
                 break;
             }
             default:
@@ -633,25 +654,25 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
             }
 
             stop_dragging();
-            update_data(canvas);
+            update_data();
 
             wxGetApp().obj_manipul()->set_dirty();
             // Let the platter know that the dragging finished, so a delayed refresh
             // of the scene with the background processing data should be performed.
-            canvas.post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
+            m_parent->post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
             // updates camera target constraints
-            canvas.refresh_camera_scene_box();
+            m_parent->refresh_camera_scene_box();
 
             processed = true;
         }
-        else if (evt.LeftUp() && (m_current == SlaSupports) && !canvas.is_mouse_dragging())
+        else if (evt.LeftUp() && (m_current == SlaSupports) && !m_parent->is_mouse_dragging())
         {
             // in case SLA gizmo is selected, we just pass the LeftUp event and stop processing - neither
             // object moving or selecting is suppressed in that case
             gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown());
             processed = true;
         }
-        else if (evt.LeftUp() && (m_current == Flatten) && ((canvas.get_first_hover_volume_idx() != -1) || grabber_contains_mouse()))
+        else if (evt.LeftUp() && (m_current == Flatten) && ((m_parent->get_first_hover_volume_idx() != -1) || grabber_contains_mouse()))
         {
             // to avoid to loose the selection when user clicks an object while the Flatten gizmo is active
             processed = true;
@@ -663,24 +684,24 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
         if (evt.LeftDown() || evt.LeftDClick())
         {
             m_mouse_capture.left = true;
-            m_mouse_capture.parent = &canvas;
+            m_mouse_capture.parent = m_parent;
             processed = true;
             if (!selection.is_empty())
             {
-                update_on_off_state(canvas, mouse_pos, selection);
-                update_data(canvas);
-                canvas.set_as_dirty();
+                update_on_off_state(mouse_pos);
+                update_data();
+                m_parent->set_as_dirty();
             }
         }
         else if (evt.MiddleDown())
         {
             m_mouse_capture.middle = true;
-            m_mouse_capture.parent = &canvas;
+            m_mouse_capture.parent = m_parent;
         }
         else if (evt.RightDown())
         {
             m_mouse_capture.right = true;
-            m_mouse_capture.parent = &canvas;
+            m_mouse_capture.parent = m_parent;
         }
         else if (evt.LeftUp())
             processed = true;
@@ -689,8 +710,11 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
     return processed;
 }
 
-bool GLGizmosManager::on_char(wxKeyEvent& evt, GLCanvas3D& canvas)
+bool GLGizmosManager::on_char(wxKeyEvent& evt)
 {
+    if (m_parent == nullptr)
+        return false;
+
     // see include/wx/defs.h enum wxKeyCode
     int keyCode = evt.GetKeyCode();
     int ctrlMask = wxMOD_CONTROL;
@@ -797,21 +821,24 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt, GLCanvas3D& canvas)
 
     if (!processed && !evt.HasModifiers())
     {
-        if (handle_shortcut(keyCode, canvas.get_selection()))
+        if (handle_shortcut(keyCode))
         {
-            update_data(canvas);
+            update_data();
             processed = true;
         }
     }
 
     if (processed)
-        canvas.set_as_dirty();
+        m_parent->set_as_dirty();
 
     return processed;
 }
 
-bool GLGizmosManager::on_key(wxKeyEvent& evt, GLCanvas3D& canvas)
+bool GLGizmosManager::on_key(wxKeyEvent& evt)
 {
+    if (m_parent == nullptr)
+        return false;
+
     const int keyCode = evt.GetKeyCode();
     bool processed = false;
 
@@ -836,23 +863,29 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt, GLCanvas3D& canvas)
         }
 
 //        if (processed)
-//            canvas.set_cursor(GLCanvas3D::Standard);
+//            m_parent->set_cursor(GLCanvas3D::Standard);
     }
     else if (evt.GetEventType() == wxEVT_KEY_DOWN)
     {
         if ((m_current == SlaSupports) && ((keyCode == WXK_SHIFT) || (keyCode == WXK_ALT)) && reinterpret_cast<GLGizmoSlaSupports*>(get_current())->is_in_editing_mode())
         {
-//            canvas.set_cursor(GLCanvas3D::Cross);
+//            m_parent->set_cursor(GLCanvas3D::Cross);
             processed = true;
         }
     }
 
     if (processed)
-        canvas.set_as_dirty();
+        m_parent->set_as_dirty();
 
     return processed;
 }
 
+void GLGizmosManager::update_after_undo_redo()
+{
+    update_data();
+    m_serializing = false;
+}
+
 void GLGizmosManager::reset()
 {
     for (GizmosMap::value_type& gizmo : m_gizmos)
@@ -864,14 +897,16 @@ void GLGizmosManager::reset()
     m_gizmos.clear();
 }
 
-void GLGizmosManager::do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const
+void GLGizmosManager::do_render_overlay() const
 {
-    if (m_gizmos.empty())
+    if ((m_parent == nullptr) || m_gizmos.empty())
         return;
 
-    float cnv_w = (float)canvas.get_canvas_size().get_width();
-    float cnv_h = (float)canvas.get_canvas_size().get_height();
-    float zoom = (float)canvas.get_camera().get_zoom();
+    const Selection& selection = m_parent->get_selection();
+
+    float cnv_w = (float)m_parent->get_canvas_size().get_width();
+    float cnv_h = (float)m_parent->get_canvas_size().get_height();
+    float zoom = (float)m_parent->get_camera().get_zoom();
     float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f;
 
     float height = get_total_overlay_height();
@@ -984,7 +1019,7 @@ void GLGizmosManager::do_render_overlay(const GLCanvas3D& canvas, const Selectio
 
         GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } });
         if (it->second->get_state() == GLGizmoBase::On) {
-            float toolbar_top = (float)cnv_h - canvas.get_view_toolbar_height();
+            float toolbar_top = (float)cnv_h - m_parent->get_view_toolbar_height();
             it->second->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection);
         }
         top_y -= scaled_stride_y;
@@ -1047,12 +1082,14 @@ bool GLGizmosManager::generate_icons_texture() const
     return res;
 }
 
-void GLGizmosManager::update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection)
+void GLGizmosManager::update_on_off_state(const Vec2d& mouse_pos)
 {
-    if (!m_enabled)
+    if (!m_enabled || (m_parent == nullptr))
         return;
 
-    float cnv_h = (float)canvas.get_canvas_size().get_height();
+    const Selection& selection = m_parent->get_selection();
+
+    float cnv_h = (float)m_parent->get_canvas_size().get_height();
     float height = get_total_overlay_height();
 
     float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
@@ -1091,16 +1128,16 @@ void GLGizmosManager::update_on_off_state(const GLCanvas3D& canvas, const Vec2d&
         it->second->set_state(GLGizmoBase::On);
 }
 
-std::string GLGizmosManager::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos)
+std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos)
 {
     std::string name = "";
 
-    if (!m_enabled)
+    if (!m_enabled || (m_parent == nullptr))
         return name;
 
-    const Selection& selection = canvas.get_selection();
+    const Selection& selection = m_parent->get_selection();
 
-    float cnv_h = (float)canvas.get_canvas_size().get_height();
+    float cnv_h = (float)m_parent->get_canvas_size().get_height();
     float height = get_total_overlay_height();
     float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
     float scaled_border = m_overlay_border * m_overlay_scale;
@@ -1126,12 +1163,12 @@ std::string GLGizmosManager::update_hover_state(const GLCanvas3D& canvas, const
     return name;
 }
 
-bool GLGizmosManager::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const
+bool GLGizmosManager::overlay_contains_mouse(const Vec2d& mouse_pos) const
 {
-    if (!m_enabled)
+    if (!m_enabled || (m_parent == nullptr))
         return false;
 
-    float cnv_h = (float)canvas.get_canvas_size().get_height();
+    float cnv_h = (float)m_parent->get_canvas_size().get_height();
     float height = get_total_overlay_height();
 
     float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
index 87be7da41..db73345ae 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
@@ -4,14 +4,13 @@
 #include "slic3r/GUI/GLTexture.hpp"
 #include "slic3r/GUI/GLToolbar.hpp"
 #include "slic3r/GUI/Gizmos/GLGizmos.hpp"
+#include "libslic3r/ObjectID.hpp"
 
 #include <map>
 
 namespace Slic3r {
 namespace GUI {
 
-class Selection;
-class GLGizmoBase;
 class GLCanvas3D;
 class ClippingPlane;
 
@@ -43,7 +42,7 @@ public:
     float get_height() const { return m_top - m_bottom; }
 };
 
-class GLGizmosManager
+class GLGizmosManager : public Slic3r::ObjectBase
 {
 public:
     static const float Default_Icons_Size;
@@ -61,6 +60,7 @@ public:
     };
 
 private:
+    GLCanvas3D* m_parent;
     bool m_enabled;
     typedef std::map<EType, GLGizmoBase*> GizmosMap;
     GizmosMap m_gizmos;
@@ -89,6 +89,7 @@ private:
 
     MouseCapture m_mouse_capture;
     std::string m_tooltip;
+    bool m_serializing;
 
 public:
     GLGizmosManager();
@@ -96,29 +97,59 @@ public:
 
     bool init(GLCanvas3D& parent);
 
+    template<class Archive>
+    void load(Archive& ar)
+    {
+        if (!m_enabled)
+            return;
+
+        m_serializing = true;
+
+        ar(m_current);
+
+        GLGizmoBase* curr = get_current();
+        if (curr != nullptr)
+        {
+            curr->set_state(GLGizmoBase::On);
+            curr->load(ar);
+        }
+    }
+
+    template<class Archive>
+    void save(Archive& ar) const
+    {
+        if (!m_enabled)
+            return;
+
+        ar(m_current);
+
+        GLGizmoBase* curr = get_current();
+        if (curr != nullptr)
+            curr->save(ar);
+    }
+
     bool is_enabled() const { return m_enabled; }
     void set_enabled(bool enable) { m_enabled = enable; }
 
     void set_overlay_icon_size(float size);
     void set_overlay_scale(float scale);
 
-    void refresh_on_off_state(const Selection& selection);
+    void refresh_on_off_state();
     void reset_all_states();
 
     void set_hover_id(int id);
     void enable_grabber(EType type, unsigned int id, bool enable);
 
-    void update(const Linef3& mouse_ray, const Selection& selection, const Point* mouse_pos = nullptr);
-    void update_data(GLCanvas3D& canvas);
+    void update(const Linef3& mouse_ray, const Point* mouse_pos = nullptr);
+    void update_data();
 
-    Rect get_reset_rect_viewport(const GLCanvas3D& canvas) const;
     EType get_current_type() const { return m_current; }
 
     bool is_running() const;
-    bool handle_shortcut(int key, const Selection& selection);
+    bool handle_shortcut(int key);
 
     bool is_dragging() const;
-    void start_dragging(const Selection& selection);
+    void start_dragging();
     void stop_dragging();
 
     Vec3d get_displacement() const;
@@ -135,26 +166,28 @@ public:
 
     void set_flattening_data(const ModelObject* model_object);
 
-    void set_sla_support_data(ModelObject* model_object, const Selection& selection);
+    void set_sla_support_data(ModelObject* model_object);
     bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false);
     ClippingPlane get_sla_clipping_plane() const;
 
-    void render_current_gizmo(const Selection& selection) const;
-    void render_current_gizmo_for_picking_pass(const Selection& selection) const;
+    void render_current_gizmo() const;
+    void render_current_gizmo_for_picking_pass() const;
 
-    void render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
+    void render_overlay() const;
 
     const std::string& get_tooltip() const { return m_tooltip; }
 
-    bool on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas);
-    bool on_mouse_wheel(wxMouseEvent& evt, GLCanvas3D& canvas);
-    bool on_char(wxKeyEvent& evt, GLCanvas3D& canvas);
-    bool on_key(wxKeyEvent& evt, GLCanvas3D& canvas);
+    bool on_mouse(wxMouseEvent& evt);
+    bool on_mouse_wheel(wxMouseEvent& evt);
+    bool on_char(wxKeyEvent& evt);
+    bool on_key(wxKeyEvent& evt);
+
+    void update_after_undo_redo();
 
 private:
     void reset();
 
-    void do_render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
+    void do_render_overlay() const;
 
     float get_total_overlay_height() const;
     float get_total_overlay_width() const;
@@ -163,13 +196,18 @@ private:
 
     bool generate_icons_texture() const;
 
-    void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection);
-    std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos);
-    bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const;
+    void update_on_off_state(const Vec2d& mouse_pos);
+    std::string update_hover_state(const Vec2d& mouse_pos);
+    bool overlay_contains_mouse(const Vec2d& mouse_pos) const;
     bool grabber_contains_mouse() const;
 };
 
 } // namespace GUI
 } // namespace Slic3r
 
+namespace cereal
+{
+    template <class Archive> struct specialize<Archive, Slic3r::GUI::GLGizmosManager, cereal::specialization::member_load_save> {};
+}
+
 #endif // slic3r_GUI_GLGizmosManager_hpp_
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index f5f245471..c5a4ccead 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -1633,8 +1633,8 @@ struct Plater::priv
         if (this->m_prevent_snapshots > 0) 
             return;
         assert(this->m_prevent_snapshots >= 0);
-	    this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection());
-	}
+        this->undo_redo_stack.take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager());
+    }
 	void take_snapshot(const wxString& snapshot_name) { this->take_snapshot(std::string(snapshot_name.ToUTF8().data())); }
     int  get_active_snapshot_index();
     void undo();
@@ -3611,34 +3611,35 @@ int Plater::priv::get_active_snapshot_index()
 
 void Plater::priv::undo()
 {
-	if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection()))
-		this->update_after_undo_redo();
+    if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager()))
+        this->update_after_undo_redo();
 }
 
 void Plater::priv::redo()
 { 
-	if (this->undo_redo_stack.redo(model))
-		this->update_after_undo_redo();
+    if (this->undo_redo_stack.redo(model, this->view3D->get_canvas3d()->get_gizmos_manager()))
+        this->update_after_undo_redo();
 }
 
 void Plater::priv::undo_to(size_t time_to_load)
 {
-	if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), time_to_load))
-		this->update_after_undo_redo();
+    if (this->undo_redo_stack.undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), time_to_load))
+        this->update_after_undo_redo();
 }
 
 void Plater::priv::redo_to(size_t time_to_load)
 { 
-	if (this->undo_redo_stack.redo(model, time_to_load))
-		this->update_after_undo_redo();
+    if (this->undo_redo_stack.redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), time_to_load))
+        this->update_after_undo_redo();
 }
 
 void Plater::priv::update_after_undo_redo()
 {
-	this->view3D->get_canvas3d()->get_selection().clear();
+    this->view3D->get_canvas3d()->get_selection().clear();
 	this->update(false); // update volumes from the deserializd model
 	//YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time)
     this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack.selection_deserialized().mode), this->undo_redo_stack.selection_deserialized().volumes_and_instances);
+    this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo();
 
     wxGetApp().obj_list()->update_after_undo_redo();
 
@@ -3884,7 +3885,7 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe
         return;
     }
 
-    this->take_snapshot(_(L("Cut")));
+    this->take_snapshot(_(L("Gizmo - Cut")));
 
     wxBusyCursor wait;
     const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower);
diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp
index 058062502..69d60603e 100644
--- a/src/slic3r/Utils/UndoRedo.cpp
+++ b/src/slic3r/Utils/UndoRedo.cpp
@@ -17,8 +17,6 @@
 #define CEREAL_FUTURE_EXPERIMENTAL
 #include <cereal/archives/adapters.hpp>
 
-#include <libslic3r/ObjectID.hpp>
-
 #include <boost/foreach.hpp>
 
 #ifndef NDEBUG
@@ -358,18 +356,14 @@ public:
 	// Stack needs to be initialized. An empty stack is not valid, there must be a "New Project" status stored at the beginning.
 	StackImpl() : m_active_snapshot_time(0), m_current_time(0) {}
 
-	// The Undo / Redo stack is being initialized with an empty model and an empty selection.
-	// The first snapshot cannot be removed.
-	void initialize(const Slic3r::Model &model, const Slic3r::GUI::Selection &selection);
-
-	// Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
-	void take_snapshot(const std::string &snapshot_name, const Slic3r::Model &model, const Slic3r::GUI::Selection &selection);
-	void load_snapshot(size_t timestamp, Slic3r::Model &model);
+    // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
+    void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos);
+    void load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos);
 
 	bool has_undo_snapshot() const;
 	bool has_redo_snapshot() const;
-	bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, size_t jump_to_time);
-	bool redo(Slic3r::Model &model, size_t jump_to_time);
+    bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t jump_to_time);
+    bool redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t jump_to_time);
 
 	// Snapshot history (names with timestamps).
 	const std::vector<Snapshot>& 	snapshots() const { return m_snapshots; }
@@ -551,6 +545,7 @@ namespace cereal
 #include <libslic3r/Model.hpp>
 #include <libslic3r/TriangleMesh.hpp>
 #include <slic3r/GUI/Selection.hpp>
+#include <slic3r/GUI/Gizmos/GLGizmosManager.hpp>
 
 namespace Slic3r {
 namespace UndoRedo {
@@ -632,7 +627,7 @@ template<typename T, typename T_AS> void StackImpl::load_mutable_object(const Sl
 }
 
 // Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
-void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Model &model, const Slic3r::GUI::Selection &selection)
+void StackImpl::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos)
 {
 	// Release old snapshot data.
 	assert(m_active_snapshot_time <= m_current_time);
@@ -650,7 +645,8 @@ void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Mo
 	for (unsigned int volume_idx : selection.get_volume_idxs())
 		m_selection.volumes_and_instances.emplace_back(selection.get_volume(volume_idx)->geometry_id);
 	this->save_mutable_object<Selection, Selection>(m_selection);
-	// Save the snapshot info.
+    this->save_mutable_object<Slic3r::GUI::GLGizmosManager, Slic3r::GUI::GLGizmosManager>(gizmos);
+    // Save the snapshot info.
 	m_snapshots.emplace_back(snapshot_name, m_current_time ++, model.id().id);
 	m_active_snapshot_time = m_current_time;
 	// Save snapshot info of the last "current" aka "top most" state, that is only being serialized
@@ -665,7 +661,7 @@ void StackImpl::take_snapshot(const std::string &snapshot_name, const Slic3r::Mo
 #endif /* SLIC3R_UNDOREDO_DEBUG */
 }
 
-void StackImpl::load_snapshot(size_t timestamp, Slic3r::Model &model)
+void StackImpl::load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos)
 {
 	// Find the snapshot by time. It must exist.
 	const auto it_snapshot = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(timestamp));
@@ -679,7 +675,9 @@ void StackImpl::load_snapshot(size_t timestamp, Slic3r::Model &model)
 	model.update_links_bottom_up_recursive();
 	m_selection.volumes_and_instances.clear();
 	this->load_mutable_object<Selection, Selection>(m_selection.id(), m_selection);
-	// Sort the volumes so that we may use binary search.
+    gizmos.reset_all_states();
+    this->load_mutable_object<Slic3r::GUI::GLGizmosManager, Slic3r::GUI::GLGizmosManager>(gizmos.id(), gizmos);
+    // Sort the volumes so that we may use binary search.
 	std::sort(m_selection.volumes_and_instances.begin(), m_selection.volumes_and_instances.end());
 	this->m_active_snapshot_time = timestamp;
 	assert(this->valid());
@@ -699,8 +697,8 @@ bool StackImpl::has_redo_snapshot() const
 	return ++ it != m_snapshots.end();
 }
 
-bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, size_t time_to_load)
-{ 
+bool StackImpl::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load)
+{
 	assert(this->valid());
 	if (time_to_load == SIZE_MAX) {
 		auto it_current = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
@@ -712,8 +710,8 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
 	assert(std::binary_search(m_snapshots.begin(), m_snapshots.end(), Snapshot(time_to_load)));
 	if (m_active_snapshot_time == m_snapshots.back().timestamp && ! m_snapshots.back().is_topmost_captured()) {
 		// The current state is temporary. The current state needs to be captured to be redoable.
-		this->take_snapshot(topmost_snapsnot_name, model, selection);
-		// The line above entered another topmost_snapshot_name.
+        this->take_snapshot(topmost_snapsnot_name, model, selection, gizmos);
+        // The line above entered another topmost_snapshot_name.
 		assert(m_snapshots.back().is_topmost());
 		assert(! m_snapshots.back().is_topmost_captured());
 		// Pop it back, it is not needed as there is now a captured topmost state.
@@ -723,7 +721,7 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
 		assert(m_snapshots.back().is_topmost());
 		assert(m_snapshots.back().is_topmost_captured());
 	}
-	this->load_snapshot(time_to_load, model);
+    this->load_snapshot(time_to_load, model, gizmos);
 #ifdef SLIC3R_UNDOREDO_DEBUG
 	std::cout << "After undo" << std::endl;
  	this->print();
@@ -731,8 +729,8 @@ bool StackImpl::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selecti
 	return true;
 }
 
-bool StackImpl::redo(Slic3r::Model &model, size_t time_to_load)
-{ 
+bool StackImpl::redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load)
+{
 	assert(this->valid());
 	if (time_to_load == SIZE_MAX) {
 		auto it_current = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(m_active_snapshot_time));
@@ -742,7 +740,7 @@ bool StackImpl::redo(Slic3r::Model &model, size_t time_to_load)
 	}
 	assert(time_to_load > m_active_snapshot_time);
 	assert(std::binary_search(m_snapshots.begin(), m_snapshots.end(), Snapshot(time_to_load)));
-	this->load_snapshot(time_to_load, model);
+    this->load_snapshot(time_to_load, model, gizmos);
 #ifdef SLIC3R_UNDOREDO_DEBUG
 	std::cout << "After redo" << std::endl;
  	this->print();
@@ -767,11 +765,11 @@ void StackImpl::collect_garbage()
 // Wrappers of the private implementation.
 Stack::Stack() : pimpl(new StackImpl()) {}
 Stack::~Stack() {}
-void Stack::take_snapshot(const std::string &snapshot_name, const Slic3r::Model &model, const Slic3r::GUI::Selection &selection) { pimpl->take_snapshot(snapshot_name, model, selection); }
+void Stack::take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos) { pimpl->take_snapshot(snapshot_name, model, selection, gizmos); }
 bool Stack::has_undo_snapshot() const { return pimpl->has_undo_snapshot(); }
 bool Stack::has_redo_snapshot() const { return pimpl->has_redo_snapshot(); }
-bool Stack::undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, size_t time_to_load) { return pimpl->undo(model, selection, time_to_load); }
-bool Stack::redo(Slic3r::Model &model, size_t time_to_load) { return pimpl->redo(model, time_to_load); }
+bool Stack::undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load) { return pimpl->undo(model, selection, gizmos, time_to_load); }
+bool Stack::redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load) { return pimpl->redo(model, gizmos, time_to_load); }
 const Selection& Stack::selection_deserialized() const { return pimpl->selection_deserialized(); }
 
 const std::vector<Snapshot>& Stack::snapshots() const { return pimpl->snapshots(); }
diff --git a/src/slic3r/Utils/UndoRedo.hpp b/src/slic3r/Utils/UndoRedo.hpp
index f8bfda08c..236970b68 100644
--- a/src/slic3r/Utils/UndoRedo.hpp
+++ b/src/slic3r/Utils/UndoRedo.hpp
@@ -15,6 +15,7 @@ class Model;
 
 namespace GUI {
 	class Selection;
+    class GLGizmosManager;
 } // namespace GUI
 
 namespace UndoRedo {
@@ -56,7 +57,7 @@ public:
 	~Stack();
 
 	// Store the current application state onto the Undo / Redo stack, remove all snapshots after m_active_snapshot_time.
-	void take_snapshot(const std::string &snapshot_name, const Slic3r::Model &model, const Slic3r::GUI::Selection &selection);
+    void take_snapshot(const std::string& snapshot_name, const Slic3r::Model& model, const Slic3r::GUI::Selection& selection, const Slic3r::GUI::GLGizmosManager& gizmos);
 
 	// To be queried to enable / disable the Undo / Redo buttons at the UI.
 	bool has_undo_snapshot() const;
@@ -64,10 +65,10 @@ public:
 
 	// Roll back the time. If time_to_load is SIZE_MAX, the previous snapshot is activated.
 	// Undoing an action may need to take a snapshot of the current application state, so that redo to the current state is possible.
-	bool undo(Slic3r::Model &model, const Slic3r::GUI::Selection &selection, size_t time_to_load = SIZE_MAX);
+    bool undo(Slic3r::Model& model, const Slic3r::GUI::Selection& selection, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load = SIZE_MAX);
 
 	// Jump forward in time. If time_to_load is SIZE_MAX, the next snapshot is activated.
-	bool redo(Slic3r::Model &model, size_t time_to_load = SIZE_MAX);
+    bool redo(Slic3r::Model& model, Slic3r::GUI::GLGizmosManager& gizmos, size_t time_to_load = SIZE_MAX);
 
 	// Snapshot history (names with timestamps).
 	// Each snapshot indicates start of an interval in which this operation is performed.