diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
index 9fae8893a..7f33916cd 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
@@ -2,6 +2,7 @@
 #include "GLGizmoFlatten.hpp"
 #include "slic3r/GUI/GLCanvas3D.hpp"
 #include "slic3r/GUI/GUI_App.hpp"
+#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
 
 #include <numeric>
 
@@ -26,20 +27,15 @@ bool GLGizmoFlatten::on_init()
 
 void GLGizmoFlatten::on_set_state()
 {
-    // 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;
-    for (const auto mo : wxGetApp().model().objects) {
-        if (mo->id() == m_model_object_id) {
-            m_model_object = mo;
-            break;
-        }
-    }
-
     if (m_state == On && is_plane_update_necessary())
         update_planes();
 }
 
+CommonGizmosDataID GLGizmoFlatten::on_get_requirements() const
+{
+    return CommonGizmosDataID::SelectionInfo;
+}
+
 std::string GLGizmoFlatten::on_get_name() const
 {
     return (_(L("Place on face")) + " [F]").ToUTF8().data();
@@ -132,18 +128,17 @@ void GLGizmoFlatten::on_render_for_picking() const
 void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
 {
     m_starting_center = Vec3d::Zero();
-    if (m_model_object != model_object) {
+    if (model_object != m_old_model_object) {
         m_planes.clear();
         m_planes_valid = false;
     }
-    m_model_object = model_object;
-    m_model_object_id = model_object ? model_object->id() : 0;
 }
 
 void GLGizmoFlatten::update_planes()
 {
+    const ModelObject* mo = m_c->selection_info()->model_object();
     TriangleMesh ch;
-    for (const ModelVolume* vol : m_model_object->volumes)
+    for (const ModelVolume* vol : mo->volumes)
     {
         if (vol->type() != ModelVolumeType::MODEL_PART)
             continue;
@@ -153,7 +148,7 @@ void GLGizmoFlatten::update_planes()
     }
     ch = ch.convex_hull_3d();
     m_planes.clear();
-    const Transform3d& inst_matrix = m_model_object->instances.front()->get_matrix(true);
+    const Transform3d& inst_matrix = mo->instances.front()->get_matrix(true);
 
     // Following constants are used for discarding too small polygons.
     const float minimal_area = 5.f; // in square mm (world coordinates)
@@ -331,12 +326,13 @@ void GLGizmoFlatten::update_planes()
     // Planes are finished - let's save what we calculated it from:
     m_volumes_matrices.clear();
     m_volumes_types.clear();
-    for (const ModelVolume* vol : m_model_object->volumes) {
+    for (const ModelVolume* vol : mo->volumes) {
         m_volumes_matrices.push_back(vol->get_matrix());
         m_volumes_types.push_back(vol->type());
     }
-    m_first_instance_scale = m_model_object->instances.front()->get_scaling_factor();
-    m_first_instance_mirror = m_model_object->instances.front()->get_mirror();
+    m_first_instance_scale = mo->instances.front()->get_scaling_factor();
+    m_first_instance_mirror = mo->instances.front()->get_mirror();
+    m_old_model_object = mo;
 
     m_planes_valid = true;
 }
@@ -344,20 +340,22 @@ void GLGizmoFlatten::update_planes()
 
 bool GLGizmoFlatten::is_plane_update_necessary() const
 {
-    if (m_state != On || !m_model_object || m_model_object->instances.empty())
+    const ModelObject* mo = m_c->selection_info()->model_object();
+    if (m_state != On || ! mo || mo->instances.empty())
         return false;
 
-    if (! m_planes_valid || m_model_object->volumes.size() != m_volumes_matrices.size())
+    if (! m_planes_valid || mo != m_old_model_object
+     || mo->volumes.size() != m_volumes_matrices.size())
         return true;
 
     // We want to recalculate when the scale changes - some planes could (dis)appear.
-    if (! m_model_object->instances.front()->get_scaling_factor().isApprox(m_first_instance_scale)
-     || ! m_model_object->instances.front()->get_mirror().isApprox(m_first_instance_mirror))
+    if (! mo->instances.front()->get_scaling_factor().isApprox(m_first_instance_scale)
+     || ! mo->instances.front()->get_mirror().isApprox(m_first_instance_mirror))
         return true;
 
-    for (unsigned int i=0; i < m_model_object->volumes.size(); ++i)
-        if (! m_model_object->volumes[i]->get_matrix().isApprox(m_volumes_matrices[i])
-         || m_model_object->volumes[i]->type() != m_volumes_types[i])
+    for (unsigned int i=0; i < mo->volumes.size(); ++i)
+        if (! mo->volumes[i]->get_matrix().isApprox(m_volumes_matrices[i])
+         || mo->volumes[i]->type() != m_volumes_types[i])
             return true;
 
     return false;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
index 9cd2ab6bb..05b4ae4cd 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
@@ -30,8 +30,7 @@ private:
     std::vector<PlaneData> m_planes;
     bool m_planes_valid = false;
     mutable Vec3d m_starting_center;
-    const ModelObject* m_model_object = nullptr;
-    ObjectID m_model_object_id = 0;
+    const ModelObject* m_old_model_object = nullptr;
     std::vector<const Transform3d*> instances_matrices;
 
     void update_planes();
@@ -51,6 +50,7 @@ protected:
     virtual void on_render() const override;
     virtual void on_render_for_picking() const override;
     virtual void on_set_state() override;
+    virtual CommonGizmosDataID on_get_requirements() const override;
 };
 
 } // namespace GUI
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp
index bcc562d8b..8022b93f2 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp
@@ -7,11 +7,11 @@
 namespace Slic3r {
 namespace GUI {
 
+using namespace CommonGizmosDataObjects;
 
 CommonGizmosDataPool::CommonGizmosDataPool(GLCanvas3D* canvas)
     : m_canvas(canvas)
 {
-    using namespace CommonGizmosDataObjects;
     using c = CommonGizmosDataID;
     m_data[c::SelectionInfo].reset(       new SelectionInfo(this));
     //m_data[c::InstancesHider].reset(      new InstancesHider(this));
@@ -24,8 +24,19 @@ CommonGizmosDataPool::CommonGizmosDataPool(GLCanvas3D* canvas)
 void CommonGizmosDataPool::update(CommonGizmosDataID required)
 {
     assert(check_dependencies(required));
-    for (auto& [id, data] : m_data)
-        data->update(int(required) & int(CommonGizmosDataID(id)));
+    for (auto& [id, data] : m_data) {
+        if (int(required) & int(CommonGizmosDataID(id)))
+            data->update();
+        else if (data->is_valid())
+            data->release();
+    }
+}
+
+
+SelectionInfo* CommonGizmosDataPool::selection_info()
+{
+    SelectionInfo* sel_info = dynamic_cast<SelectionInfo*>(m_data[CommonGizmosDataID::SelectionInfo].get());
+    return sel_info;
 }
 
 #ifndef NDEBUG
@@ -41,13 +52,19 @@ bool CommonGizmosDataPool::check_dependencies(CommonGizmosDataID required) const
 
 
 
-void CommonGizmosDataObjects::SelectionInfo::update(bool required)
+void SelectionInfo::on_update()
 {
     Selection selection = m_common->get_canvas()->get_selection();
-
+    if (selection.is_single_full_instance())
+        m_model_object = selection.get_model()->objects[selection.get_object_idx()];
+    else
+        m_model_object = nullptr;
 }
 
-
+void SelectionInfo::on_release()
+{
+    m_model_object = nullptr;
+}
 
 } // namespace GUI
 } // namespace Slic3r
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp
index 259de5013..3f3854ffa 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp
@@ -46,10 +46,10 @@ public:
 
     // Update all resources and release what is not used.
     // Accepts a bitmask of currently required resources.
-    void update(CommonGizmosDataID required = CommonGizmosDataID::None);
+    void update(CommonGizmosDataID required);
 
     // Getters for the data that need to be accessed from the gizmos directly.
-    CommonGizmosDataObjects::SelectionInfo selection_info();
+    CommonGizmosDataObjects::SelectionInfo* selection_info();
 
     GLCanvas3D* get_canvas() const { return m_canvas; }
 
@@ -74,16 +74,21 @@ public:
     // objects can communicate with one another.
     explicit CommonGizmosDataBase(CommonGizmosDataPool* cgdp)
         : m_common{cgdp} {}
+    virtual ~CommonGizmosDataBase() {}
 
-    // Update the resource. If it is not needed (based on argument value)
-    // any persistent data will be released.
-    virtual void update(bool required) = 0;
+    // Update the resource.
+    void update() { on_update(); m_is_valid = true; }
+
+    // Release any data that are stored internally.
+    void release() { on_release(); m_is_valid = false; }
 
     // Returns whether the resource is currently maintained.
     bool is_valid() const { return m_is_valid; }
 
 protected:
     CommonGizmosDataPool* m_common = nullptr;
+    virtual void on_release() = 0;
+    virtual void on_update() = 0;
 
 private:
     bool m_is_valid = false;
@@ -99,13 +104,16 @@ namespace CommonGizmosDataObjects
 class SelectionInfo : public CommonGizmosDataBase
 {
 public:
-    explicit SelectionInfo(CommonGizmosDataPool* cgdp) :
-        CommonGizmosDataBase(cgdp) {}
-    void update(bool required) override;
+    explicit SelectionInfo(CommonGizmosDataPool* cgdp)
+        : CommonGizmosDataBase(cgdp) {}
 
-    ModelObject* model_object();
+    ModelObject* model_object() { return m_model_object; }
     int get_active_instance();
 
+protected:
+    void on_update() override;
+    void on_release() override;
+
 private:
     ModelObject* m_model_object = nullptr;
     int m_active_inst = -1;
@@ -115,8 +123,8 @@ private:
 class InstancesHider : public CommonGizmosDataBase
 {
 public:
-    explicit InstancesHider(CommonGizmosDataPool* cgdp) :
-        CommonGizmosDataBase(cgdp) {}
+    explicit InstancesHider(CommonGizmosDataPool* cgdp)
+        : CommonGizmosDataBase(cgdp) {}
     void update(bool required) override;
 };
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
index 9600b3d64..d5be7cd10 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
@@ -201,6 +201,10 @@ void GLGizmosManager::update_data()
         enable_grabber(Scale, i, enable_scale_xyz);
     }
 
+    m_common_gizmos_data->update(get_current()
+                           ? get_current()->get_requirements()
+                           : CommonGizmosDataID(0));
+
     if (selection.is_single_full_instance())
     {
         // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first