diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
index 18053dcd6..da3042779 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
@@ -69,7 +69,6 @@ public:
     enum EState
     {
         Off,
-        Hover,
         On,
         Num_States
     };
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
index c69d64134..9cd2ab6bb 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
@@ -44,12 +44,12 @@ public:
     Vec3d get_flattening_normal() const;
 
 protected:
-    virtual bool on_init();
-    virtual std::string on_get_name() const;
-    virtual bool on_is_activable() const;
-    virtual void on_start_dragging();
-    virtual void on_render() const;
-    virtual void on_render_for_picking() const;
+    virtual bool on_init() override;
+    virtual std::string on_get_name() const override;
+    virtual bool on_is_activable() const override;
+    virtual void on_start_dragging() override;
+    virtual void on_render() const override;
+    virtual void on_render_for_picking() const override;
     virtual void on_set_state() override;
 };
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
index 8733c9a11..c856e5465 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
@@ -87,16 +87,12 @@ protected:
     virtual void on_set_state()
     {
         for (GLGizmoRotate& g : m_gizmos)
-        {
             g.set_state(m_state);
-        }
     }
     virtual void on_set_hover_id()
     {
         for (int i = 0; i < 3; ++i)
-        {
             m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
-        }
     }
     virtual void on_enable_grabber(unsigned int id)
     {
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index 3f91a3556..25c1d4d42 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -12,6 +12,7 @@
 #include "slic3r/GUI/GUI.hpp"
 #include "slic3r/GUI/GUI_ObjectSettings.hpp"
 #include "slic3r/GUI/GUI_ObjectList.hpp"
+#include "slic3r/GUI/Plater.hpp"
 #include "slic3r/GUI/PresetBundle.hpp"
 #include "libslic3r/SLAPrint.hpp"
 #include "libslic3r/Tesselate.hpp"
@@ -1099,9 +1100,6 @@ std::string GLGizmoSlaSupports::on_get_name() const
 
 void GLGizmoSlaSupports::on_set_state()
 {
-    if (m_state == Hover)
-        return;
-
     // m_model_object pointer can be invalid (for instance because of undo/redo action),
     // we should recover it from the object id
     m_model_object = nullptr;
@@ -1112,6 +1110,11 @@ void GLGizmoSlaSupports::on_set_state()
         }
     }
 
+    if (m_state == m_old_state)
+        return;
+
+    Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo on/off")));
+
     if (m_state == On && m_old_state != On) { // the gizmo was just turned on
         Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on")));
         if (is_mesh_update_necessary())
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
index 49aad0dd2..787d220da 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
@@ -157,6 +157,7 @@ private:
 protected:
     void on_set_state() override;
     void on_set_hover_id() override
+
     {
         if (! m_editing_mode || (int)m_editing_cache.size() <= m_hover_id)
             m_hover_id = -1;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
index 1528a4bcb..00ca9ee05 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
@@ -29,9 +29,49 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent)
 {
 }
 
-GLGizmosManager::~GLGizmosManager()
+std::vector<size_t> GLGizmosManager::get_selectable_idxs() const
 {
-    reset();
+    std::vector<size_t> out;
+    for (size_t i=0; i<m_gizmos.size(); ++i)
+        if (m_gizmos[i]->is_selectable())
+            out.push_back(i);
+    return out;
+}
+
+std::vector<size_t> GLGizmosManager::get_activable_idxs() const
+{
+    std::vector<size_t> out;
+    for (size_t i=0; i<m_gizmos.size(); ++i)
+        if (m_gizmos[i]->is_activable())
+            out.push_back(i);
+    return out;
+}
+
+size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const
+{
+    if (! m_enabled)
+        return Undefined;
+
+    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;
+    float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
+    float scaled_stride_y = scaled_icons_size + scaled_gap_y;
+    float top_y = 0.5f * (cnv_h - height) + scaled_border;
+
+    // is mouse horizontally in the area?
+    if ((scaled_border <= (float)mouse_pos(0) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size))) {
+        // which icon is it on?
+        size_t from_top = (size_t)((float)mouse_pos(1) - top_y)/scaled_stride_y;
+        // is it really on the icon or already past the border?
+        if ((float)mouse_pos(1) <= top_y + from_top*scaled_stride_y + scaled_icons_size) {
+            std::vector<size_t> selectable = get_selectable_idxs();
+            if (from_top < selectable.size())
+                return selectable[from_top];
+        }
+    }
+    return Undefined;
 }
 
 bool GLGizmosManager::init()
@@ -45,77 +85,25 @@ bool GLGizmosManager::init()
     if (!m_background_texture.metadata.filename.empty())
     {
         if (!m_background_texture.texture.load_from_file(resources_dir() + "/icons/" + m_background_texture.metadata.filename, false, GLTexture::SingleThreaded, false))
-        {
-            reset();
+            return false;
+    }
+
+    m_gizmos.emplace_back(new GLGizmoMove3D(m_parent, "move.svg", 0));
+    m_gizmos.emplace_back(new GLGizmoScale3D(m_parent, "scale.svg", 1));
+    m_gizmos.emplace_back(new GLGizmoRotate3D(m_parent, "rotate.svg", 2));
+    m_gizmos.emplace_back(new GLGizmoFlatten(m_parent, "place.svg", 3));
+    m_gizmos.emplace_back(new GLGizmoCut(m_parent, "cut.svg", 4));
+    m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, "sla_supports.svg", 5));
+
+    for (auto& gizmo : m_gizmos) {
+        if (! gizmo->init()) {
+            m_gizmos.clear();
             return false;
         }
     }
 
-    GLGizmoBase* gizmo = new GLGizmoMove3D(m_parent, "move.svg", 0);
-    if (gizmo == nullptr)
-        return false;
-
-    if (!gizmo->init())
-        return false;
-
-    m_gizmos.insert(GizmosMap::value_type(Move, gizmo));
-
-    gizmo = new GLGizmoScale3D(m_parent, "scale.svg", 1);
-    if (gizmo == nullptr)
-        return false;
-
-    if (!gizmo->init())
-        return false;
-
-    m_gizmos.insert(GizmosMap::value_type(Scale, gizmo));
-
-    gizmo = new GLGizmoRotate3D(m_parent, "rotate.svg", 2);
-    if (gizmo == nullptr)
-    {
-        reset();
-        return false;
-    }
-
-    if (!gizmo->init())
-    {
-        reset();
-        return false;
-    }
-
-    m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo));
-
-    gizmo = new GLGizmoFlatten(m_parent, "place.svg", 3);
-    if (gizmo == nullptr)
-        return false;
-
-    if (!gizmo->init()) {
-        reset();
-        return false;
-    }
-
-    m_gizmos.insert(GizmosMap::value_type(Flatten, gizmo));
-
-    gizmo = new GLGizmoCut(m_parent, "cut.svg", 4);
-    if (gizmo == nullptr)
-        return false;
-
-    if (!gizmo->init()) {
-        reset();
-        return false;
-    }
-
-    m_gizmos.insert(GizmosMap::value_type(Cut, gizmo));
-
-    gizmo = new GLGizmoSlaSupports(m_parent, "sla_supports.svg", 5);
-    if (gizmo == nullptr)
-        return false;
-
-    if (!gizmo->init()) {
-        reset();
-        return false;
-    }
-
-    m_gizmos.insert(GizmosMap::value_type(SlaSupports, gizmo));
+    m_current = Undefined;
+    m_hover = Undefined;
 
     return true;
 }
@@ -140,65 +128,39 @@ void GLGizmosManager::set_overlay_scale(float scale)
 
 void GLGizmosManager::refresh_on_off_state()
 {
-    if (m_serializing)
+    if (m_serializing || m_current == Undefined || m_gizmos.empty())
         return;
 
-    GizmosMap::iterator it = m_gizmos.find(m_current);
-    if ((it != m_gizmos.end()) && (it->second != nullptr))
-    {
-        if (!it->second->is_activable())
-        {
-            it->second->set_state(GLGizmoBase::Off);
-            m_current = Undefined;
-        }
-    }
+    if (m_current != Undefined && ! m_gizmos[m_current]->is_activable())
+        activate_gizmo(Undefined);
 }
 
 void GLGizmosManager::reset_all_states()
 {
-    if (!m_enabled)
+    if (! m_enabled || m_serializing)
         return;
 
-    if (m_serializing)
-        return;
-
-    for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
-    {
-        if (it->second != nullptr)
-        {
-            it->second->set_state(GLGizmoBase::Off);
-            it->second->set_hover_id(-1);
-        }
-    }
-
-    m_current = Undefined;
+    activate_gizmo(Undefined);
+    m_hover = Undefined;
 }
 
 void GLGizmosManager::set_hover_id(int id)
 {
-    if (!m_enabled)
+    if (!m_enabled || m_current == Undefined)
         return;
 
-    for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
-    {
-        if ((it->second != nullptr) && (it->second->get_state() == GLGizmoBase::On))
-            it->second->set_hover_id(id);
-    }
+    m_gizmos[m_current]->set_hover_id(id);
 }
 
 void GLGizmosManager::enable_grabber(EType type, unsigned int id, bool enable)
 {
-    if (!m_enabled)
+    if (!m_enabled || type == Undefined || m_gizmos.empty())
         return;
 
-    GizmosMap::const_iterator it = m_gizmos.find(type);
-    if (it != m_gizmos.end())
-    {
-        if (enable)
-            it->second->enable_grabber(id);
-        else
-            it->second->disable_grabber(id);
-    }
+    if (enable)
+        m_gizmos[type]->enable_grabber(id);
+    else
+        m_gizmos[type]->disable_grabber(id);
 }
 
 void GLGizmosManager::update(const Linef3& mouse_ray, const Point& mouse_pos)
@@ -269,8 +231,9 @@ bool GLGizmosManager::is_running() const
     if (!m_enabled)
         return false;
 
-    GLGizmoBase* curr = get_current();
-    return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false;
+    //GLGizmoBase* curr = get_current();
+    //return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false;
+    return m_current != Undefined;
 }
 
 bool GLGizmosManager::handle_shortcut(int key)
@@ -283,43 +246,12 @@ bool GLGizmosManager::handle_shortcut(int key)
 
     bool handled = false;
 
-    for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
-    {
-        if ((it->second == nullptr) || !it->second->is_selectable())
-            continue;
+    for (size_t idx : get_selectable_idxs()) {
+        int it_key = m_gizmos[idx]->get_shortcut_key();
 
-        int it_key = it->second->get_shortcut_key();
-
-        if (it->second->is_activable() && ((it_key == key - 64) || (it_key == key - 96)))
-        {
-            if ((it->second->get_state() == GLGizmoBase::On))
-            {
-                it->second->set_state(GLGizmoBase::Off);
-                if (it->second->get_state() == GLGizmoBase::Off) {
-                    m_current = Undefined;
-                }
+        if (m_gizmos[idx]->is_activable() && ((it_key == key - 64) || (it_key == key - 96))) {
+                activate_gizmo(m_current == idx ? Undefined : (EType)idx);
                 handled = true;
-            }
-            else if ((it->second->get_state() == GLGizmoBase::Off))
-            {
-                // Before turning anything on, turn everything else off to see if
-                // nobody refuses. Only then activate the gizmo.
-                bool can_open = true;
-                for (GizmosMap::iterator i = m_gizmos.begin(); i != m_gizmos.end(); ++i) {
-                    if (i->first != it->first) {
-                        if (m_current == i->first && i->second->get_state() != GLGizmoBase::Off ) {
-                            i->second->set_state(GLGizmoBase::Off);
-                            if (i->second->get_state() != GLGizmoBase::Off)
-                                can_open = false;
-                        }
-                    }
-                }
-                if (can_open) {
-                    it->second->set_state(GLGizmoBase::On);
-                    m_current = it->first;
-                }
-                handled = true;
-            }
         }
     }
 
@@ -328,31 +260,25 @@ bool GLGizmosManager::handle_shortcut(int key)
 
 bool GLGizmosManager::is_dragging() const
 {
-    if (!m_enabled)
+    if (! m_enabled || m_current == Undefined)
         return false;
 
-    GLGizmoBase* curr = get_current();
-    return (curr != nullptr) ? curr->is_dragging() : false;
+    return m_gizmos[m_current]->is_dragging();
 }
 
 void GLGizmosManager::start_dragging()
 {
-    if (!m_enabled)
+    if (! m_enabled || m_current == Undefined)
         return;
-
-    GLGizmoBase* curr = get_current();
-    if (curr != nullptr)
-        curr->start_dragging();
+    m_gizmos[m_current]->start_dragging();
 }
 
 void GLGizmosManager::stop_dragging()
 {
-    if (!m_enabled)
+    if (! m_enabled || m_current == Undefined)
         return;
 
-    GLGizmoBase* curr = get_current();
-    if (curr != nullptr)
-        curr->stop_dragging();
+    m_gizmos[m_current]->stop_dragging();
 }
 
 Vec3d GLGizmosManager::get_displacement() const
@@ -360,8 +286,7 @@ Vec3d GLGizmosManager::get_displacement() const
     if (!m_enabled)
         return Vec3d::Zero();
 
-    GizmosMap::const_iterator it = m_gizmos.find(Move);
-    return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoMove3D*>(it->second)->get_displacement() : Vec3d::Zero();
+    return dynamic_cast<GLGizmoMove3D*>(m_gizmos[Move].get())->get_displacement();
 }
 
 Vec3d GLGizmosManager::get_scale() const
@@ -369,126 +294,101 @@ Vec3d GLGizmosManager::get_scale() const
     if (!m_enabled)
         return Vec3d::Ones();
 
-    GizmosMap::const_iterator it = m_gizmos.find(Scale);
-    return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoScale3D*>(it->second)->get_scale() : Vec3d::Ones();
+    return dynamic_cast<GLGizmoScale3D*>(m_gizmos[Scale].get())->get_scale();
 }
 
 void GLGizmosManager::set_scale(const Vec3d& scale)
 {
-    if (!m_enabled)
+    if (!m_enabled || m_gizmos.empty())
         return;
 
-    GizmosMap::const_iterator it = m_gizmos.find(Scale);
-    if (it != m_gizmos.end())
-        reinterpret_cast<GLGizmoScale3D*>(it->second)->set_scale(scale);
+    dynamic_cast<GLGizmoScale3D*>(m_gizmos[Scale].get())->set_scale(scale);
 }
 
 Vec3d GLGizmosManager::get_scale_offset() const
 {
-    if (!m_enabled)
+    if (!m_enabled || m_gizmos.empty())
         return Vec3d::Zero();
 
-    GizmosMap::const_iterator it = m_gizmos.find(Scale);
-    return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoScale3D*>(it->second)->get_offset() : Vec3d::Zero();
+    return dynamic_cast<GLGizmoScale3D*>(m_gizmos[Scale].get())->get_offset();
 }
 
 Vec3d GLGizmosManager::get_rotation() const
 {
-    if (!m_enabled)
+    if (!m_enabled || m_gizmos.empty())
         return Vec3d::Zero();
 
-    GizmosMap::const_iterator it = m_gizmos.find(Rotate);
-    return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoRotate3D*>(it->second)->get_rotation() : Vec3d::Zero();
+    return dynamic_cast<GLGizmoRotate3D*>(m_gizmos[Rotate].get())->get_rotation();
 }
 
 void GLGizmosManager::set_rotation(const Vec3d& rotation)
 {
-    if (!m_enabled)
+    if (!m_enabled || m_gizmos.empty())
         return;
-
-    GizmosMap::const_iterator it = m_gizmos.find(Rotate);
-    if (it != m_gizmos.end())
-        reinterpret_cast<GLGizmoRotate3D*>(it->second)->set_rotation(rotation);
+    dynamic_cast<GLGizmoRotate3D*>(m_gizmos[Rotate].get())->set_rotation(rotation);
 }
 
 Vec3d GLGizmosManager::get_flattening_normal() const
 {
-    if (!m_enabled)
+    if (!m_enabled || m_gizmos.empty())
         return Vec3d::Zero();
 
-    GizmosMap::const_iterator it = m_gizmos.find(Flatten);
-    return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoFlatten*>(it->second)->get_flattening_normal() : Vec3d::Zero();
+    return dynamic_cast<GLGizmoFlatten*>(m_gizmos[Flatten].get())->get_flattening_normal();
 }
 
 void GLGizmosManager::set_flattening_data(const ModelObject* model_object)
 {
-    if (!m_enabled)
+    if (!m_enabled || m_gizmos.empty())
         return;
 
-    GizmosMap::const_iterator it = m_gizmos.find(Flatten);
-    if (it != m_gizmos.end())
-        reinterpret_cast<GLGizmoFlatten*>(it->second)->set_flattening_data(model_object);
+    dynamic_cast<GLGizmoFlatten*>(m_gizmos[Flatten].get())->set_flattening_data(model_object);
 }
 
 void GLGizmosManager::set_sla_support_data(ModelObject* model_object)
 {
-    if (!m_enabled)
+    if (!m_enabled || m_gizmos.empty())
         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, m_parent.get_selection());
+    dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->set_sla_support_data(model_object, m_parent.get_selection());
 }
 
 // Returns true if the gizmo used the event to do something, false otherwise.
 bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
 {
-    if (!m_enabled)
+    if (!m_enabled || m_gizmos.empty())
         return false;
 
-    GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
-    if (it != m_gizmos.end())
-        return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
-
-    return false;
+    return dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
 }
 
 ClippingPlane GLGizmosManager::get_sla_clipping_plane() const
 {
-    if (!m_enabled || m_current != SlaSupports)
+    if (!m_enabled || m_current != SlaSupports || m_gizmos.empty())
         return ClippingPlane::ClipsNothing();
 
-    GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
-    if (it != m_gizmos.end())
-        return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->get_sla_clipping_plane();
-
-    return ClippingPlane::ClipsNothing();
+    return dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->get_sla_clipping_plane();
 }
 
 bool GLGizmosManager::wants_reslice_supports_on_undo() const
 {
     return (m_current == SlaSupports
-        && dynamic_cast<const GLGizmoSlaSupports*>(m_gizmos.at(SlaSupports))->has_backend_supports());
+        && dynamic_cast<const GLGizmoSlaSupports*>(m_gizmos.at(SlaSupports).get())->has_backend_supports());
 }
 
 void GLGizmosManager::render_current_gizmo() const
 {
-    if (!m_enabled)
+    if (!m_enabled || m_current == Undefined)
         return;
 
-    GLGizmoBase* curr = get_current();
-    if (curr != nullptr)
-        curr->render();
+    m_gizmos[m_current]->render();
 }
 
 void GLGizmosManager::render_current_gizmo_for_picking_pass() const
 {
-    if (!m_enabled)
+    if (! m_enabled || m_current == Undefined)
         return;
 
-    GLGizmoBase* curr = get_current();
-    if (curr != nullptr)
-        curr->render_for_picking();
+    m_gizmos[m_current]->render_for_picking();
 }
 
 void GLGizmosManager::render_overlay() const
@@ -547,7 +447,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
         // if the button down was done on this toolbar, prevent from dragging into the scene
         processed = true;
 
-    if (!overlay_contains_mouse(mouse_pos))
+    if (get_gizmo_idx_from_mouse(mouse_pos) == Undefined)
     {
         // mouse is outside the toolbar
         m_tooltip = "";
@@ -557,14 +457,12 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
             if ((m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
                 // the gizmo got the event and took some action, there is no need to do anything more
                 processed = true;
-            else if (!selection.is_empty() && grabber_contains_mouse())
-            {
+            else if (!selection.is_empty() && grabber_contains_mouse()) {
                 update_data();
                 selection.start_dragging();
                 start_dragging();
 
-                if (m_current == Flatten)
-                {
+                if (m_current == Flatten) {
                     // Rotate the object so the normal points downward:
                     m_parent.do_flatten(get_flattening_normal(), L("Gizmo-Place on Face"));
                     wxGetApp().obj_manipul()->set_dirty();
@@ -634,25 +532,14 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
         }
         else if (evt.LeftUp() && is_dragging())
         {
-            switch (m_current)
-            {
-            case Move:
-            {
-                m_parent.do_move(L("Gizmo-Move"));
-                break;
-            }
-            case Scale:
-            {
-                m_parent.do_scale(L("Gizmo-Scale"));
-                break;
-            }
-            case Rotate:
-            {
-                m_parent.do_rotate(L("Gizmo-Rotate"));
-                break;
-            }
-            default:
-                break;
+            switch (m_current) {
+            case Move : m_parent.do_move(L("Gizmo-Move"));
+                        break;
+            case Scale : m_parent.do_scale(L("Gizmo-Scale"));
+                         break;
+            case Rotate : m_parent.do_rotate(L("Gizmo-Rotate"));
+                          break;
+            default : break;
             }
 
             stop_dragging();
@@ -842,7 +729,7 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
     {
         if (m_current == SlaSupports)
         {
-            GLGizmoSlaSupports* gizmo = reinterpret_cast<GLGizmoSlaSupports*>(get_current());
+            GLGizmoSlaSupports* gizmo = dynamic_cast<GLGizmoSlaSupports*>(get_current());
 
             if (keyCode == WXK_SHIFT)
             {
@@ -863,7 +750,8 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
     }
     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())
+        if ((m_current == SlaSupports) && ((keyCode == WXK_SHIFT) || (keyCode == WXK_ALT))
+          && dynamic_cast<GLGizmoSlaSupports*>(get_current())->is_in_editing_mode())
         {
 //            m_parent.set_cursor(GLCanvas3D::Cross);
             processed = true;
@@ -882,18 +770,7 @@ void GLGizmosManager::update_after_undo_redo(const UndoRedo::Snapshot& snapshot)
     m_serializing = false;
     if (m_current == SlaSupports
      && snapshot.snapshot_data.flags & UndoRedo::SnapshotData::RECALCULATE_SLA_SUPPORTS)
-        dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports])->reslice_SLA_supports(true);
-}
-
-void GLGizmosManager::reset()
-{
-    for (GizmosMap::value_type& gizmo : m_gizmos)
-    {
-        delete gizmo.second;
-        gizmo.second = nullptr;
-    }
-
-    m_gizmos.clear();
+        dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->reslice_SLA_supports(true);
 }
 
 void GLGizmosManager::render_background(float left, float top, float right, float bottom, float border) const
@@ -911,7 +788,7 @@ void GLGizmosManager::render_background(float left, float top, float right, floa
         float internal_top = top - border;
         float internal_bottom = bottom + border;
 
-        float left_uv = 0.0f;
+        // float left_uv = 0.0f;
         float right_uv = 1.0f;
         float top_uv = 1.0f;
         float bottom_uv = 0.0f;
@@ -981,33 +858,32 @@ void GLGizmosManager::do_render_overlay() const
     float scaled_icons_size = m_overlay_icons_size * m_overlay_scale * inv_zoom;
     float scaled_stride_y = scaled_icons_size + scaled_gap_y;
     unsigned int icons_texture_id = m_icons_texture.get_id();
-    unsigned int tex_width = m_icons_texture.get_width();
-    unsigned int tex_height = m_icons_texture.get_height();
-    float inv_tex_width = (tex_width != 0) ? 1.0f / (float)tex_width : 0.0f;
-    float inv_tex_height = (tex_height != 0) ? 1.0f / (float)tex_height : 0.0f;
+    int tex_width = m_icons_texture.get_width();
+    int tex_height = m_icons_texture.get_height();
+    float inv_tex_width = (tex_width != 0) ? 1.0f / tex_width : 0.0f;
+    float inv_tex_height = (tex_height != 0) ? 1.0f / tex_height : 0.0f;
 
     if ((icons_texture_id == 0) || (tex_width <= 0) || (tex_height <= 0))
         return;
 
-    for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
+    for (size_t idx : get_selectable_idxs())
     {
-        if ((it->second == nullptr) || !it->second->is_selectable())
-            continue;
+        GLGizmoBase* gizmo = m_gizmos[idx].get();
 
-        unsigned int sprite_id = it->second->get_sprite_id();
-        GLGizmoBase::EState state = it->second->get_state();
+        unsigned int sprite_id = gizmo->get_sprite_id();
+        int icon_idx = m_current == idx ? 2 : (m_hover == idx ? 1 : 0);
 
         float u_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_width;
         float v_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_height;
         float v_top = sprite_id * v_icon_size;
-        float u_left = state * u_icon_size;
+        float u_left = icon_idx * u_icon_size;
         float v_bottom = v_top + v_icon_size;
         float u_right = u_left + u_icon_size;
 
         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 - m_parent.get_view_toolbar_height();
-            it->second->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top);
+        if (idx == m_current) {
+            float toolbar_top = cnv_h - m_parent.get_view_toolbar_height();
+            gizmo->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top);
         }
         top_y -= scaled_stride_y;
     }
@@ -1021,13 +897,14 @@ float GLGizmosManager::get_total_overlay_height() const
     float scaled_stride_y = scaled_icons_size + scaled_gap_y;
     float height = 2.0f * scaled_border;
 
-    for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
+    /*for (size_t idx=0; idx<m_gizmos.size(); ++idx)
     {
-        if ((it->second == nullptr) || !it->second->is_selectable())
+        if ((m_gizmos[idx] == nullptr) || !m_gizmos[idx]->is_selectable())
             continue;
 
         height += scaled_stride_y;
-    }
+    }*/
+    height += get_selectable_idxs().size() * scaled_stride_y;
 
     return height - scaled_gap_y;
 }
@@ -1039,19 +916,21 @@ float GLGizmosManager::get_total_overlay_width() const
 
 GLGizmoBase* GLGizmosManager::get_current() const
 {
-    GizmosMap::const_iterator it = m_gizmos.find(m_current);
-    return (it != m_gizmos.end()) ? it->second : nullptr;
+    if (m_current==Undefined || m_gizmos.empty())
+        return nullptr;
+    else
+        return m_gizmos[m_current].get();
 }
 
 bool GLGizmosManager::generate_icons_texture() const
 {
     std::string path = resources_dir() + "/icons/";
     std::vector<std::string> filenames;
-    for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
+    for (size_t idx=0; idx<m_gizmos.size(); ++idx)
     {
-        if (it->second != nullptr)
+        if (m_gizmos[idx] != nullptr)
         {
-            const std::string& icon_filename = it->second->get_icon_filename();
+            const std::string& icon_filename = m_gizmos[idx]->get_icon_filename();
             if (!icon_filename.empty())
                 filenames.push_back(path + icon_filename);
         }
@@ -1074,74 +953,9 @@ void GLGizmosManager::update_on_off_state(const Vec2d& mouse_pos)
     if (!m_enabled)
         return;
 
-    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;
-    float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
-    float scaled_stride_y = scaled_icons_size + scaled_gap_y;
-    float top_y = 0.5f * (cnv_h - height) + scaled_border;
-
-    auto inside = [scaled_border, scaled_icons_size, &mouse_pos](float top_y) {
-        return (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
-    };
-
-    bool could_activate = true;
-    for (std::pair<const GLGizmosManager::EType, GLGizmoBase*> &type_and_gizmo : m_gizmos)
-    {
-        GLGizmoBase *gizmo = type_and_gizmo.second;
-        if ((gizmo == nullptr) || !gizmo->is_selectable())
-            continue;
-
-        if (! (gizmo->is_activable() && inside(top_y))) {
-            gizmo->set_state(GLGizmoBase::Off);
-            if (gizmo->get_state() != GLGizmoBase::Off) {
-                // Gizmo refused to leave it's active state. Don't try to select
-                could_activate = false;
-            }
-        }
-
-        top_y += scaled_stride_y;
-    }
-
-    // We may change m_current soon. If we did it during following loop, gizmos that take undo/redo snapshots
-    // in their on_set_state function could snapshot a state with the new gizmo already active.
-    // Therefore, just remember what needs to be done and actually change m_current afterwards.
-    EType new_current = m_current;
-    top_y = 0.5f * (cnv_h - height) + scaled_border;
-    for (std::pair<const GLGizmosManager::EType, GLGizmoBase*> &type_and_gizmo : m_gizmos)
-    {
-        GLGizmoBase *gizmo = type_and_gizmo.second;
-        if ((gizmo == nullptr) || !gizmo->is_selectable())
-            continue;
-
-        if (gizmo->is_activable() && inside(top_y))
-        {
-            if ((gizmo->get_state() == GLGizmoBase::On))
-            {
-                gizmo->set_state(GLGizmoBase::Off);
-                if (gizmo->get_state() == GLGizmoBase::Off) {
-                    gizmo->set_state(GLGizmoBase::Hover);
-                    new_current = Undefined;
-                }
-            }
-            else if ((gizmo->get_state() == GLGizmoBase::Hover) && could_activate)
-            {
-                gizmo->set_state(GLGizmoBase::On);
-                new_current = type_and_gizmo.first;
-            }
-        }
-
-        top_y += scaled_stride_y;
-    }
-    m_current = new_current;
-
-    if (could_activate) {
-        GizmosMap::iterator it = m_gizmos.find(m_current);
-        if ((it != m_gizmos.end()) && (it->second != nullptr) && (it->second->get_state() != GLGizmoBase::On))
-            it->second->set_state(GLGizmoBase::On);
-    }
+    size_t idx = get_gizmo_idx_from_mouse(mouse_pos);
+    if (idx != Undefined && m_gizmos[idx]->is_activable() && m_hover == idx)
+        activate_gizmo(m_current == idx ? Undefined : (EType)idx);
 }
 
 std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos)
@@ -1151,60 +965,37 @@ std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos)
     if (!m_enabled)
         return name;
 
-    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;
-    float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
-    float scaled_stride_y = scaled_icons_size + scaled_gap_y;
-    float top_y = 0.5f * (cnv_h - height) + scaled_border;
+    m_hover = Undefined;
 
-    for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
-    {
-        if ((it->second == nullptr) || !it->second->is_selectable())
-            continue;
+    size_t idx = get_gizmo_idx_from_mouse(mouse_pos);
+    if (idx != Undefined) {
+        name = m_gizmos[idx]->get_name();
 
-        bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
-        if (inside)
-            name = it->second->get_name();
-
-        if (it->second->is_activable() && (it->second->get_state() != GLGizmoBase::On))
-            it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off);
-
-        top_y += scaled_stride_y;
+        if (m_gizmos[idx]->is_activable())
+            m_hover = (EType)idx;
     }
 
     return name;
 }
 
-bool GLGizmosManager::overlay_contains_mouse(const Vec2d& mouse_pos) const
+void GLGizmosManager::activate_gizmo(EType type)
 {
-    if (!m_enabled)
-        return false;
+    if (m_gizmos.empty() || m_current == type)
+        return;
 
-    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;
-    float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
-    float scaled_stride_y = scaled_icons_size + scaled_gap_y;
-    float top_y = 0.5f * (cnv_h - height) + scaled_border;
-
-    for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
-    {
-        if ((it->second == nullptr) || !it->second->is_selectable())
-            continue;
-
-        if ((scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size))
-            return true;
-
-        top_y += scaled_stride_y;
+    if (m_current != Undefined) {
+        m_gizmos[m_current]->set_state(GLGizmoBase::Off);
+        if (m_gizmos[m_current]->get_state() != GLGizmoBase::Off)
+            return; // gizmo refused to be turned off, do nothing.
     }
 
-    return false;
+    if (type != Undefined)
+        m_gizmos[type]->set_state(GLGizmoBase::On);
+
+    m_current = type;
 }
 
+
 bool GLGizmosManager::grabber_contains_mouse() const
 {
     if (!m_enabled)
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
index c0adeb957..f649c98b2 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
@@ -54,25 +54,30 @@ public:
 
     enum EType : unsigned char
     {
-        Undefined,
         Move,
         Scale,
         Rotate,
         Flatten,
         Cut,
         SlaSupports,
-        Num_Types
+        Undefined
     };
 
 private:
     GLCanvas3D& m_parent;
     bool m_enabled;
-    typedef std::map<EType, GLGizmoBase*> GizmosMap;
-    GizmosMap m_gizmos;
+    std::vector<std::unique_ptr<GLGizmoBase>> m_gizmos;
     mutable GLTexture m_icons_texture;
     mutable bool m_icons_texture_dirty;
     BackgroundTexture m_background_texture;
     EType m_current;
+    EType m_hover;
+
+    std::vector<size_t> get_selectable_idxs() const;
+    std::vector<size_t> get_activable_idxs() const;
+    size_t get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const;
+
+    void activate_gizmo(EType type);
 
     float m_overlay_icons_size;
     float m_overlay_scale;
@@ -98,7 +103,6 @@ private:
 
 public:
     explicit GLGizmosManager(GLCanvas3D& parent);
-    ~GLGizmosManager();
 
     bool init();
 
@@ -112,16 +116,8 @@ public:
 
         ar(m_current);
 
-        GLGizmoBase* curr = get_current();
-		for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) {
-			GLGizmoBase* gizmo = it->second;
-			if (gizmo != nullptr) {
-				gizmo->set_hover_id(-1);
-				gizmo->set_state((it->second == curr) ? GLGizmoBase::On : GLGizmoBase::Off);
-				if (gizmo == curr)
-					gizmo->load(ar);
-			}
-		}
+        if (m_current != Undefined)
+            m_gizmos[m_current]->load(ar);
     }
 
     template<class Archive>
@@ -132,9 +128,8 @@ public:
 
         ar(m_current);
 
-        GLGizmoBase* curr = get_current();
-        if (curr != nullptr)
-            curr->save(ar);
+        if (m_current != Undefined && !m_gizmos.empty())
+            m_gizmos[m_current]->save(ar);
     }
 
     bool is_enabled() const { return m_enabled; }
@@ -195,8 +190,6 @@ public:
     void update_after_undo_redo(const UndoRedo::Snapshot& snapshot);
 
 private:
-    void reset();
-
     void render_background(float left, float top, float right, float bottom, float border) const;
     void do_render_overlay() const;
 
@@ -209,7 +202,6 @@ private:
 
     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;
 };