From ed271d66e67ac71ba4cbe681bcfb2a6ae1c4630b Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Thu, 15 Nov 2018 11:38:40 +0100
Subject: [PATCH 1/4] Fixed object picking when gizmos are rendered on top

---
 src/slic3r/GUI/GLCanvas3D.cpp | 20 ++++++++++++++++++++
 src/slic3r/GUI/GLCanvas3D.hpp |  3 +++
 2 files changed, 23 insertions(+)

diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index c7a1bad5b..da6a9839c 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1103,6 +1103,9 @@ GLCanvas3D::Mouse::Drag::Drag()
 GLCanvas3D::Mouse::Mouse()
     : dragging(false)
     , position(DBL_MAX, DBL_MAX)
+#if ENABLE_GIZMOS_ON_TOP
+    , scene_position(DBL_MAX, DBL_MAX, DBL_MAX)
+#endif // ENABLE_GIZMOS_ON_TOP
 #if ENABLE_GIZMOS_RESET
     , ignore_up_event(false)
 #endif // ENABLE_GIZMOS_RESET
@@ -3601,6 +3604,13 @@ void GLCanvas3D::render()
         _render_bed(theta);
     }
 
+#if ENABLE_GIZMOS_ON_TOP
+    // we need to set the mouse's scene position here because the depth buffer
+    // could be invalidated by the following gizmo render methods
+    // this position is used later into on_mouse() to drag the objects
+    m_mouse.scene_position = _mouse_to_3d(m_mouse.position.cast<int>());
+#endif // ENABLE_GIZMOS_ON_TOP
+
     _render_current_gizmo();
     _render_cutting_plane();
 #if ENABLE_SHOW_CAMERA_TARGET
@@ -4176,19 +4186,29 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
             {
                 if (evt.LeftDown() && m_moving_enabled && (m_mouse.drag.move_volume_idx == -1))
                 {
+#if !ENABLE_GIZMOS_ON_TOP
                     // The mouse_to_3d gets the Z coordinate from the Z buffer at the screen coordinate pos x, y,
                     // an converts the screen space coordinate to unscaled object space.
                     Vec3d pos3d = _mouse_to_3d(pos);
+#endif // !ENABLE_GIZMOS_ON_TOP
 
                     // Only accept the initial position, if it is inside the volume bounding box.
                     BoundingBoxf3 volume_bbox = m_volumes.volumes[m_hover_volume_id]->transformed_bounding_box();
                     volume_bbox.offset(1.0);
+#if ENABLE_GIZMOS_ON_TOP
+                    if (volume_bbox.contains(m_mouse.scene_position))
+#else
                     if (volume_bbox.contains(pos3d))
+#endif // ENABLE_GIZMOS_ON_TOP
                     {
                         // The dragging operation is initiated.
                         m_mouse.drag.move_volume_idx = m_hover_volume_id;
                         m_selection.start_dragging();
+#if ENABLE_GIZMOS_ON_TOP
+                        m_mouse.drag.start_position_3D = m_mouse.scene_position;
+#else
                         m_mouse.drag.start_position_3D = pos3d;
+#endif // ENABLE_GIZMOS_ON_TOP
                     }
                 }
                 else if (evt.RightDown())
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index fd4fa1953..be48b1ac2 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -337,6 +337,9 @@ class GLCanvas3D
 
         bool dragging;
         Vec2d position;
+#if ENABLE_GIZMOS_ON_TOP
+        Vec3d scene_position;
+#endif // ENABLE_GIZMOS_ON_TOP
         Drag drag;
 #if ENABLE_GIZMOS_RESET
         bool ignore_up_event;

From e83e755e8b9aab7c021ae8a368424154e9e5da17 Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Thu, 15 Nov 2018 12:21:09 +0100
Subject: [PATCH 2/4] Fixed crash when dismissing file dialog for quick slice
 menu command

---
 src/slic3r/GUI/MainFrame.cpp | 26 +++++++++++++-------------
 src/slic3r/GUI/MainFrame.hpp |  1 +
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp
index df4cba60b..b67d19af2 100644
--- a/src/slic3r/GUI/MainFrame.cpp
+++ b/src/slic3r/GUI/MainFrame.cpp
@@ -233,25 +233,25 @@ void MainFrame::init_menubar()
         append_menu_item(fileMenu, wxID_ANY, _(L("&Export Config Bundle…")), _(L("Export all presets to file")), 
                         [this](wxCommandEvent&) { export_configbundle(); }, "lorry_go.png");
         fileMenu->AppendSeparator();
-        wxMenuItem* repeat = nullptr;
-        append_menu_item(fileMenu, wxID_ANY, _(L("Q&uick Slice…\tCtrl+U")), _(L("Slice a file into a G-code")), 
-            [this, repeat](wxCommandEvent&) {
-                wxTheApp->CallAfter([this, repeat]() {
+        m_menu_item_repeat = nullptr;
+        append_menu_item(fileMenu, wxID_ANY, _(L("Q&uick Slice…\tCtrl+U")), _(L("Slice a file into a G-code")),
+            [this](wxCommandEvent&) {
+                wxTheApp->CallAfter([this]() {
                     quick_slice();
-                    repeat->Enable(is_last_input_file());
-            }); }, "cog_go.png");
-        append_menu_item(fileMenu, wxID_ANY, _(L("Quick Slice and Save &As…\tCtrl+Alt+U")), _(L("Slice a file into a G-code, save as")), 
-            [this, repeat](wxCommandEvent&) {
-                wxTheApp->CallAfter([this, repeat]() {
+                    m_menu_item_repeat->Enable(is_last_input_file());
+                }); }, "cog_go.png");
+        append_menu_item(fileMenu, wxID_ANY, _(L("Quick Slice and Save &As…\tCtrl+Alt+U")), _(L("Slice a file into a G-code, save as")),
+            [this](wxCommandEvent&) {
+            wxTheApp->CallAfter([this]() {
                     quick_slice(qsSaveAs);
-                    repeat->Enable(is_last_input_file());
-            }); }, "cog_go.png");
-        repeat = append_menu_item(fileMenu, wxID_ANY, _(L("&Repeat Last Quick Slice\tCtrl+Shift+U")), _(L("Repeat last quick slice")), 
+                    m_menu_item_repeat->Enable(is_last_input_file());
+                }); }, "cog_go.png");
+        m_menu_item_repeat = append_menu_item(fileMenu, wxID_ANY, _(L("&Repeat Last Quick Slice\tCtrl+Shift+U")), _(L("Repeat last quick slice")),
             [this](wxCommandEvent&) {
             wxTheApp->CallAfter([this]() {
                 quick_slice(qsReslice);
             }); }, "cog_go.png");
-        repeat->Enable(0);
+        m_menu_item_repeat->Enable(false);
         fileMenu->AppendSeparator();
         append_menu_item(fileMenu, wxID_ANY, _(L("Slice to SV&G…\tCtrl+G")), _(L("Slice file to a multi-layer SVG")),
             [this](wxCommandEvent&) { quick_slice(qsSaveAs | qsExportSVG); }, "shape_handles.png");
diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp
index e00216cbc..b6cd7916a 100644
--- a/src/slic3r/GUI/MainFrame.hpp
+++ b/src/slic3r/GUI/MainFrame.hpp
@@ -55,6 +55,7 @@ class MainFrame : public wxFrame
 
     std::map<std::string, Tab*>     m_options_tabs;
 
+    wxMenuItem* m_menu_item_repeat { nullptr };
     wxMenuItem* m_menu_item_reslice_now { nullptr };
     wxMenu*     m_plater_menu { nullptr };
     wxMenu*     m_viewMenu{ nullptr };

From ede21eec7afedef4b1f8c61230d7655c8e3cd0ac Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Thu, 15 Nov 2018 11:15:24 +0100
Subject: [PATCH 3/4] Rotation/Scale from modification pane for SingleObject,
 SingleVolume & SingleInstance

Note:
- doesn't work for group selection
- scaling work only with percent mode
---
 src/slic3r/GUI/GUI_ObjectManipulation.cpp | 75 +++++++++++++++++------
 src/slic3r/GUI/GUI_ObjectManipulation.hpp |  4 +-
 src/slic3r/GUI/Plater.cpp                 | 16 ++---
 3 files changed, 67 insertions(+), 28 deletions(-)

diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
index 73c004514..fb1fbbbe6 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
@@ -23,11 +23,12 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
     m_og->set_process_enter(); // We need to update new values only after press ENTER 
     
     m_og->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
+        std::vector<std::string> axes{ "_x", "_y", "_z" };
+
         if (opt_key == "scale_unit") {
             const wxString& selection = boost::any_cast<wxString>(value);
-            std::vector<std::string> axes{ "x", "y", "z" };
             for (auto axis : axes) {
-                std::string key = "scale_" + axis;
+                std::string key = "scale" + axis;
                 m_og->set_side_text(key, selection);
             }
 
@@ -39,13 +40,17 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
         std::string param; 
         std::copy(opt_key.begin(), opt_key.end() - 2, std::back_inserter(param));
 
-        if (param == "position") {
-            Vec3d displacement;
-            displacement(0) = boost::any_cast<double>(m_og->get_value("position_x"));
-            displacement(1) = boost::any_cast<double>(m_og->get_value("position_y"));
-            displacement(2) = boost::any_cast<double>(m_og->get_value("position_z"));
-            change_position_value(displacement);
-        }
+        size_t i = 0;
+        Vec3d new_value;
+        for (auto axis : axes)
+            new_value(i++) = boost::any_cast<double>(m_og->get_value(param+axis));
+
+        if (param == "position")
+            change_position_value(new_value);
+        else if (param == "rotation")
+            change_rotation_value(new_value);
+        else if (param == "scale")
+            change_scale_value(new_value);
     };
 
     ConfigOptionDef def;
@@ -132,7 +137,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
     m_og->append_line(add_og_to_object_settings(L("Rotation"), "°"));
     m_og->append_line(add_og_to_object_settings(L("Scale"), "mm"));
 
-
+    /* Unused parameter at this time
     def.label = L("Place on bed");
     def.type = coBool;
     def.tooltip = L("Automatic placing of models on printing bed in Y axis");
@@ -140,6 +145,7 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
     def.sidetext = "";
     def.default_value = new ConfigOptionBool{ false };
     m_og->append_single_option_line(Option(def, "place_on_bed"));
+    */
 }
 
 void ObjectManipulation::Show(const bool show)
@@ -241,6 +247,8 @@ void ObjectManipulation::update_settings_value(const GLCanvas3D::Selection& sele
     }
     else
         reset_settings_value();
+
+    m_og->get_field("scale_unit")->disable();// temporary decision 
 }
 
 void ObjectManipulation::reset_settings_value()
@@ -317,9 +325,9 @@ void ObjectManipulation::update_scale_values()
         m_og->set_value("scale_z", double_to_string(instance->get_scaling_factor(Z) * 100, 2));
     }
     else {
-        m_og->set_value("scale_x", double_to_string(instance->get_scaling_factor(X) * size(0) + 0.5, 2));
-        m_og->set_value("scale_y", double_to_string(instance->get_scaling_factor(Y) * size(1) + 0.5, 2));
-        m_og->set_value("scale_z", double_to_string(instance->get_scaling_factor(Z) * size(2) + 0.5, 2));
+        m_og->set_value("scale_x", double_to_string(size(0), 2));
+        m_og->set_value("scale_y", double_to_string(size(1), 2));
+        m_og->set_value("scale_z", double_to_string(size(2), 2));
     }
 }
 
@@ -347,8 +355,10 @@ void ObjectManipulation::update_scale_value(const Vec3d& scaling_factor)
     // to be able to update the values as size
     // we need to store somewhere the original size
     // or have it passed as parameter
-    if (!m_is_percent_scale)
+    if (!m_is_percent_scale) {
+        m_is_percent_scale = true;
         m_og->set_value("scale_unit", _("%"));
+    }
 
     auto scale = scaling_factor * 100.0;
     m_og->set_value("scale_x", double_to_string(scale(0), 2));
@@ -399,11 +409,40 @@ void ObjectManipulation::change_position_value(const Vec3d& position)
     cache_position = position;
 }
 
-
-
-void ObjectManipulation::print_cashe_value(const std::string& label, const Vec3d& value)
+void ObjectManipulation::change_rotation_value(const Vec3d& rotation)
 {
-    std::cout << label << " => " << " X:" << value(0) << " Y:" << value(1) << " Z:" << value(2) << std::endl;
+    Vec3d rad_rotation;
+    for (size_t i = 0; i < 3; ++i)
+        rad_rotation(i) = Geometry::deg2rad(rotation(i));
+    auto canvas = _3DScene::get_canvas(wxGetApp().canvas3D());
+    canvas->get_selection().start_dragging();
+    canvas->get_selection().rotate(rad_rotation);
+    canvas->_on_rotate();
+}
+
+void ObjectManipulation::change_scale_value(const Vec3d& scale)
+{
+    Vec3d scaling_factor;
+    if (m_is_percent_scale)
+        scaling_factor = scale*0.01;
+    else {
+        int selection = ol_selection();
+        ModelObjectPtrs& objects = *wxGetApp().model_objects();
+
+        auto size = objects[selection]->instance_bounding_box(0).size();
+        for (size_t i = 0; i < 3; ++i)
+            scaling_factor(i) = scale(i) / size(i);
+    }
+
+    auto canvas = _3DScene::get_canvas(wxGetApp().canvas3D());
+    canvas->get_selection().start_dragging();
+    canvas->get_selection().scale(scaling_factor);
+    canvas->_on_scale();
+}
+
+void ObjectManipulation::print_cashe_value(const std::string& label, const Vec3d& v)
+{
+    std::cout << label << " => " << " X:" << v(0) << " Y:" << v(1) << " Z:" << v(2) << std::endl;
 }
 
 } //namespace GUI
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.hpp b/src/slic3r/GUI/GUI_ObjectManipulation.hpp
index 2f016f46f..6ab76a83b 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.hpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.hpp
@@ -18,8 +18,6 @@ class ObjectManipulation : public OG_Settings
     bool        m_is_uniform_scale = false;         // It indicates if scale is uniform
 
     Vec3d       cache_position   { 0., 0., 0. };
-    Vec3d       cache_rotation   { 0., 0., 0. };
-    Vec3d       cache_scale      { 0., 0., 0. };
 
 public:
     ObjectManipulation(wxWindow* parent);
@@ -55,6 +53,8 @@ public:
 
     // change values 
     void    change_position_value(const Vec3d& position);
+    void    change_rotation_value(const Vec3d& rotation);
+    void    change_scale_value(const Vec3d& scale);
 
 
 private:
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index cd045d1a5..3840b248c 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -449,8 +449,7 @@ void Sidebar::priv::show_preset_comboboxes()
 {
     const bool showSLA = plater->printer_technology() == ptSLA;
 
-    wxWindowUpdateLocker noUpdates_scrolled(scrolled);
-//     scrolled->Freeze();
+    wxWindowUpdateLocker noUpdates_scrolled(scrolled->GetParent());
     
     for (size_t i = 0; i < 4; ++i) {
         if (sizer_presets->IsShown(i) == showSLA)
@@ -465,8 +464,8 @@ void Sidebar::priv::show_preset_comboboxes()
     if (frequently_changed_parameters->IsShown() == showSLA)
         frequently_changed_parameters->Show(!showSLA);
 
-    scrolled->Layout();
-//     scrolled->Thaw();
+    scrolled->GetParent()->Layout();
+    scrolled->Refresh();
 }
 
 
@@ -710,7 +709,7 @@ void Sidebar::show_info_sizer()
 
     const ModelInstance* model_instance = !model_object->instances.empty() ? model_object->instances.front() : nullptr;
 
-    auto size = model_object->instance_bounding_box(0).size();    
+    auto size = model_object->bounding_box().size();
     p->object_info->info_size->SetLabel(wxString::Format("%.2f x %.2f x %.2f",size(0), size(1), size(2)));
     p->object_info->info_materials->SetLabel(wxString::Format("%d", static_cast<int>(model_object->materials_count())));
 
@@ -776,6 +775,7 @@ void Sidebar::show_sliced_info_sizer(const bool show)
     }
 
     Layout();
+    p->scrolled->Refresh();
 }
 
 void Sidebar::show_buttons(const bool show)
@@ -2370,7 +2370,7 @@ void Plater::on_extruders_change(int num_extruders)
 {
     auto& choices = sidebar().combos_filament();
 
-    wxWindowUpdateLocker noUpdates_scrolled_panel(sidebar().scrolled_panel());
+    wxWindowUpdateLocker noUpdates_scrolled_panel(&sidebar()/*.scrolled_panel()*/);
 //     sidebar().scrolled_panel()->Freeze();
 
     int i = choices.size();
@@ -2388,8 +2388,8 @@ void Plater::on_extruders_change(int num_extruders)
     // remove unused choices if any
     sidebar().remove_unused_filament_combos(num_extruders);
 
-    sidebar().scrolled_panel()->Layout();
-//     sidebar().scrolled_panel()->Thaw();
+    sidebar().Layout();
+    sidebar().scrolled_panel()->Refresh();
 }
 
 void Plater::on_config_change(const DynamicPrintConfig &config)

From 410568c9d958dfd4d75a31da6614475439343ab8 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Thu, 15 Nov 2018 12:25:08 +0100
Subject: [PATCH 4/4] Temporary workaround for the correct behavior of the
 Scrolled sidebar panel

---
 src/slic3r/GUI/GUI_App.cpp        | 10 ++++++++++
 src/slic3r/GUI/GUI_ObjectList.cpp |  5 ++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 66ac7a979..c201d4018 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -115,6 +115,16 @@ bool GUI_App::OnInit()
     update_mode();
     SetTopWindow(mainframe);
 
+    CallAfter([this]() {
+        // temporary workaround for the correct behavior of the Scrolled sidebar panel 
+        auto& panel = sidebar();
+        if (panel.obj_list()->GetMinHeight() > 200) {
+            wxWindowUpdateLocker noUpdates_sidebar(&panel);
+            panel.obj_list()->SetMinSize(wxSize(-1, 200));
+            panel.Layout();
+        }
+    });
+
     // This makes CallAfter() work
     Bind(wxEVT_IDLE, [this](wxIdleEvent& event)
     {
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index a616307ba..01815cfd6 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -83,7 +83,10 @@ ObjectList::~ObjectList()
 
 void ObjectList::create_objects_ctrl()
 {
-    SetMinSize(wxSize(-1, 150)); // TODO - Set correct height according to the opened/closed objects
+    // temporary workaround for the correct behavior of the Scrolled sidebar panel:
+    // 1. set a height of the list to some big value 
+    // 2. change it to the normal min value (200) after first whole App updating/layouting
+    SetMinSize(wxSize(-1, 1500));   // #ys_FIXME 
 
     m_sizer = new wxBoxSizer(wxVERTICAL);
     m_sizer->Add(this, 1, wxGROW | wxLEFT, 20);