diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 47ccb2269..9d8974afe 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 8b1ed3f7a..fdb8e788f 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/Field.cpp b/xs/src/slic3r/GUI/Field.cpp index 57420a411..36a1c396f 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(){ 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(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;