From 515502e685e8eeafd1c7b45ca44d09abdecfb689 Mon Sep 17 00:00:00 2001
From: YuSanka <yusanka@gmail.com>
Date: Mon, 25 Jun 2018 13:32:28 +0200
Subject: [PATCH 1/2] Fixed #994.

Print double-type values according to "full" value instead of 2 digits after point
---
 xs/src/slic3r/GUI/Field.cpp | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp
index 43c9e7db9..85247b41b 100644
--- a/xs/src/slic3r/GUI/Field.cpp
+++ b/xs/src/slic3r/GUI/Field.cpp
@@ -12,10 +12,20 @@ namespace Slic3r { namespace GUI {
 
 	wxString double_to_string(double const value)
 	{
-		int precision = 10 * value - int(10 * value) == 0 ? 1 : 2;
-		return value - int(value) == 0 ?
-			wxString::Format(_T("%i"), int(value)) :
-			wxNumberFormatter::ToString(value, precision, wxNumberFormatter::Style_None);
+		if (value - int(value) == 0)
+			return wxString::Format(_T("%i"), int(value));
+		else {
+			int precision = 4;
+			for (size_t p = 1; p < 4; p++)
+			{
+				double cur_val = pow(10, p)*value;
+				if (cur_val - int(cur_val) == 0) {
+					precision = p;
+					break;
+				}
+			}
+			return wxNumberFormatter::ToString(value, precision, wxNumberFormatter::Style_None);
+		}
 	}
 
 	void Field::PostInitialize(){

From 40b327eb116392b80835d28ef43778212a7a14a1 Mon Sep 17 00:00:00 2001
From: Enrico Turri <enricoturri@seznam.cz>
Date: Mon, 25 Jun 2018 15:17:13 +0200
Subject: [PATCH 2/2] Fix of interaction between opengl contexts and main page
 notebook

---
 lib/Slic3r/GUI/Plater.pm                | 20 +++++-----
 lib/Slic3r/GUI/Plater/2D.pm             |  6 ++-
 xs/src/slic3r/GUI/3DScene.cpp           | 10 +++++
 xs/src/slic3r/GUI/3DScene.hpp           |  3 ++
 xs/src/slic3r/GUI/GLCanvas3D.cpp        | 50 ++++++++++++++++++-------
 xs/src/slic3r/GUI/GLCanvas3D.hpp        |  2 +-
 xs/src/slic3r/GUI/GLCanvas3DManager.cpp | 29 ++++++++++++++
 xs/src/slic3r/GUI/GLCanvas3DManager.hpp |  2 +
 xs/xsp/GUI_3DScene.xsp                  |  5 +++
 9 files changed, 99 insertions(+), 28 deletions(-)

diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index f4ba05bdb..e6b2fca79 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -187,6 +187,7 @@ sub new {
     if ($Slic3r::GUI::have_OpenGL) {
         $self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{gcode_preview_data}, $self->{config});
         Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
+        Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 1);
         Slic3r::GUI::_3DScene::register_on_viewport_changed_callback($self->{preview3D}->canvas, sub { Slic3r::GUI::_3DScene::set_viewport_from_scene($self->{canvas3D}, $self->{preview3D}->canvas); });
         $self->{preview_notebook}->AddPage($self->{preview3D}, L('Preview'));
         $self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1;
@@ -200,19 +201,18 @@ sub new {
     
     EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub {
         my $preview = $self->{preview_notebook}->GetCurrentPage;
-        if ($preview == $self->{preview3D})
-        {
+        if (($preview != $self->{preview3D}) && ($preview != $self->{canvas3D})) {
+            Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
+            Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 0);
+            Slic3r::GUI::_3DScene::reset_current_canvas();
+            $preview->OnActivate if $preview->can('OnActivate');        
+        } elsif ($preview == $self->{preview3D}) {
             Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 1);
             Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 0);
-            Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 1);
-            $self->{preview3D}->load_print(1);
+            $self->{preview3D}->load_print;
             # sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably)
             Slic3r::GUI::_3DScene::set_as_dirty($self->{preview3D}->canvas);
-        } else {
-            Slic3r::GUI::_3DScene::enable_legend_texture($self->{preview3D}->canvas, 0);
-        }
-
-        if ($preview == $self->{canvas3D}) {
+        } elsif ($preview == $self->{canvas3D}) {
             Slic3r::GUI::_3DScene::set_active($self->{canvas3D}, 1);
             Slic3r::GUI::_3DScene::set_active($self->{preview3D}->canvas, 0);
             if (Slic3r::GUI::_3DScene::is_reload_delayed($self->{canvas3D})) {
@@ -222,8 +222,6 @@ sub new {
             }            
             # sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably)
             Slic3r::GUI::_3DScene::set_as_dirty($self->{canvas3D});
-        } else {
-            $preview->OnActivate if $preview->can('OnActivate');        
         }
     });
     
diff --git a/lib/Slic3r/GUI/Plater/2D.pm b/lib/Slic3r/GUI/Plater/2D.pm
index ad8f54ddb..83c2a5021 100644
--- a/lib/Slic3r/GUI/Plater/2D.pm
+++ b/lib/Slic3r/GUI/Plater/2D.pm
@@ -231,8 +231,10 @@ sub mouse_event {
         }
         $self->Refresh;
     } elsif ($event->LeftUp) {
-        $self->{on_instances_moved}->()
-            if $self->{drag_object};
+        if ($self->{drag_object}) {
+            $self->{on_instances_moved}->();
+            Slic3r::GUI::_3DScene::reset_current_canvas();            
+        }
         $self->{drag_start_pos} = undef;
         $self->{drag_object} = undef;
         $self->SetCursor(wxSTANDARD_CURSOR);
diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp
index feae9312e..a499825a4 100644
--- a/xs/src/slic3r/GUI/3DScene.cpp
+++ b/xs/src/slic3r/GUI/3DScene.cpp
@@ -1754,6 +1754,16 @@ bool _3DScene::init(wxGLCanvas* canvas)
     return s_canvas_mgr.init(canvas);
 }
 
+bool _3DScene::set_current(wxGLCanvas* canvas, bool force)
+{
+    return s_canvas_mgr.set_current(canvas, force);
+}
+
+void _3DScene::reset_current_canvas()
+{
+    s_canvas_mgr.set_current(nullptr, false);
+}
+
 void _3DScene::set_active(wxGLCanvas* canvas, bool active)
 {
     s_canvas_mgr.set_active(canvas, active);
diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp
index c317dba24..f45bab276 100644
--- a/xs/src/slic3r/GUI/3DScene.hpp
+++ b/xs/src/slic3r/GUI/3DScene.hpp
@@ -516,6 +516,9 @@ public:
 
     static bool init(wxGLCanvas* canvas);
 
+    static bool set_current(wxGLCanvas* canvas, bool force);
+    static void reset_current_canvas();
+
     static void set_active(wxGLCanvas* canvas, bool active);
     static void set_as_dirty(wxGLCanvas* canvas);
 
diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp
index 6f23af5a3..f5db97731 100644
--- a/xs/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1520,13 +1520,10 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl)
     return true;
 }
 
-bool GLCanvas3D::set_current()
+bool GLCanvas3D::set_current(bool force)
 {
-    if ((m_canvas != nullptr) && (m_context != nullptr))
-    {
-        m_canvas->SetCurrent(*m_context);
-        return true;
-    }
+    if ((force || m_active) && (m_canvas != nullptr) && (m_context != nullptr))
+        return m_canvas->SetCurrent(*m_context);
 
     return false;
 }
@@ -1548,8 +1545,13 @@ unsigned int GLCanvas3D::get_volumes_count() const
 
 void GLCanvas3D::reset_volumes()
 {
-    if (set_current())
+
+    if (!m_volumes.empty())
     {
+        // ensures this canvas is current
+        if ((m_canvas == nullptr) || !_3DScene::set_current(m_canvas, true))
+            return;
+
         m_volumes.release_geometry();
         m_volumes.clear();
         m_dirty = true;
@@ -1847,8 +1849,8 @@ void GLCanvas3D::render()
     if (!_is_shown_on_screen())
         return;
 
-    // ensures that the proper context is selected and that this canvas is initialized
-    if (!set_current() || !_3DScene::init(m_canvas))
+    // ensures this canvas is current and initialized
+    if (!_3DScene::set_current(m_canvas, false) || !_3DScene::init(m_canvas))
         return;
 
     if (m_force_zoom_to_bed_enabled)
@@ -1929,6 +1931,11 @@ void GLCanvas3D::reload_scene(bool force)
         return;
 
     reset_volumes();
+
+    // ensures this canvas is current
+    if (!_3DScene::set_current(m_canvas, true))
+        return;
+
     set_bed_shape(dynamic_cast<const ConfigOptionPoints*>(m_config->option("bed_shape"))->values);
 
     if (!m_canvas->IsShown() && !force)
@@ -2000,6 +2007,10 @@ void GLCanvas3D::reload_scene(bool force)
 
 void GLCanvas3D::load_print_toolpaths()
 {
+    // ensures this canvas is current
+    if (!_3DScene::set_current(m_canvas, true))
+        return;
+
     if (m_print == nullptr)
         return;
 
@@ -2364,8 +2375,8 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
 {
     if ((m_canvas != nullptr) && (m_print != nullptr))
     {
-        // ensures that the proper context is selected
-        if (!set_current())
+        // ensures that this canvas is current
+        if (!_3DScene::set_current(m_canvas, false))
             return;
 
         if (m_volumes.empty())
@@ -2682,7 +2693,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
 #endif
     } 
     else if (evt.LeftDClick() && (m_hover_volume_id != -1))
+    {
+        m_active = false;
         m_on_double_click_callback.call();
+        m_active = true;
+    }
     else if (evt.LeftDown() || evt.RightDown())
     {
         // If user pressed left or right button we first check whether this happened
@@ -2778,7 +2793,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
                 {
                     // if right clicking on volume, propagate event through callback
                     if (m_volumes.volumes[volume_idx]->hover)
+                    {
+                        m_active = false;
                         m_on_right_click_callback.call(pos.x, pos.y);
+                        m_active = true;
+                    }
                 }
             }
         }
@@ -2996,10 +3015,11 @@ void GLCanvas3D::_force_zoom_to_bed()
 
 void GLCanvas3D::_resize(unsigned int w, unsigned int h)
 {
-    if (m_context == nullptr)
+    if ((m_canvas == nullptr) && (m_context == nullptr))
         return;
 
-    set_current();
+    // ensures that this canvas is current
+    _3DScene::set_current(m_canvas, false);
     ::glViewport(0, 0, w, h);
 
     ::glMatrixMode(GL_PROJECTION);
@@ -3585,9 +3605,11 @@ void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt)
 
 Pointf3 GLCanvas3D::_mouse_to_3d(const Point& mouse_pos, float* z)
 {
-    if (!set_current())
+    if (m_canvas == nullptr)
         return Pointf3(DBL_MAX, DBL_MAX, DBL_MAX);
 
+    _camera_tranform();
+
     GLint viewport[4];
     ::glGetIntegerv(GL_VIEWPORT, viewport);
     GLdouble modelview_matrix[16];
diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp
index 18011f497..237044e83 100644
--- a/xs/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp
@@ -449,7 +449,7 @@ public:
 
     bool init(bool useVBOs, bool use_legacy_opengl);
 
-    bool set_current();
+    bool set_current(bool force);
 
     void set_active(bool active);
     void set_as_dirty();
diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp
index 81efe4408..62d17827a 100644
--- a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp
+++ b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp
@@ -115,6 +115,7 @@ std::string GLCanvas3DManager::GLInfo::to_string(bool format_as_html, bool exten
 
 GLCanvas3DManager::GLCanvas3DManager()
     : m_context(nullptr)
+    , m_current(nullptr)
     , m_gl_initialized(false)
     , m_use_legacy_opengl(false)
     , m_use_VBOs(false)
@@ -212,6 +213,34 @@ bool GLCanvas3DManager::init(wxGLCanvas* canvas)
         return false;
 }
 
+bool GLCanvas3DManager::set_current(wxGLCanvas* canvas, bool force)
+{
+    // given canvas is already current, return
+    if (m_current == canvas)
+        return true;
+
+    if (canvas == nullptr)
+    {
+        m_current = nullptr;
+        return true;
+    }
+
+    // set given canvas as current
+    CanvasesMap::iterator it = _get_canvas(canvas);
+    if (it != m_canvases.end())
+    {
+        bool res = it->second->set_current(force);
+        if (res)
+        {
+            m_current = canvas;
+            return true;
+        }
+    }
+
+    m_current = nullptr;
+    return false;
+}
+
 void GLCanvas3DManager::set_active(wxGLCanvas* canvas, bool active)
 {
     CanvasesMap::iterator it = _get_canvas(canvas);
diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp
index 8726eb0b1..35a1db206 100644
--- a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp
+++ b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp
@@ -45,6 +45,7 @@ class GLCanvas3DManager
 
     wxGLContext* m_context;
     CanvasesMap m_canvases;
+    wxGLCanvas* m_current;
     GLInfo m_gl_info;
     bool m_gl_initialized;
     bool m_use_legacy_opengl;
@@ -69,6 +70,7 @@ public:
 
     bool init(wxGLCanvas* canvas);
 
+    bool set_current(wxGLCanvas* canvas, bool force);
     void set_active(wxGLCanvas* canvas, bool active);
     void set_as_dirty(wxGLCanvas* canvas);
 
diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp
index d46c06120..8ee88543d 100644
--- a/xs/xsp/GUI_3DScene.xsp
+++ b/xs/xsp/GUI_3DScene.xsp
@@ -190,6 +190,11 @@ remove_all_canvases()
     CODE:
         _3DScene::remove_all_canvases();
 
+void
+reset_current_canvas()
+    CODE:
+        _3DScene::reset_current_canvas();
+
 void
 set_active(canvas, active)
         SV   *canvas;