From 102bc99958b8f904c7c36fa3d2fb138954c4b082 Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Wed, 7 Nov 2018 12:11:34 +0100
Subject: [PATCH] Only one instance enabled when selecting sub parts

---
 src/slic3r/GUI/3DScene.cpp    |  4 +++
 src/slic3r/GUI/3DScene.hpp    |  3 ++
 src/slic3r/GUI/GLCanvas3D.cpp | 68 ++++++++++++++++++++++++++++++++---
 src/slic3r/GUI/GLCanvas3D.hpp |  1 +
 4 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index 11f0b570e..565ef94fb 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -193,6 +193,7 @@ const float GLVolume::SELECTED_COLOR[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
 const float GLVolume::HOVER_COLOR[4] = { 0.4f, 0.9f, 0.1f, 1.0f };
 const float GLVolume::OUTSIDE_COLOR[4] = { 0.0f, 0.38f, 0.8f, 1.0f };
 const float GLVolume::SELECTED_OUTSIDE_COLOR[4] = { 0.19f, 0.58f, 1.0f, 1.0f };
+const float GLVolume::DISABLED_COLOR[4] = { 0.25f, 0.25f, 0.25f, 1.0f };
 
 GLVolume::GLVolume(float r, float g, float b, float a)
 #if ENABLE_MODELVOLUME_TRANSFORM
@@ -211,6 +212,7 @@ GLVolume::GLVolume(float r, float g, float b, float a)
     , composite_id(-1)
     , extruder_id(0)
     , selected(false)
+    , disabled(false)
     , is_active(true)
     , zoom_to_volumes(true)
     , shader_outside_printer_detection_enabled(false)
@@ -252,6 +254,8 @@ void GLVolume::set_render_color()
         set_render_color(is_outside ? SELECTED_OUTSIDE_COLOR : SELECTED_COLOR, 4);
     else if (hover)
         set_render_color(HOVER_COLOR, 4);
+    else if (disabled)
+        set_render_color(DISABLED_COLOR, 4);
     else if (is_outside && shader_outside_printer_detection_enabled)
         set_render_color(OUTSIDE_COLOR, 4);
     else
diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp
index 8384e11b8..87c9df385 100644
--- a/src/slic3r/GUI/3DScene.hpp
+++ b/src/slic3r/GUI/3DScene.hpp
@@ -249,6 +249,7 @@ public:
     static const float HOVER_COLOR[4];
     static const float OUTSIDE_COLOR[4];
     static const float SELECTED_OUTSIDE_COLOR[4];
+    static const float DISABLED_COLOR[4];
 
     GLVolume(float r = 1.f, float g = 1.f, float b = 1.f, float a = 1.f);
     GLVolume(const float *rgba) : GLVolume(rgba[0], rgba[1], rgba[2], rgba[3]) {}
@@ -295,6 +296,8 @@ public:
     int                 extruder_id;
     // Is this object selected?
     bool                selected;
+    // Is this object disabled from selection?
+    bool                disabled;
     // Whether or not this volume is active for rendering
     bool                is_active;
     // Whether or not to use this volume when applying zoom_to_volumes()
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index f9a265829..1cd5fe6fc 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1212,13 +1212,14 @@ void GLCanvas3D::Selection::add(unsigned int volume_idx, bool as_single_selectio
     if (needs_reset)
         clear();
 
-    m_mode = volume->is_modifier ? Volume : Instance;
+    if (volume->is_modifier)
+        m_mode = Volume;
 
     switch (m_mode)
     {
     case Volume:
     {
-        if (is_empty() || ((is_modifier() && volume->is_modifier) && (volume->instance_idx() == get_instance_idx())))
+        if (is_empty() || (volume->instance_idx() == get_instance_idx()))
             _add_volume(volume_idx);
 
         break;
@@ -1282,6 +1283,8 @@ void GLCanvas3D::Selection::add_object(unsigned int object_idx, bool as_single_s
     if (as_single_selection)
         clear();
 
+    m_mode = Instance;
+
     _add_object(object_idx);
 
     _update_type();
@@ -1308,6 +1311,8 @@ void GLCanvas3D::Selection::add_instance(unsigned int object_idx, unsigned int i
     if (as_single_selection)
         clear();
 
+    m_mode = Instance;
+
     _add_instance(object_idx, instance_idx);
 
     _update_type();
@@ -1334,13 +1339,15 @@ void GLCanvas3D::Selection::add_volume(unsigned int object_idx, unsigned int vol
     if (as_single_selection)
         clear();
 
+    m_mode = Volume;
+
     for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
     {
         GLVolume* v = (*m_volumes)[i];
         if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx))
         {
             if ((instance_idx != -1) && (v->instance_idx() == instance_idx))
-            _add_volume(i);
+                _add_volume(i);
         }
     }
 
@@ -1375,6 +1382,7 @@ void GLCanvas3D::Selection::clear()
     }
 
     m_list.clear();
+
     _update_type();
     m_bounding_box_dirty = true;
 }
@@ -1754,6 +1762,7 @@ void GLCanvas3D::Selection::render() const
 
     // render cumulative bounding box of selected volumes
     _render_selected_volumes();
+    _render_synchronized_volumes();
 }
 
 void GLCanvas3D::Selection::_update_valid()
@@ -1778,6 +1787,8 @@ void GLCanvas3D::Selection::_update_type()
         obj_it->second.insert(inst_idx);
     }
 
+    bool requires_disable = false;
+
     if (!m_valid)
         m_type = Invalid;
     else
@@ -1790,7 +1801,10 @@ void GLCanvas3D::Selection::_update_type()
             if (first->is_wipe_tower)
                 m_type = WipeTower;
             else if (first->is_modifier)
+            {
                 m_type = SingleModifier;
+                requires_disable = true;
+            }
             else
             {
                 const ModelObject* model_object = m_model->objects[first->object_idx()];
@@ -1801,7 +1815,10 @@ void GLCanvas3D::Selection::_update_type()
                 else if (volumes_count == 1) // instances_count > 1
                     m_type = SingleFullInstance;
                 else
+                {
                     m_type = SingleVolume;
+                    requires_disable = true;
+                }
             }
         }
         else
@@ -1828,9 +1845,15 @@ void GLCanvas3D::Selection::_update_type()
                         }
 
                         if (modifiers_count == 0)
+                        {
                             m_type = MultipleVolume;
+                            requires_disable = true;
+                        }
                         else if (modifiers_count == (unsigned int)m_list.size())
+                        {
                             m_type = MultipleModifier;
+                            requires_disable = true;
+                        }
                     }
                 }
                 else if ((selected_instances_count > 1) && (selected_instances_count * volumes_count == (unsigned int)m_list.size()))
@@ -1839,6 +1862,13 @@ void GLCanvas3D::Selection::_update_type()
         }
     }
 
+    int object_idx = get_object_idx();
+    int instance_idx = get_instance_idx();
+    for (GLVolume* v : *m_volumes)
+    {
+        v->disabled = requires_disable ? (v->object_idx() != object_idx) || (v->instance_idx() != instance_idx) : false;
+    }
+
     switch (m_type)
     {
     case Invalid:
@@ -1994,6 +2024,33 @@ void GLCanvas3D::Selection::_render_selected_volumes() const
     _render_bounding_box(get_bounding_box(), color);
 }
 
+void GLCanvas3D::Selection::_render_synchronized_volumes() const
+{
+    if (m_mode == Instance)
+        return;
+
+    float color[3] = { 1.0f, 1.0f, 0.0f };
+
+    for (unsigned int i : m_list)
+    {
+        const GLVolume* volume = (*m_volumes)[i];
+        int object_idx = volume->object_idx();
+        int instance_idx = volume->instance_idx();
+        int volume_idx = volume->volume_idx();
+        for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
+        {
+            if (i == j)
+                continue;
+
+            const GLVolume* v = (*m_volumes)[j];
+            if ((v->object_idx() != object_idx) || (v->volume_idx() != volume_idx))
+                continue;
+
+            _render_bounding_box(v->transformed_convex_hull_bounding_box(), color);
+        }
+    }
+}
+
 void GLCanvas3D::Selection::_render_bounding_box(const BoundingBoxf3& box, float* color) const
 {
     if (color == nullptr)
@@ -4253,6 +4310,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
 #endif // ENABLE_GIZMOS_RESET
             {
                 m_selection.clear();
+                m_selection.set_mode(Selection::Instance);
                 wxGetApp().obj_manipul()->update_settings_value(m_selection);
                 post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
                 _update_gizmos_data();
@@ -4968,7 +5026,9 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const
             ::glColor4fv(vol->render_color);
         }
 
-        vol->render();
+        if (!fake_colors || !vol->disabled)
+            vol->render();
+
         ++volume_id;
     }
 
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index f68c2a702..b1b78d3b4 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -535,6 +535,7 @@ public:
         void _remove_object(unsigned int object_idx);
         void _calc_bounding_box() const;
         void _render_selected_volumes() const;
+        void _render_synchronized_volumes() const;
         void _render_bounding_box(const BoundingBoxf3& box, float* color) const;
         void _synchronize_unselected_instances();
         void _synchronize_unselected_volumes();