From 5b01eb30047e3a67896ee02bd7dd6fc606a8dc40 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 15 Mar 2019 09:13:15 +0100 Subject: [PATCH 01/23] 2nd fix for x position of gizmos' imgui dialogs --- src/slic3r/GUI/GLCanvas3D.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 8178c9cf6..33f460802 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3039,6 +3039,7 @@ void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCan float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; float height = get_total_overlay_height(); + float width = get_total_overlay_width(); #if ENABLE_SVG_ICONS float scaled_border = m_overlay_border * m_overlay_scale * inv_zoom; #else @@ -3050,7 +3051,7 @@ void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCan float left = top_x; float top = top_y; - float right = left + get_total_overlay_width() * inv_zoom; + float right = left + width * inv_zoom; float bottom = top - height * inv_zoom; // renders background @@ -3158,24 +3159,24 @@ void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCan #if ENABLE_SVG_ICONS float u_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_width; float v_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_height; - float top = sprite_id * v_icon_size; - float left = state * u_icon_size; - float bottom = top + v_icon_size; - float right = left + u_icon_size; + float v_top = sprite_id * v_icon_size; + float u_left = state * u_icon_size; + float v_bottom = v_top + v_icon_size; + float u_right = u_left + u_icon_size; #else float uv_icon_size = (float)m_icons_texture.metadata.icon_size * inv_texture_size; - float top = sprite_id * uv_icon_size; - float left = state * uv_icon_size; - float bottom = top + uv_icon_size; - float right = left + uv_icon_size; + float v_top = sprite_id * uv_icon_size; + float u_left = state * uv_icon_size; + float v_bottom = v_top + uv_icon_size; + float u_right = u_left + uv_icon_size; #endif // ENABLE_SVG_ICONS - GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { left, bottom }, { right, bottom }, { right, top }, { left, top } }); + GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } }); #if ENABLE_IMGUI if (it->second->get_state() == GLGizmoBase::On) { float toolbar_top = (float)cnv_h - canvas.m_view_toolbar.get_height(); #if ENABLE_SVG_ICONS - it->second->render_input_window(2.0f * m_overlay_border + m_overlay_icons_size, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection); + it->second->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection); #else it->second->render_input_window(2.0f * m_overlay_border + icon_size * zoom, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection); #endif // ENABLE_SVG_ICONS From dd309c9dfc69af15344a8607cdb93e5e927dfe1c Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 15 Mar 2019 10:05:14 +0100 Subject: [PATCH 02/23] GLGizmoBase::picking_color_component modified to return all the three components of the picking color --- src/slic3r/GUI/GLGizmo.cpp | 34 ++++++++++++++++++++++------------ src/slic3r/GUI/GLGizmo.hpp | 2 +- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index a87cb68fb..e8e48b63c 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -244,13 +244,21 @@ void GLGizmoBase::update(const UpdateData& data, const GLCanvas3D::Selection& se on_update(data, selection); } -float GLGizmoBase::picking_color_component(unsigned int id) const +std::array GLGizmoBase::picking_color_component(unsigned int id) const { - int color = 254 - (int)id; - if (m_group_id > -1) - color -= m_group_id; + // Starting value for id to avoid clashing with id used by GLVolumes + static const unsigned int BASE = 254 * 255 * 255; + static const float INV_255 = 1.0f / 255.0f; - return (float)color / 255.0f; + id = BASE - id; + + std::array color; + + color[0] = (float)((id >> 16) & 0xff) * INV_255; // red + color[1] = (float)((id >> 8) & 0xff) * INV_255; // green + color[2] = (float)(id & 0xff) * INV_255; // blue + + return color; } void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const @@ -281,9 +289,10 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const { if (m_grabbers[i].enabled) { - m_grabbers[i].color[0] = 1.0f; - m_grabbers[i].color[1] = 1.0f; - m_grabbers[i].color[2] = picking_color_component(i); + std::array color = picking_color_component(i); + m_grabbers[i].color[0] = color[0]; + m_grabbers[i].color[1] = color[1]; + m_grabbers[i].color[2] = color[2]; m_grabbers[i].render_for_picking(size); } } @@ -1478,7 +1487,7 @@ void GLGizmoFlatten::on_render_for_picking(const GLCanvas3D::Selection& selectio const_cast(this)->update_planes(); for (int i = 0; i < (int)m_planes.size(); ++i) { - ::glColor3f(1.0f, 1.0f, picking_color_component(i)); + ::glColor3fv(picking_color_component(i).data()); ::glBegin(GL_POLYGON); for (const Vec3d& vertex : m_planes[i].vertices) { @@ -1878,9 +1887,10 @@ void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, b // First decide about the color of the point. if (picking) { - render_color[0] = 1.0f; - render_color[1] = 1.0f; - render_color[2] = picking_color_component(i); + std::array color = picking_color_component(i); + render_color[0] = color[0]; + render_color[1] = color[1]; + render_color[2] = color[2]; } else { if ((m_hover_id == i && m_editing_mode)) { // ignore hover state unless editing mode is active diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index a872a161e..83a062a2c 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -175,7 +175,7 @@ protected: virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) {} #endif // ENABLE_IMGUI - float picking_color_component(unsigned int id) const; + std::array picking_color_component(unsigned int id) const; void render_grabbers(const BoundingBoxf3& box) const; void render_grabbers(float size) const; void render_grabbers_for_picking(const BoundingBoxf3& box) const; From 32c9e8b168277e0d916c2f1eb1b69d1dc0c34139 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 15 Mar 2019 10:15:23 +0100 Subject: [PATCH 03/23] A small fix of the gizmo grabbers picking --- src/slic3r/GUI/GLGizmo.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index e8e48b63c..359deed3a 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -252,13 +252,12 @@ std::array GLGizmoBase::picking_color_component(unsigned int id) const id = BASE - id; - std::array color; + if (m_group_id > -1) + id -= m_group_id; - color[0] = (float)((id >> 16) & 0xff) * INV_255; // red - color[1] = (float)((id >> 8) & 0xff) * INV_255; // green - color[2] = (float)(id & 0xff) * INV_255; // blue - - return color; + return std::array { (float)((id >> 16) & 0xff) * INV_255, // red + (float)((id >> 8) & 0xff) * INV_255, // green + (float)(id & 0xff) * INV_255}; // blue } void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const From ef939905b198460dc1e8c8ab0661dbf2518ff4c4 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 15 Mar 2019 11:04:08 +0100 Subject: [PATCH 04/23] Another fix of the gizmo grabber color picking --- src/slic3r/GUI/GLCanvas3D.cpp | 3 +-- src/slic3r/GUI/GLGizmo.cpp | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 33f460802..3100a024b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6286,7 +6286,6 @@ void GLCanvas3D::_picking_pass() const ::glReadPixels(pos(0), cnv_size.get_height() - pos(1) - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color); volume_id = color[0] + color[1] * 256 + color[2] * 256 * 256; } - if ((0 <= volume_id) && (volume_id < (int)m_volumes.volumes.size())) { m_hover_volume_id = volume_id; @@ -6295,7 +6294,7 @@ void GLCanvas3D::_picking_pass() const else { m_hover_volume_id = -1; - m_gizmos.set_hover_id(inside ? (254 - (int)color[2]) : -1); + m_gizmos.set_hover_id(inside && volume_id <= 254 * 255 * 255 ? (254 * 255 * 255 - volume_id) : -1); } _update_volumes_hover_state(); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 359deed3a..19d50e2e0 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -255,9 +255,9 @@ std::array GLGizmoBase::picking_color_component(unsigned int id) const if (m_group_id > -1) id -= m_group_id; - return std::array { (float)((id >> 16) & 0xff) * INV_255, // red + return std::array { (float)((id >> 0) & 0xff) * INV_255, // red (float)((id >> 8) & 0xff) * INV_255, // green - (float)(id & 0xff) * INV_255}; // blue + (float)((id >> 16)& 0xff) * INV_255}; // blue } void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const From bc3036d777fb6ca7c937c28d8aa9b9131a376c20 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Fri, 15 Mar 2019 12:07:25 +0100 Subject: [PATCH 05/23] Follow-up to previous commits on gizmo grabbers picking (use of centralized static constant for ids and added comments) --- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- src/slic3r/GUI/GLGizmo.cpp | 7 +++---- src/slic3r/GUI/GLGizmo.hpp | 7 +++++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 3100a024b..dac370b54 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6294,7 +6294,7 @@ void GLCanvas3D::_picking_pass() const else { m_hover_volume_id = -1; - m_gizmos.set_hover_id(inside && volume_id <= 254 * 255 * 255 ? (254 * 255 * 255 - volume_id) : -1); + m_gizmos.set_hover_id(inside && volume_id <= GLGizmoBase::BASE_ID ? (GLGizmoBase::BASE_ID - volume_id) : -1); } _update_volumes_hover_state(); diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 19d50e2e0..6ab2f46ab 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -246,18 +246,17 @@ void GLGizmoBase::update(const UpdateData& data, const GLCanvas3D::Selection& se std::array GLGizmoBase::picking_color_component(unsigned int id) const { - // Starting value for id to avoid clashing with id used by GLVolumes - static const unsigned int BASE = 254 * 255 * 255; static const float INV_255 = 1.0f / 255.0f; - id = BASE - id; + id = BASE_ID - id; if (m_group_id > -1) id -= m_group_id; + // color components are encoded to match the calculation of volume_id made into GLCanvas3D::_picking_pass() return std::array { (float)((id >> 0) & 0xff) * INV_255, // red (float)((id >> 8) & 0xff) * INV_255, // green - (float)((id >> 16)& 0xff) * INV_255}; // blue + (float)((id >> 16) & 0xff) * INV_255 }; // blue } void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp index 83a062a2c..4e44da540 100644 --- a/src/slic3r/GUI/GLGizmo.hpp +++ b/src/slic3r/GUI/GLGizmo.hpp @@ -35,6 +35,11 @@ class ImGuiWrapper; class GLGizmoBase { +public: + // Starting value for ids to avoid clashing with ids used by GLVolumes + // (254 is choosen to leave some space for forward compatibility) + static const unsigned int BASE_ID = 255 * 255 * 254; + protected: struct Grabber { @@ -175,6 +180,8 @@ protected: virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) {} #endif // ENABLE_IMGUI + // Returns the picking color for the given id, based on the BASE_ID constant + // No check is made for clashing with other picking color (i.e. GLVolumes) std::array picking_color_component(unsigned int id) const; void render_grabbers(const BoundingBoxf3& box) const; void render_grabbers(float size) const; From 6548a6d525108ae1c694239ba0bbce83eb97cc19 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Fri, 15 Mar 2019 14:21:32 +0100 Subject: [PATCH 06/23] Fixed preset selection after ConfigWizard running --- src/slic3r/GUI/GUI.cpp | 3 --- src/slic3r/GUI/Preset.cpp | 4 +++- src/slic3r/GUI/Tab.cpp | 24 +++++++++++++++++++++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 11e94f2ca..4a3ccc356 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -148,9 +148,6 @@ void config_wizard(int reason) _(L("Please check and fix your object list.")), _(L("Attention!"))); } - - // Load the currently selected preset into the GUI, update the preset selection box. - // wxGetApp().load_current_presets(); // #ys_FIXME_to_delete presets are loaded now in select_preset function } // opt_index = 0, by the reason of zero-index in ConfigOptionVector by default (in case only one element) diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 86fdde44b..bb70b8f47 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -952,7 +952,9 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) ui->SetToolTip(ui->GetString(selected_preset_item)); ui->Thaw(); - ui->selected_preset_name = this->get_selected_preset().name; + // For printer preset it's important to update preset list every time because of ConfigWizard + // So, don't save selected preset name + ui->selected_preset_name = type()==Preset::TYPE_PRINTER ? "" : this->get_selected_preset().name; } size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index ae33443c3..b23becaae 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2594,7 +2594,7 @@ void Tab::select_preset(std::string preset_name) } else { if (current_dirty) m_presets->discard_current_changes(); - m_presets->select_preset_by_name(preset_name, false); + const bool is_selected = m_presets->select_preset_by_name(preset_name, false); // Mark the print & filament enabled if they are compatible with the currently selected preset. // The following method should not discard changes of current print or filament presets on change of a printer profile, // if they are compatible with the current printer. @@ -2603,6 +2603,28 @@ void Tab::select_preset(std::string preset_name) // Initialize the UI from the current preset. if (printer_tab) static_cast(this)->update_pages(); + + if (!is_selected && printer_tab) + { + /* There is a case, when : + * after Config Wizard applying we try to select previously selected preset, but + * in a current configuration this one: + * 1. doesn't exist now, + * 2. have another printer_technology + * So, it is necessary to update list of dependent tabs + * to the corresponding printer_technology + */ + const PrinterTechnology printer_technology = m_presets->get_edited_preset().printer_technology(); + if (printer_technology == ptFFF && m_dependent_tabs.front() != Preset::Type::TYPE_PRINT || + printer_technology == ptSLA && m_dependent_tabs.front() != Preset::Type::TYPE_SLA_PRINT ) + { + m_dependent_tabs.clear(); + if (printer_technology == ptFFF) + m_dependent_tabs = { Preset::Type::TYPE_PRINT, Preset::Type::TYPE_FILAMENT }; + else + m_dependent_tabs = { Preset::Type::TYPE_SLA_PRINT, Preset::Type::TYPE_SLA_MATERIAL }; + } + } load_current_preset(); } } From fdf59f756c5767d536f17fa7c6799687a6345220 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 15 Mar 2019 15:30:20 +0100 Subject: [PATCH 07/23] Fixing memory corruption from invalidated references --- src/libslic3r/SLA/SLASupportTree.cpp | 63 +++++++++++++++------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index 9f2575036..437f07fcb 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -716,7 +716,7 @@ public: assert(it != m_heads.end()); const Head& h = it->second; assert(h.pillar_id >= 0 && h.pillar_id < long(m_pillars.size())); - return m_pillars[size_t(h.pillar_id)]; + return pillar(h.pillar_id); } template const Junction& add_junction(Args&&... args) { @@ -755,6 +755,10 @@ public: return m_compact_bridges; } + template inline + typename std::enable_if::value, const Pillar&>::type + pillar(T id) const { assert(id >= 0); return m_pillars.at(size_t(id)); } + const Pad& create_pad(const TriangleMesh& object_supports, const ExPolygons& baseplate, const PoolConfig& cfg) { @@ -1242,12 +1246,14 @@ class SLASupportTree::Algorithm { } // For connecting a head to a nearby pillar. - bool connect_to_nearpillar(const Head& head, const Pillar& nearpillar) { - if(nearpillar.bridges > m_cfg.max_bridges_on_pillar) return false; + bool connect_to_nearpillar(const Head& head, long nearpillar_id) { + + auto nearpillar = [this, nearpillar_id]() { return m_result.pillar(nearpillar_id); }; + if(nearpillar().bridges > m_cfg.max_bridges_on_pillar) return false; Vec3d headjp = head.junction_point(); - Vec3d nearjp_u = nearpillar.startpoint(); - Vec3d nearjp_l = nearpillar.endpoint(); + Vec3d nearjp_u = nearpillar().startpoint(); + Vec3d nearjp_l = nearpillar().endpoint(); double r = head.r_back_mm; double d2d = distance(to_2d(headjp), to_2d(nearjp_u)); @@ -1308,7 +1314,7 @@ class SLASupportTree::Algorithm { } m_result.add_bridge(bridgestart, bridgeend, r); - m_result.increment_bridges(nearpillar); + m_result.increment_bridges(nearpillar()); return true; } @@ -1336,8 +1342,7 @@ class SLASupportTree::Algorithm { if(nearest_id >= 0) { auto nearpillarID = unsigned(nearest_id); if(nearpillarID < m_result.pillars().size()) { - const Pillar& nearpillar = m_result.pillars()[nearpillarID]; - if(!connect_to_nearpillar(head, nearpillar)) { + if(!connect_to_nearpillar(head, nearpillarID)) { nearest_id = -1; // continue searching spindex.remove(ne); // without the current pillar } @@ -1649,7 +1654,7 @@ public: // central position where the pillar can be placed. this way // the weight is distributed more effectively on the pillar. - const Pillar& centerpillar = m_result.head_pillar(cidx); + auto centerpillarID = m_result.head_pillar(cidx).id; for(auto c : cl) { m_thr(); if(c == cidx) continue; @@ -1657,7 +1662,7 @@ public: auto& sidehead = m_result.head(c); sidehead.transform(); - if(!connect_to_nearpillar(sidehead, centerpillar) && + if(!connect_to_nearpillar(sidehead, centerpillarID) && !search_pillar_and_connect(sidehead)) { Vec3d pstart = sidehead.junction_point(); @@ -1859,7 +1864,7 @@ public: } for(auto pillid : modelpillars) { - auto& pillar = m_result.pillars()[pillid]; + auto& pillar = m_result.pillar(pillid); m_pillar_index.insert(pillar.endpoint(), pillid); } } @@ -1886,7 +1891,7 @@ public: { Vec3d qp = el.first; - const Pillar& pillar = m_result.pillars()[el.second]; + const Pillar& pillar = m_result.pillar(el.second); unsigned neighbors = m_cfg.pillar_cascade_neighbors; @@ -1946,15 +1951,15 @@ public: size_t pillarcount = m_result.pillars().size(); for(size_t pid = 0; pid < pillarcount; pid++) { - const Pillar& pillar = m_result.pillars()[pid]; + auto pillar = [this, pid]() { return m_result.pillar(pid); }; unsigned needpillars = 0; - if(pillar.bridges > m_cfg.max_bridges_on_pillar) needpillars = 3; - else if(pillar.links < 2 && pillar.height > H2) { + if(pillar().bridges > m_cfg.max_bridges_on_pillar) needpillars = 3; + else if(pillar().links < 2 && pillar().height > H2) { // Not enough neighbors to support this pillar - needpillars = 2 - pillar.links; + needpillars = 2 - pillar().links; } - else if(pillar.links < 1 && pillar.height > H1) { + else if(pillar().links < 1 && pillar().height > H1) { // No neighbors could be found and the pillar is too long. needpillars = 1; } @@ -1963,7 +1968,7 @@ public: bool found = false; double alpha = 0; // goes to 2Pi double r = 2 * m_cfg.base_radius_mm; - Vec3d pillarsp = pillar.startpoint(); + Vec3d pillarsp = pillar().startpoint(); Vec3d sp(pillarsp(X), pillarsp(Y), pillarsp(Z) - r); std::vector tv(needpillars, false); std::vector spts(needpillars); @@ -1976,7 +1981,7 @@ public: s(X) += std::cos(a) * r; s(Y) += std::sin(a) * r; spts[n] = s; - auto hr = bridge_mesh_intersect(s, {0, 0, -1}, pillar.r); + auto hr = bridge_mesh_intersect(s, {0, 0, -1}, pillar().r); tv[n] = std::isinf(hr.distance()); } @@ -1991,33 +1996,33 @@ public: if(found) for(unsigned n = 0; n < needpillars; n++) { Vec3d s = spts[n]; double gnd = m_result.ground_level; - Pillar p(s, Vec3d(s(X), s(Y), gnd), pillar.r); + Pillar p(s, Vec3d(s(X), s(Y), gnd), pillar().r); p.add_base(m_cfg.base_height_mm, m_cfg.base_radius_mm); - if(interconnect(pillar, p)) { + if(interconnect(pillar(), p)) { Pillar& pp = m_result.add_pillar(p); m_pillar_index.insert(pp.endpoint(), unsigned(pp.id)); - m_result.add_junction(s, pillar.r); + m_result.add_junction(s, pillar().r); double t = bridge_mesh_intersect(pillarsp, dirv(pillarsp, s), - pillar.r); + pillar().r); if(distance(pillarsp, s) < t) - m_result.add_bridge(pillarsp, s, pillar.r); + m_result.add_bridge(pillarsp, s, pillar().r); - if(pillar.endpoint()(Z) > m_result.ground_level) - m_result.add_junction(pillar.endpoint(), pillar.r); + if(pillar().endpoint()(Z) > m_result.ground_level) + m_result.add_junction(pillar().endpoint(), pillar().r); newpills.emplace_back(pp.id); - m_result.increment_links(pillar); + m_result.increment_links(pillar()); } } if(!newpills.empty()) { for(auto it = newpills.begin(), nx = std::next(it); nx != newpills.end(); ++it, ++nx) { - const Pillar& itpll = m_result.pillars()[size_t(*it)]; - const Pillar& nxpll = m_result.pillars()[size_t(*nx)]; + const Pillar& itpll = m_result.pillar(*it); + const Pillar& nxpll = m_result.pillar(*nx); if(interconnect(itpll, nxpll)) { m_result.increment_links(itpll); m_result.increment_links(nxpll); From 5f81328aa4967e140c817295d475fccf07ccfca7 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 15 Mar 2019 18:40:49 +0100 Subject: [PATCH 08/23] Fixed a case when the SLA gizmo did not calculate igl mesh and aabb tree even though it should --- src/slic3r/GUI/GLGizmo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp index 6ab2f46ab..34d0c746a 100644 --- a/src/slic3r/GUI/GLGizmo.cpp +++ b/src/slic3r/GUI/GLGizmo.cpp @@ -1954,7 +1954,8 @@ void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, b bool GLGizmoSlaSupports::is_mesh_update_necessary() const { - return (m_state == On) && (m_model_object != m_old_model_object) && (m_model_object != nullptr) && !m_model_object->instances.empty(); + return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty()) + && ((m_model_object != m_old_model_object) || m_V.size()==0); //if (m_state != On || !m_model_object || m_model_object->instances.empty() || ! m_instance_matrix.isApprox(m_source_data.matrix)) // return false; From 954d571ab0a713d3df5fdcf97a9a9cc0e06fa471 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 16 Mar 2019 17:12:51 +0100 Subject: [PATCH 09/23] Bumped up version number to 1.42.0-beta changed the config path from Slic3rPE-alpha to Slic3rPE-beta --- src/slic3r/GUI/GUI_App.cpp | 2 +- version.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 7d448fbe4..1cf2ca17c 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -95,7 +95,7 @@ bool GUI_App::OnInit() wxCHECK_MSG(m_imgui->init(), false, "Failed to initialize ImGui"); #endif // ENABLE_IMGUI - SetAppName("Slic3rPE-alpha"); + SetAppName("Slic3rPE-beta"); SetAppDisplayName("Slic3r Prusa Edition"); // Slic3r::debugf "wxWidgets version %s, Wx version %s\n", wxVERSION_STRING, wxVERSION; diff --git a/version.inc b/version.inc index 0e84a48a2..18ac508b2 100644 --- a/version.inc +++ b/version.inc @@ -2,7 +2,7 @@ # (the version numbers are generated by the build script from the git current label) set(SLIC3R_FORK_NAME "Slic3r Prusa Edition") -set(SLIC3R_VERSION "1.42.0-alpha7") +set(SLIC3R_VERSION "1.42.0-beta") set(SLIC3R_BUILD "${SLIC3R_VERSION}+UNKNOWN") set(SLIC3R_BUILD_ID "${SLIC3R_BUILD_ID}") set(SLIC3R_RC_VERSION "1,42,0,0") From e3153fc8fe4657ea978b8cd5daa481b0a745bc50 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sat, 16 Mar 2019 19:13:30 +0100 Subject: [PATCH 10/23] Updated Prusa3D print profiles --- resources/profiles/PrusaResearch.idx | 15 +- resources/profiles/PrusaResearch.ini | 501 +++++++++++++++++++++------ 2 files changed, 414 insertions(+), 102 deletions(-) diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx index 407883544..a6f9deb28 100644 --- a/resources/profiles/PrusaResearch.idx +++ b/resources/profiles/PrusaResearch.idx @@ -1,14 +1,22 @@ min_slic3r_version = 1.42.0-alpha6 -0.8.0-alpha7 -0.8.0-alpha6 +0.8.0-beta Updated SLA profiles +0.8.0-alpha9 Updated SLA and FFF profiles +0.8.0-alpha8 Updated SLA profiles +0.8.0-alpha7 Updated SLA profiles +0.8.0-alpha6 Updated SLA profiles min_slic3r_version = 1.42.0-alpha -0.8.0-alpha +0.8.0-alpha Updated SLA profiles 0.4.0-alpha4 Updated SLA profiles 0.4.0-alpha3 Update of SLA profiles 0.4.0-alpha2 First SLA profiles min_slic3r_version = 1.41.3-alpha +0.4.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt +0.4.3 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt +0.4.2 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt +0.4.1 New MK2.5S and MK3S FW versions 0.4.0 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt min_slic3r_version = 1.41.1 +0.3.5 New MK2.5 and MK3 FW versions 0.3.4 Changelog: https://github.com/prusa3d/Slic3r-settings/blob/master/live/PrusaResearch/changelog.txt 0.3.3 Prusament PETG released 0.3.2 New MK2.5 and MK3 FW versions @@ -41,6 +49,7 @@ min_slic3r_version = 1.41.0-alpha 0.2.0-alpha1 added initial profiles for the i3 MK3 Multi Material Upgrade 2.0 0.2.0-alpha moved machine limits from the start G-code to the new print profile parameters min_slic3r_version = 1.40.0 +0.1.13 New MK2.5 and MK3 FW versions 0.1.12 New MK2.5 and MK3 FW versions 0.1.11 fw version changed to 3.3.1 0.1.10 MK3 jerk and acceleration update diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index a471700fb..35916377b 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -5,7 +5,7 @@ name = Prusa Research # Configuration version of this file. Config file will only be installed, if the config_version differs. # This means, the server may force the Slic3r configuration to be downgraded. -config_version = 0.8.0-alpha7 +config_version = 0.8.0-beta # Where to get the updates from? config_update_url = https://raw.githubusercontent.com/prusa3d/Slic3r-settings/master/live/PrusaResearch/ @@ -190,6 +190,14 @@ travel_speed = 180 wipe_tower_x = 170 wipe_tower_y = 125 +[print:*MK306*] +fill_pattern = gyroid +fill_density = 15% +single_extruder_multi_material_priming = 0 +travel_speed = 180 +wipe_tower_x = 170 +wipe_tower_y = 125 + # Print parameters common to a 0.25mm diameter nozzle. [print:*0.25nozzle*] external_perimeter_extrusion_width = 0.25 @@ -205,6 +213,38 @@ support_material_interface_spacing = 0.15 support_material_spacing = 1 support_material_xy_spacing = 150% +[print:*0.25nozzleMK3*] +external_perimeter_extrusion_width = 0.25 +extrusion_width = 0.25 +first_layer_extrusion_width = 0.35 +infill_extrusion_width = 0.25 +perimeter_extrusion_width = 0.25 +solid_infill_extrusion_width = 0.25 +top_infill_extrusion_width = 0.25 +support_material_extrusion_width = 0.2 +support_material_interface_layers = 0 +support_material_interface_spacing = 0.15 +support_material_spacing = 1 +support_material_xy_spacing = 150% +perimeter_speed = 30 +external_perimeter_speed = 20 +small_perimeter_speed = 20 +infill_speed = 45 +solid_infill_speed = 45 +top_solid_infill_speed = 30 +support_material_speed = 40 +bridge_speed = 20 +gap_fill_speed = 30 +perimeter_acceleration = 500 +infill_acceleration = 1000 +bridge_acceleration = 500 +first_layer_acceleration = 500 +default_acceleration = 1000 +max_print_speed = 80 +perimeters = 3 +fill_pattern = grid +fill_density = 20% + # Print parameters common to a 0.6mm diameter nozzle. [print:*0.6nozzle*] external_perimeter_extrusion_width = 0.61 @@ -216,6 +256,18 @@ solid_infill_extrusion_width = 0.65 top_infill_extrusion_width = 0.6 support_material_extrusion_width = 0.55 +[print:*0.6nozzleMK3*] +external_perimeter_extrusion_width = 0.65 +extrusion_width = 0.65 +first_layer_extrusion_width = 0.65 +infill_extrusion_width = 0.7 +perimeter_extrusion_width = 0.65 +solid_infill_extrusion_width = 0.7 +top_infill_extrusion_width = 0.6 +support_material_extrusion_width = 0.55 +bridge_flow_ratio = 0.95 +bridge_speed = 25 + [print:*soluble_support*] overhangs = 1 skirts = 0 @@ -288,6 +340,9 @@ support_material_speed = 20 [print:0.05mm ULTRADETAIL 0.25 nozzle MK3] inherits = *0.05mm*; *0.25nozzle*; *MK3* compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1 +fill_pattern = grid +fill_density = 20% +first_layer_extrusion_width = 0.35 # XXXXXXXXXXXXXXXXXXXX # XXX--- 0.07mm ---XXX @@ -326,6 +381,17 @@ fill_pattern = gyroid compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 and ! single_extruder_multi_material top_infill_extrusion_width = 0.4 +[print:0.07mm ULTRADETAIL 0.25 nozzle MK3] +inherits = *0.07mm*; *0.25nozzle*; *MK3* +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 and num_extruders==1 +infill_speed = 30 +solid_infill_speed = 30 +support_material_speed = 30 +top_solid_infill_speed = 20 +fill_pattern = grid +fill_density = 20% +first_layer_extrusion_width = 0.35 + # XXXXXXXXXXXXXXXXXXXX # XXX--- 0.10mm ---XXX # XXXXXXXXXXXXXXXXXXXX @@ -382,29 +448,10 @@ top_solid_infill_speed = 30 # MK3 # [print:0.10mm DETAIL 0.25 nozzle MK3] -inherits = *0.10mm*; *0.25nozzle*; *MK3* -bridge_speed = 30 +inherits = *0.10mm*; *0.25nozzleMK3*; *MK3* compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 -external_perimeter_speed = 35 -infill_acceleration = 1250 -infill_speed = 200 -max_print_speed = 200 -perimeter_speed = 45 -solid_infill_speed = 200 -top_solid_infill_speed = 50 - -# MK3 # -[print:0.10mm DETAIL 0.6 nozzle MK3] -inherits = *0.10mm*; *0.6nozzle*; *MK3* -bridge_speed = 30 -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6 -external_perimeter_speed = 35 -infill_acceleration = 1250 -infill_speed = 200 -max_print_speed = 200 -perimeter_speed = 45 -solid_infill_speed = 200 -top_solid_infill_speed = 50 +fill_pattern = grid +fill_density = 20% # XXXXXXXXXXXXXXXXXXXX # XXX--- 0.15mm ---XXX @@ -531,17 +578,27 @@ support_material_with_sheath = 0 support_material_xy_spacing = 80% # MK3 # -[print:0.15mm OPTIMAL 0.25 nozzle MK3] -inherits = *0.15mm*; *0.25nozzle*; *MK3* -bridge_speed = 30 +[print:0.15mm QUALITY 0.25 nozzle MK3] +inherits = *0.15mm*; *0.25nozzleMK3*; *MK3* compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.25 +fill_pattern = grid +fill_density = 20% + +# MK3 # +[print:0.15mm DETAIL 0.6 nozzle MK3] +inherits = *0.15mm*; *0.6nozzleMK3*; *MK306* +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6 external_perimeter_speed = 35 infill_acceleration = 1250 -infill_speed = 200 -max_print_speed = 200 +infill_speed = 70 +max_print_speed = 100 perimeter_speed = 45 -solid_infill_speed = 200 -top_solid_infill_speed = 50 +solid_infill_speed = 70 +top_solid_infill_speed = 45 + +# XXXXXXXXXXXXXXXXXXXX +# XXX--- 0.20mm ---XXX +# XXXXXXXXXXXXXXXXXXXX [print:*0.20mm*] inherits = *common* @@ -557,23 +614,6 @@ solid_infill_speed = 50 top_infill_extrusion_width = 0.4 top_solid_layers = 5 -# MK3 # -[print:0.15mm OPTIMAL 0.6 nozzle MK3] -inherits = *0.15mm*; *0.6nozzle*; *MK3* -bridge_speed = 30 -compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6 -external_perimeter_speed = 35 -infill_acceleration = 1250 -infill_speed = 200 -max_print_speed = 200 -perimeter_speed = 45 -solid_infill_speed = 200 -top_solid_infill_speed = 50 - -# XXXXXXXXXXXXXXXXXXXX -# XXX--- 0.20mm ---XXX -# XXXXXXXXXXXXXXXXXXXX - # MK2 # [print:0.20mm 100mms Linear Advance] inherits = *0.20mm* @@ -664,17 +704,68 @@ support_material_with_sheath = 0 support_material_xy_spacing = 80% # MK3 # -[print:0.20mm FAST 0.6 nozzle MK3] -inherits = *0.20mm*; *0.6nozzle*; *MK3* -bridge_speed = 30 +[print:0.20mm DETAIL 0.6 nozzle MK3] +inherits = *0.20mm*; *0.6nozzleMK3*; *MK306* compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6 external_perimeter_speed = 35 infill_acceleration = 1250 -infill_speed = 200 -max_print_speed = 200 +infill_speed = 70 +max_print_speed = 100 perimeter_speed = 45 -solid_infill_speed = 200 -top_solid_infill_speed = 50 +solid_infill_speed = 70 +top_solid_infill_speed = 45 + +# XXXXXXXXXXXXXXXXXXXX +# XXX--- 0.30mm ---XXX +# XXXXXXXXXXXXXXXXXXXX + +[print:*0.30mm*] +inherits = *common* +bottom_solid_layers = 4 +bridge_flow_ratio = 0.95 +external_perimeter_speed = 40 +infill_acceleration = 2000 +infill_speed = 60 +layer_height = 0.3 +perimeter_acceleration = 800 +perimeter_speed = 50 +solid_infill_speed = 50 +top_infill_extrusion_width = 0.4 +top_solid_layers = 4 + +[print:0.30mm QUALITY 0.6 nozzle MK3] +inherits = *0.30mm*; *0.6nozzleMK3*; *MK306* +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6 +external_perimeter_speed = 35 +infill_acceleration = 1250 +infill_speed = 70 +max_print_speed = 100 +perimeter_speed = 45 +solid_infill_speed = 70 +top_solid_infill_speed = 45 + +[print:0.30mm DRAFT MK3] +inherits = *0.30mm*; *MK3* +bottom_solid_layers = 3 +bridge_speed = 30 +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.4 +external_perimeter_speed = 35 +infill_acceleration = 1250 +infill_speed = 85 +max_print_speed = 200 +perimeter_speed = 50 +small_perimeter_speed = 30 +solid_infill_speed = 80 +top_solid_infill_speed = 40 +support_material_speed = 45 +external_perimeter_extrusion_width = 0.6 +extrusion_width = 0.5 +first_layer_extrusion_width = 0.42 +infill_extrusion_width = 0.5 +perimeter_extrusion_width = 0.5 +solid_infill_extrusion_width = 0.5 +top_infill_extrusion_width = 0.45 +support_material_extrusion_width = 0.35 # XXXXXXXXXXXXXXXXXXXX # XXX--- 0.35mm ---XXX @@ -732,6 +823,57 @@ support_material_interface_layers = 2 support_material_with_sheath = 0 support_material_xy_spacing = 150% +# MK3 # +[print:0.35mm SPEED 0.6 nozzle MK3] +inherits = *0.35mm*; *0.6nozzleMK3*; *MK306* +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6 +external_perimeter_speed = 35 +infill_acceleration = 1250 +infill_speed = 70 +max_print_speed = 100 +perimeter_speed = 45 +solid_infill_speed = 70 +top_solid_infill_speed = 45 +external_perimeter_extrusion_width = 0.68 +perimeter_extrusion_width = 0.68 + +# XXXXXXXXXXXXXXXXXXXX +# XXX--- 0.40mm ---XXX +# XXXXXXXXXXXXXXXXXXXX + +[print:*0.40mm*] +inherits = *common* +bottom_solid_layers = 3 +external_perimeter_extrusion_width = 0.6 +external_perimeter_speed = 40 +first_layer_extrusion_width = 0.65 +infill_acceleration = 2000 +infill_speed = 60 +layer_height = 0.4 +perimeter_acceleration = 800 +perimeter_extrusion_width = 0.65 +perimeter_speed = 50 +solid_infill_extrusion_width = 0.65 +solid_infill_speed = 60 +top_solid_infill_speed = 40 +top_solid_layers = 4 + +# MK3 # +[print:0.40mm DRAFT 0.6 nozzle MK3] +inherits = *0.40mm*; *0.6nozzleMK3*; *MK306* +compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK3.*/ and nozzle_diameter[0]==0.6 +external_perimeter_speed = 35 +infill_acceleration = 1250 +infill_speed = 70 +max_print_speed = 100 +perimeter_speed = 45 +solid_infill_speed = 70 +top_solid_infill_speed = 45 +external_perimeter_extrusion_width = 0.7 +perimeter_extrusion_width = 0.7 +infill_extrusion_width = 0.72 +solid_infill_extrusion_width = 0.72 + # XXXXXXXXXXXXXXXXXXXXXX # XXX----- MK2.5 ----XXX # XXXXXXXXXXXXXXXXXXXXXX @@ -827,7 +969,7 @@ filament_settings_id = "" filament_soluble = 0 min_print_speed = 15 slowdown_below_layer_time = 20 -start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}30{endif} ; Filament gcode" [filament:*PLA*] inherits = *common* @@ -844,6 +986,7 @@ first_layer_temperature = 215 max_fan_speed = 100 min_fan_speed = 100 temperature = 210 +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}15{else}30{endif} ; Filament gcode" [filament:*PET*] inherits = *common* @@ -859,9 +1002,14 @@ first_layer_bed_temperature = 85 first_layer_temperature = 230 max_fan_speed = 50 min_fan_speed = 30 -start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}45{endif}; Filament gcode" +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}22{else}45{endif} ; Filament gcode" temperature = 240 +[filament:*PET06*] +inherits = *PET* +compatible_printers_condition = nozzle_diameter[0]==0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +filament_max_volumetric_speed = 15 + [filament:*ABS*] inherits = *common* bed_temperature = 110 @@ -879,6 +1027,7 @@ first_layer_temperature = 255 max_fan_speed = 30 min_fan_speed = 20 temperature = 255 +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{elsif nozzle_diameter[0]==0.6}15{else}30{endif} ; Filament gcode" [filament:*FLEX*] inherits = *common* @@ -906,10 +1055,11 @@ inherits = *PLA* # For now, all but selected filaments are disabled for the MMU 2.0 compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) extrusion_multiplier = 1.2 -filament_cost = 80.65 -filament_density = 4 +filament_cost = 56.64 +filament_density = 3.9 filament_colour = #804040 -filament_max_volumetric_speed = 10 +filament_max_volumetric_speed = 9 +filament_notes = "List of materials tested with standard print settings:\n\nColorFabb bronzeFill\nColorFabb brassFill\nColorFabb steelFill\nColorFabb copperFill" [filament:ColorFabb HT] inherits = *PET* @@ -933,19 +1083,31 @@ inherits = *PLA* filament_cost = 55.5 filament_density = 1.24 -[filament:ColorFabb Woodfil] +[filament:ColorFabb woodFill] inherits = *PLA* # For now, all but selected filaments are disabled for the MMU 2.0 compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) extrusion_multiplier = 1.2 filament_cost = 62.9 filament_density = 1.15 -filament_colour = #804040 +filament_colour = #dfc287 filament_max_volumetric_speed = 10 first_layer_temperature = 200 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 200 +[filament:ColorFabb corkFill] +inherits = *PLA* +compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) +extrusion_multiplier = 1.2 +filament_cost = 45.45 +filament_density = 1.18 +filament_colour = #634d33 +filament_max_volumetric_speed = 6 +first_layer_temperature = 220 +start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" +temperature = 220 + [filament:ColorFabb XT] inherits = *PET* filament_type = PET @@ -1001,7 +1163,7 @@ temperature = 260 inherits = *PET* filament_cost = 56.9 filament_density = 1.26 -filament_notes = "List of manufacturers tested with standart PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG" +filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG" [filament:E3D PC-ABS] inherits = *ABS* @@ -1036,7 +1198,7 @@ max_fan_speed = 50 min_fan_speed = 50 temperature = 275 -[filament:Fillamentum Timberfil] +[filament:Fillamentum Timberfill] inherits = *PLA* # For now, all but selected filaments are disabled for the MMU 2.0 compatible_printers_condition = nozzle_diameter[0]>0.35 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) @@ -1053,19 +1215,19 @@ temperature = 190 inherits = *ABS* filament_cost = 27.82 filament_density = 1.04 -filament_notes = "List of materials tested with standart ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS" +filament_notes = "List of materials tested with standard ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS" [filament:Generic PET] inherits = *PET* filament_cost = 27.82 filament_density = 1.27 -filament_notes = "List of manufacturers tested with standart PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG" +filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG" [filament:Generic PLA] inherits = *PLA* filament_cost = 25.4 filament_density = 1.24 -filament_notes = "List of materials tested with standart PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" +filament_notes = "List of materials tested with standard PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" [filament:Polymaker PC-Max] inherits = *ABS* @@ -1084,11 +1246,11 @@ filament_density = 1.23 cooling = 0 fan_always_on = 0 filament_colour = #FFFFD7 -filament_max_volumetric_speed = 10 -filament_notes = "List of materials tested with standart PVA print settings:\n\nPrimaSelect PVA+\nICE FILAMENTS PVA 'NAUGHTY NATURAL'\nVerbatim BVOH" +filament_max_volumetric_speed = 4 +filament_notes = "List of materials tested with standard PVA print settings:\n\nPrimaSelect PVA+\nICE FILAMENTS PVA 'NAUGHTY NATURAL'" filament_ramming_parameters = "120 100 8.3871 8.6129 8.93548 9.22581 9.48387 9.70968 9.87097 10.0323 10.2258 10.4194 10.6452 10.8065| 0.05 8.34193 0.45 8.73548 0.95 9.34836 1.45 9.78385 1.95 10.0871 2.45 10.5161 2.95 10.8903 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6" filament_soluble = 1 -filament_type = PVA +filament_type = PLA first_layer_temperature = 195 start_filament_gcode = "M900 K{if printer_notes=~/.*PRINTER_HAS_BOWDEN.*/}200{else}10{endif}; Filament gcode" temperature = 195 @@ -1097,7 +1259,7 @@ temperature = 195 inherits = *ABS* filament_cost = 27.82 filament_density = 1.08 -filament_notes = "List of materials tested with standart ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS" +filament_notes = "List of materials tested with standard ABS print settings:\n\nEsun ABS\nFil-A-Gehr ABS\nHatchboxABS\nPlasty Mladec ABS" [filament:*ABS MMU2*] inherits = Prusa ABS @@ -1140,7 +1302,8 @@ temperature = 220 inherits = *PET* filament_cost = 27.82 filament_density = 1.27 -filament_notes = "List of manufacturers tested with standart PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG" +filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG" +compatible_printers_condition = nozzle_diameter[0]!=0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) [filament:Prusament PETG] inherits = *PET* @@ -1148,6 +1311,20 @@ first_layer_temperature = 240 temperature = 250 filament_cost = 24.99 filament_density = 1.27 +compatible_printers_condition = nozzle_diameter[0]!=0.6 and ! (printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material) + +[filament:Prusa PET 0.6 nozzle] +inherits = *PET06* +filament_cost = 27.82 +filament_density = 1.27 +filament_notes = "List of manufacturers tested with standard PET print settings:\n\nE3D Edge\nFillamentum CPE GH100\nPlasty Mladec PETG" + +[filament:Prusament PETG 0.6 nozzle] +inherits = *PET06* +first_layer_temperature = 240 +temperature = 250 +filament_cost = 24.99 +filament_density = 1.27 [filament:*PET MMU2*] inherits = Prusa PET @@ -1179,7 +1356,7 @@ inherits = *PET MMU2* inherits = *PLA* filament_cost = 25.4 filament_density = 1.24 -filament_notes = "List of materials tested with standart PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" +filament_notes = "List of materials tested with standard PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" [filament:Prusament PLA] inherits = *PLA* @@ -1265,7 +1442,7 @@ fan_always_on = 0 fan_below_layer_time = 100 filament_colour = #FFFFD7 filament_max_volumetric_speed = 4 -filament_notes = "List of materials tested with standart PLA print settings:\n\nDas Filament\nEsun PLA\nEUMAKERS PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nVerbatim PLA\nVerbatim BVOH" +filament_notes = "List of materials tested with standard PVA print settings:\n\nVerbatim BVOH" filament_soluble = 1 filament_type = PLA first_layer_bed_temperature = 60 @@ -1279,7 +1456,6 @@ temperature = 210 inherits = Verbatim BVOH compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_MK(2.5|3).*/ and single_extruder_multi_material temperature = 195 -filament_notes = BVOH fan_always_on = 1 first_layer_temperature = 200 filament_cooling_final_speed = 1 @@ -1316,7 +1492,7 @@ filament_loading_speed = 14 filament_loading_speed_start = 19 filament_max_volumetric_speed = 4 filament_minimal_purge_on_wipe_tower = 5 -filament_notes = PVA +filament_notes = "List of materials tested with standard PVA print settings:\n\nPrimaSelect PVA+" filament_ramming_parameters = "120 110 3.83871 3.90323 3.96774 4.03226 4.09677 4.19355 4.3871 4.83871 5.67742 6.93548 8.54839 10.3226 11.9677 13.2581 14.129 14.5806| 0.05 3.8258 0.45 3.89676 0.95 4.05807 1.45 4.23548 1.95 5.18386 2.45 7.80651 2.95 11.5356 3.45 13.9872 3.95 14.7613 4.45 7.6 4.95 7.6" filament_soluble = 1 filament_toolchange_delay = 0 @@ -1346,7 +1522,7 @@ fan_always_on = 1 fan_below_layer_time = 100 filament_colour = #DEE0E6 filament_max_volumetric_speed = 5 -filament_notes = "List of materials tested with standart PLA print settings:\n\nEsun PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nEUMAKERS PLA" +filament_notes = "List of materials tested with standard PLA print settings:\n\nEsun PLA\nFiberlogy HD-PLA\nFillamentum PLA\nFloreon3D\nHatchbox PLA\nPlasty Mladec PLA\nPrimavalue PLA\nProto pasta Matte Fiber\nEUMAKERS PLA" filament_type = PLA first_layer_bed_temperature = 100 first_layer_temperature = 220 @@ -1358,14 +1534,15 @@ temperature = 220 [sla_print:*common*] compatible_printers_condition = printer_notes=~/.*PRINTER_VENDOR_PRUSA3D.*/ and printer_notes=~/.*PRINTER_MODEL_SL1.*/ layer_height = 0.05 -output_filename_format = [input_filename_base].dwz +output_filename_format = [input_filename_base].sl1 pad_edge_radius = 0.5 pad_enable = 1 pad_max_merge_distance = 50 -pad_wall_height = 3 +pad_wall_height = 0 pad_wall_thickness = 1 +pad_wall_slope = 90 support_base_diameter = 3 -support_base_height = 0.5 +support_base_height = 1 support_critical_angle = 45 support_density_at_45 = 250 support_density_at_horizontal = 500 @@ -1376,6 +1553,7 @@ support_max_bridge_length = 10 support_minimal_z = 0 support_object_elevation = 5 support_pillar_diameter = 1 +support_pillar_connection_mode = zigzag support_pillar_widening_factor = 0 supports_enable = 1 @@ -1441,6 +1619,11 @@ inherits = *common 0.025* exposure_time = 5 initial_exposure_time = 35 +[sla_material:SL1 Orange solid 0.025] +inherits = *common 0.025* +exposure_time = 5 +initial_exposure_time = 35 + ########### Materials 0.05 [sla_material:3DM-HTR140 (high temperature) 0.05] @@ -1458,11 +1641,31 @@ inherits = *common 0.05* exposure_time = 8 initial_exposure_time = 45 +[sla_material:Bluecast Keramaster Dental 0.05] +inherits = *common 0.05* +exposure_time = 7 +initial_exposure_time = 45 + +[sla_material:Bluecast LCD-DLP Original 0.05] +inherits = *common 0.05* +exposure_time = 10 +initial_exposure_time = 60 + [sla_material:Bluecast Phrozen Wax 0.05] inherits = *common 0.05* exposure_time = 10 initial_exposure_time = 55 +[sla_material:Bluecast S+ 0.05] +inherits = *common 0.05* +exposure_time = 9 +initial_exposure_time = 45 + +[sla_material:Bluecast X2 0.05] +inherits = *common 0.05* +exposure_time = 10 +initial_exposure_time = 60 + [sla_material:Jamg He PJHC-00 Yellow 0.05] inherits = *common 0.05* exposure_time = 7 @@ -1475,7 +1678,7 @@ initial_exposure_time = 45 [sla_material:Jamg He PJHC-30 Orange 0.05] inherits = *common 0.05* -exposure_time = 7 +exposure_time = 7.5 initial_exposure_time = 45 [sla_material:Jamg He PJHC-60 Gray 0.05] @@ -1513,8 +1716,6 @@ inherits = *common 0.05* exposure_time = 7 initial_exposure_time = 40 -# v2 - [sla_material:3DM-ABS 0.05] inherits = *common 0.05* exposure_time = 9 @@ -1560,11 +1761,101 @@ inherits = *common 0.05* exposure_time = 6.5 initial_exposure_time = 40 +[sla_material:Harz Labs Model Resin Cherry 0.05] +inherits = *common 0.05* +exposure_time = 8 +initial_exposure_time = 45 + +[sla_material:Jamg He CRX-70C High Tenacity Black 0.05] +inherits = *common 0.05* +exposure_time = 7 +initial_exposure_time = 40 + +[sla_material:Jamg He MC-2000 Casting Green 0.05] +inherits = *common 0.05* +exposure_time = 13 +initial_exposure_time = 40 + +[sla_material:Jamg He PJHC-00 Solid Yellow 0.05] +inherits = *common 0.05* +exposure_time = 7 +initial_exposure_time = 40 + +[sla_material:Jamg He PJHC-20 White 0.05] +inherits = *common 0.05* +exposure_time = 7 +initial_exposure_time = 45 + +[sla_material:Jamg He PJHC-80 Transparent Green 0.05] +inherits = *common 0.05* +exposure_time = 8 +initial_exposure_time = 45 + +[sla_material:Jamg He PJHC-80 Transparent Red 0.05] +inherits = *common 0.05* +exposure_time = 7 +initial_exposure_time = 45 + +[sla_material:Jamg He PJHC-81 Solid Maroon 0.05] +inherits = *common 0.05* +exposure_time = 9 +initial_exposure_time = 45 + +[sla_material:Jamg He PJHC-90 Solid Pink 0.05] +inherits = *common 0.05* +exposure_time = 7 +initial_exposure_time = 40 + +[sla_material:Jamg He RJHC-00 Yellow Flexible 0.05] +inherits = *common 0.05* +exposure_time = 9 +initial_exposure_time = 40 + +[sla_material:Jamg He RJHC-10 Clear Flexible 0.05] +inherits = *common 0.05* +exposure_time = 9 +initial_exposure_time = 40 + +[sla_material:Jamg He RJHC-20 White Flexible 0.05] +inherits = *common 0.05* +exposure_time = 9 +initial_exposure_time = 40 + +[sla_material:Jamg He RJHC-50 Blue Flexible 0.05] +inherits = *common 0.05* +exposure_time = 9 +initial_exposure_time = 40 + +[sla_material:Jamg He RJHC-70 Black Flexible 0.05] +inherits = *common 0.05* +exposure_time = 9 +initial_exposure_time = 40 + +[sla_material:Jamg He RJHC-81 Red Flexible 0.05] +inherits = *common 0.05* +exposure_time = 9 +initial_exposure_time = 40 + +[sla_material:SL1 Orange solid 0.05] +inherits = *common 0.05* +exposure_time = 7.5 +initial_exposure_time = 45 + +[sla_material:SL1 Red transparent 0.05] +inherits = *common 0.05* +exposure_time = 7.5 +initial_exposure_time = 45 + ########### Materials 0.035 [sla_material:Jamg He PJHC-30 Orange 0.035] inherits = *common 0.035* -exposure_time = 9 +exposure_time = 6 +initial_exposure_time = 35 + +[sla_material:SL1 Orange solid 0.035] +inherits = *common 0.035* +exposure_time = 6 initial_exposure_time = 35 ########### Materials 0.1 @@ -1574,6 +1865,11 @@ inherits = *common 0.1* exposure_time = 10 initial_exposure_time = 45 +[sla_material:SL1 Orange solid 0.1] +inherits = *common 0.1* +exposure_time = 10 +initial_exposure_time = 45 + [printer:*common*] printer_technology = FFF bed_shape = 0x0,250x0,250x210,0x210 @@ -1740,19 +2036,19 @@ min_layer_height = 0.1 inherits = Original Prusa i3 MK2S printer_model = MK2.5 remaining_times = 1 -start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5 0.25 nozzle] inherits = Original Prusa i3 MK2S 0.25 nozzle printer_model = MK2.5 remaining_times = 1 -start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5 0.6 nozzle] inherits = Original Prusa i3 MK2S 0.6 nozzle printer_model = MK2.5 remaining_times = 1 -start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5 MMU2 Single] inherits = Original Prusa i3 MK2.5; *mm2* @@ -1781,7 +2077,7 @@ machine_min_travel_rate = 0 default_print_profile = 0.15mm OPTIMAL MK2.5 default_filament_profile = Prusament PLA printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n -start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n +start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors [printer:Original Prusa i3 MK2.5 MMU2] @@ -1815,20 +2111,23 @@ single_extruder_multi_material = 1 # to be defined explicitely. nozzle_diameter = 0.4,0.4,0.4,0.4,0.4 extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F -start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n +start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n [printer:Original Prusa i3 MK2.5S] inherits = Original Prusa i3 MK2.5 printer_model = MK2.5S +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5S 0.25 nozzle] inherits = Original Prusa i3 MK2.5 0.25 nozzle printer_model = MK2.5S +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5S 0.6 nozzle] inherits = Original Prusa i3 MK2.5 0.6 nozzle printer_model = MK2.5S +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0 [printer:Original Prusa i3 MK2.5S MMU2S Single] inherits = Original Prusa i3 MK2.5; *mm2s* @@ -1857,7 +2156,7 @@ machine_min_travel_rate = 0 default_print_profile = 0.15mm OPTIMAL MK2.5 default_filament_profile = Prusament PLA printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK2.5\n -start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n +start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors [printer:Original Prusa i3 MK2.5S MMU2S] @@ -1891,7 +2190,7 @@ single_extruder_multi_material = 1 # to be defined explicitely. nozzle_diameter = 0.4,0.4,0.4,0.4,0.4 extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F -start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n +start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n @@ -1923,7 +2222,7 @@ remaining_times = 1 printer_notes = Don't remove the following keywords! These keywords are used in the "compatible printer" condition of the print and filament profiles to link the particular print and filament profiles to this printer profile.\nPRINTER_VENDOR_PRUSA3D\nPRINTER_MODEL_MK3\n retract_lift_below = 209 max_print_height = 210 -start_gcode = M115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} printer_model = MK3 default_print_profile = 0.15mm QUALITY MK3 @@ -1933,27 +2232,31 @@ nozzle_diameter = 0.25 max_layer_height = 0.15 min_layer_height = 0.05 printer_variant = 0.25 +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} default_print_profile = 0.10mm DETAIL 0.25 nozzle MK3 [printer:Original Prusa i3 MK3 0.6 nozzle] inherits = Original Prusa i3 MK3 nozzle_diameter = 0.6 -max_layer_height = 0.35 -min_layer_height = 0.1 +max_layer_height = 0.40 +min_layer_height = 0.15 printer_variant = 0.6 -default_print_profile = 0.15mm OPTIMAL 0.6 nozzle MK3 +default_print_profile = 0.30mm QUALITY 0.6 nozzle MK3 [printer:Original Prusa i3 MK3S] inherits = Original Prusa i3 MK3 printer_model = MK3S +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} [printer:Original Prusa i3 MK3S 0.25 nozzle] inherits = Original Prusa i3 MK3 0.25 nozzle printer_model = MK3S +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E8.0 F700.0 ; intro line\nG1 X100.0 E12.5 F700.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} [printer:Original Prusa i3 MK3S 0.6 nozzle] inherits = Original Prusa i3 MK3 0.6 nozzle printer_model = MK3S +start_gcode = M115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG1 Y-3.0 F1000.0 ; go outside print area\nG92 E0.0\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E12.5 F1000.0 ; intro line\nG92 E0.0\nM221 S{if layer_height<0.075}100{else}95{endif} [printer:*mm2*] inherits = Original Prusa i3 MK3 @@ -1983,7 +2286,7 @@ default_filament_profile = Prusament PLA MMU2 inherits = *mm2* single_extruder_multi_material = 0 default_filament_profile = Prusament PLA -start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n +start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors [printer:Original Prusa i3 MK3 MMU2] @@ -1994,14 +2297,14 @@ inherits = *mm2* machine_max_acceleration_e = 8000,8000 nozzle_diameter = 0.4,0.4,0.4,0.4,0.4 extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F -start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n +start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E32.0 F1073.0\nG1 X5.0 E32.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n [printer:Original Prusa i3 MK3S MMU2S Single] inherits = *mm2s* single_extruder_multi_material = 0 default_filament_profile = Prusament PLA -start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n +start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nTx\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\n\nG21 ; set units to millimeters\n\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nTc\n; purge line\nG1 X55.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n end_gcode = G1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\nG1 X0 Y200; home X axis\nM84 ; disable motors [printer:Original Prusa i3 MK3S MMU2S] @@ -2009,14 +2312,14 @@ inherits = *mm2s* machine_max_acceleration_e = 8000,8000 nozzle_diameter = 0.4,0.4,0.4,0.4,0.4 extruder_colour = #FF8000;#DB5182;#00FFFF;#FF4F4F;#9FFF9F -start_gcode = M107\nM115 U3.5.1 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n +start_gcode = M107\nM115 U3.6.0 ; tell printer latest fw version\nM83 ; extruder relative mode\nM104 S[first_layer_temperature] ; set extruder temp\nM140 S[first_layer_bed_temperature] ; set bed temp\nM190 S[first_layer_bed_temperature] ; wait for bed temp\nM109 S[first_layer_temperature] ; wait for extruder temp\nG28 W ; home all without mesh bed level\nG80 ; mesh bed leveling\nG21 ; set units to millimeters\n\n; Send the filament type to the MMU2.0 unit.\n; E stands for extruder number, F stands for filament type (0: default; 1:flex; 2: PVA)\nM403 E0 F{"" + ((filament_type[0]=="FLEX") ? 1 : ((filament_type[0]=="PVA") ? 2 : 0))}\nM403 E1 F{"" + ((filament_type[1]=="FLEX") ? 1 : ((filament_type[1]=="PVA") ? 2 : 0))}\nM403 E2 F{"" + ((filament_type[2]=="FLEX") ? 1 : ((filament_type[2]=="PVA") ? 2 : 0))}\nM403 E3 F{"" + ((filament_type[3]=="FLEX") ? 1 : ((filament_type[3]=="PVA") ? 2 : 0))}\nM403 E4 F{"" + ((filament_type[4]=="FLEX") ? 1 : ((filament_type[4]=="PVA") ? 2 : 0))}\n\n{if not has_single_extruder_multi_material_priming}\n;go outside print area\nG1 Y-3.0 F1000.0\nG1 Z0.4 F1000.0\n; select extruder\nT[initial_tool]\n; initial load\nG1 X55.0 E29.0 F1073.0\nG1 X5.0 E29.0 F1800.0\nG1 X55.0 E8.0 F2000.0\nG1 Z0.3 F1000.0\nG92 E0.0\nG1 X240.0 E25.0 F2200.0\nG1 Y-2.0 F1000.0\nG1 X55.0 E25 F1400.0\nG1 Z0.20 F1000.0\nG1 X5.0 E4.0 F1000.0\nG92 E0.0\n{endif}\n\nM221 S{if layer_height<0.075}100{else}95{endif}\nG90 ; use absolute coordinates\nM83 ; use relative distances for extrusion\nG92 E0.0\n end_gcode = {if has_wipe_tower}\nG1 E-15.0000 F3000\n{else}\nG1 X0 Y210 F7200\nG1 E2 F5000\nG1 E2 F5500\nG1 E2 F6000\nG1 E-15.0000 F5800\nG1 E-20.0000 F5500\nG1 E10.0000 F3000\nG1 E-10.0000 F3100\nG1 E10.0000 F3150\nG1 E-10.0000 F3250\nG1 E10.0000 F3300\n{endif}\n\n; Unload filament\nM702 C\n\nG4 ; wait\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n; Lift print head a bit\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+30, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200; home X axis\nM84 ; disable motors\n [printer:Original Prusa SL1] printer_technology = SLA printer_model = SL1 printer_variant = default -default_sla_material_profile = Jamg He Transparent Green 0.05 +default_sla_material_profile = Jamg He PJHC-30 Orange 0.05 default_sla_print_profile = 0.05 Normal bed_shape = 0.98x1.02,119.98x1.02,119.98x68.02,0.98x68.02 display_height = 68.04 From e74bde858a9ccfbdd85966383487f29d02910bcc Mon Sep 17 00:00:00 2001 From: YuSanka Date: Sat, 16 Mar 2019 22:23:51 +0100 Subject: [PATCH 11/23] Deleted imaginary optimization for the Preset comboboxes on sidebar. --- src/slic3r/GUI/Plater.hpp | 2 -- src/slic3r/GUI/Preset.cpp | 7 +------ src/slic3r/GUI/PresetBundle.cpp | 5 +---- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 4261dbae2..ecce63805 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -51,8 +51,6 @@ public: int get_extruder_idx() const { return extruder_idx; } void check_selection(); - std::string selected_preset_name; - private: typedef std::size_t Marker; enum { LABEL_ITEM_MARKER = 0x4d }; diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index bb70b8f47..656658b0b 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -879,8 +879,7 @@ size_t PresetCollection::update_compatible_internal(const Preset &active_printer // Hide the void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) { - if (ui == nullptr || - ui->selected_preset_name == this->get_selected_preset().name) + if (ui == nullptr) return; // Otherwise fill in the list from scratch. @@ -951,10 +950,6 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui) ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); ui->Thaw(); - - // For printer preset it's important to update preset list every time because of ConfigWizard - // So, don't save selected preset name - ui->selected_preset_name = type()==Preset::TYPE_PRINTER ? "" : this->get_selected_preset().name; } size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompatible) diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp index 52421fafa..f0bb4de01 100644 --- a/src/slic3r/GUI/PresetBundle.cpp +++ b/src/slic3r/GUI/PresetBundle.cpp @@ -1436,8 +1436,7 @@ bool PresetBundle::parse_color(const std::string &scolor, unsigned char *rgb_out void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::PresetComboBox *ui) { if (ui == nullptr || this->printers.get_edited_preset().printer_technology() == ptSLA || - this->filament_presets.size() <= idx_extruder || - ui->selected_preset_name == this->filaments.find_preset(this->filament_presets[idx_extruder])->name) + this->filament_presets.size() <= idx_extruder ) return; unsigned char rgb[3]; @@ -1526,8 +1525,6 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr ui->SetSelection(selected_preset_item); ui->SetToolTip(ui->GetString(selected_preset_item)); ui->Thaw(); - - ui->selected_preset_name = this->filaments.find_preset(this->filament_presets[idx_extruder])->name; } void PresetBundle::set_default_suppressed(bool default_suppressed) From 9eea1561b372b00b7a200e03d1d25c5d6bdb64b8 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 17 Mar 2019 09:32:53 +0100 Subject: [PATCH 12/23] fix of problems with Cyrillic in the snapshot (if the name of the Russian letters) #1956 --- src/slic3r/GUI/ConfigSnapshotDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/ConfigSnapshotDialog.cpp b/src/slic3r/GUI/ConfigSnapshotDialog.cpp index 422f683b3..205e84f57 100644 --- a/src/slic3r/GUI/ConfigSnapshotDialog.cpp +++ b/src/slic3r/GUI/ConfigSnapshotDialog.cpp @@ -38,7 +38,7 @@ static wxString generate_html_row(const Config::Snapshot &snapshot, bool row_eve text += wxString("") + (snapshot_active ? _(L("Active: ")) : "") + Utils::format_local_date_time(snapshot.time_captured) + ": " + format_reason(snapshot.reason); if (! snapshot.comment.empty()) - text += " (" + snapshot.comment + ")"; + text += " (" + wxString::FromUTF8(snapshot.comment.data()) + ")"; text += "
"; // End of row header. text += _(L("slic3r version")) + ": " + snapshot.slic3r_version_captured.to_string() + "
"; From 2bb4b4e691ac3372e19ee829a0bf46510b0a31d4 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 17 Mar 2019 14:35:54 +0100 Subject: [PATCH 13/23] Command line - improved error handling --- src/libslic3r/Config.cpp | 16 ++++++++-------- src/slic3r.cpp | 4 +++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 037bd3500..91e74a032 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -713,11 +713,8 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra, // Look for the cli -> option mapping. const auto it = opts.find(token); if (it == opts.end()) { - printf("Warning: unknown option --%s\n", token.c_str()); - // instead of continuing, return false to caller - // to stop execution and print usage - return false; - //continue; + boost::nowide::cerr << "Unknown option --" << token.c_str() << std::endl; + return false; } const t_config_option_key opt_key = it->second; const ConfigOptionDef &optdef = this->def()->options.at(opt_key); @@ -725,8 +722,8 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra, // look for it in the next token. if (optdef.type != coBool && optdef.type != coBools && value.empty()) { if (i == (argc-1)) { - printf("No value supplied for --%s\n", token.c_str()); - continue; + boost::nowide::cerr << "No value supplied for --" << token.c_str() << std::endl; + return false; } value = argv[++ i]; } @@ -759,7 +756,10 @@ bool DynamicConfig::read_cli(int argc, char** argv, t_config_option_keys* extra, static_cast(opt_base)->value = value; } else { // Any scalar value of a type different from Bool and String. - this->set_deserialize(opt_key, value, false); + if (! this->set_deserialize(opt_key, value, false)) { + boost::nowide::cerr << "Invalid value supplied for --" << token.c_str() << std::endl; + return false; + } } } return true; diff --git a/src/slic3r.cpp b/src/slic3r.cpp index b60c5b1dd..3b301ec2a 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -523,6 +523,8 @@ bool CLI::setup(int argc, char **argv) // If any option is unsupported, print usage and abort immediately. t_config_option_keys opt_order; if (! m_config.read_cli(argc, argv, &m_input_files, &opt_order)) { + // Separate error message reported by the CLI parser from the help. + boost::nowide::cerr << std::endl; this->print_help(); return false; } @@ -615,7 +617,7 @@ std::string CLI::output_filepath(const Model &model, IO::ExportFormat format) co }; auto proposed_path = boost::filesystem::path(model.propose_export_file_name_and_path(ext)); // use --output when available - std::string cmdline_param = m_config.opt_string("output", false); + std::string cmdline_param = m_config.opt_string("output"); if (! cmdline_param.empty()) { // if we were supplied a directory, use it and append our automatically generated filename boost::filesystem::path cmdline_path(cmdline_param); From 5fc37238e08b34f79437d090f92c8dc2c0ce696f Mon Sep 17 00:00:00 2001 From: bubnikv Date: Sun, 17 Mar 2019 15:04:34 +0100 Subject: [PATCH 14/23] Fixed missing include on OSX --- src/libslic3r/Config.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index 91e74a032..a7db29b8e 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include From 902bcf7f710cb689cbe6d3cc2c193b37b2d28bbb Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 18 Mar 2019 09:42:34 +0100 Subject: [PATCH 15/23] Fix of #1978 --- src/libslic3r/GCode/Analyzer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/GCode/Analyzer.cpp b/src/libslic3r/GCode/Analyzer.cpp index f1f828776..d1ad4f575 100644 --- a/src/libslic3r/GCode/Analyzer.cpp +++ b/src/libslic3r/GCode/Analyzer.cpp @@ -726,7 +726,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ GCodePreviewData::Range volumetric_rate_range; // to avoid to call the callback too often - unsigned int cancel_callback_threshold = (unsigned int)extrude_moves->second.size() / 25; + unsigned int cancel_callback_threshold = (unsigned int)std::max((int)extrude_moves->second.size() / 25, 1); unsigned int cancel_callback_curr = 0; // constructs the polylines while traversing the moves @@ -807,7 +807,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, s GCodePreviewData::Range feedrate_range; // to avoid to call the callback too often - unsigned int cancel_callback_threshold = (unsigned int)travel_moves->second.size() / 25; + unsigned int cancel_callback_threshold = (unsigned int)std::max((int)travel_moves->second.size() / 25, 1); unsigned int cancel_callback_curr = 0; // constructs the polylines while traversing the moves @@ -864,7 +864,7 @@ void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_da return; // to avoid to call the callback too often - unsigned int cancel_callback_threshold = (unsigned int)retraction_moves->second.size() / 25; + unsigned int cancel_callback_threshold = (unsigned int)std::max((int)retraction_moves->second.size() / 25, 1); unsigned int cancel_callback_curr = 0; for (const GCodeMove& move : retraction_moves->second) @@ -886,7 +886,7 @@ void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_ return; // to avoid to call the callback too often - unsigned int cancel_callback_threshold = (unsigned int)unretraction_moves->second.size() / 25; + unsigned int cancel_callback_threshold = (unsigned int)std::max((int)unretraction_moves->second.size() / 25, 1); unsigned int cancel_callback_curr = 0; for (const GCodeMove& move : unretraction_moves->second) From 710bb66dfc39dad6e13a45329bce4de7acf18c7d Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 18 Mar 2019 10:10:11 +0100 Subject: [PATCH 16/23] Fixed assert in imgui when starting Slic3r for the 1st time (no config data saved on disk) --- src/slic3r/GUI/GLCanvas3D.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index dac370b54..94d26fea6 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4159,8 +4159,11 @@ void GLCanvas3D::render() return; if (m_bed.get_shape().empty()) + { // this happens at startup when no data is still saved under <>\AppData\Roaming\Slic3rPE post_event(SimpleEvent(EVT_GLCANVAS_UPDATE_BED_SHAPE)); + return; + } if (m_camera.requires_zoom_to_bed) { From fe91edc5216175f8becfeb68552865fcaa3d6ad2 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 18 Mar 2019 10:18:24 +0100 Subject: [PATCH 17/23] Set MinSize() in respect to em_unit --- src/slic3r/GUI/MainFrame.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 1d1982ffa..9e54b9b36 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -56,7 +56,8 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL // initialize default width_unit according to the width of the one symbol ("x") of the current system font const wxSize size = GetTextExtent("m"); - wxGetApp().set_em_unit(size.x-1); +// wxGetApp().set_em_unit(size.x-1); + wxGetApp().set_em_unit(std::max(10, size.x - 1)); // initialize tabpanel and menubar init_tabpanel(); @@ -76,12 +77,14 @@ wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAUL sizer->SetSizeHints(this); SetSizer(sizer); Fit(); + + const wxSize min_size = wxSize(76*wxGetApp().em_unit(), 49*wxGetApp().em_unit()); #ifdef __APPLE__ // Using SetMinSize() on Mac messes up the window position in some cases // cf. https://groups.google.com/forum/#!topic/wx-users/yUKPBBfXWO0 - SetSize(wxSize(760, 490)); + SetSize(min_size/*wxSize(760, 490)*/); #else - SetMinSize(wxSize(760, 490)); + SetMinSize(min_size/*wxSize(760, 490)*/); SetSize(GetMinSize()); #endif Layout(); From feb2041c7b8fce8fd5a73eef1548f3361029d159 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 18 Mar 2019 10:47:01 +0100 Subject: [PATCH 18/23] Context menu in 3D scene shown on right mouse up event --- src/slic3r/GUI/GLCanvas3D.cpp | 67 ++++++++++++++++------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 94d26fea6..dff68d21d 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5264,42 +5264,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_moving = true; } } - else if (evt.RightDown()) - { - m_mouse.position = pos.cast(); - // forces a frame render to ensure that m_hover_volume_id is updated even when the user right clicks while - // the context menu is already shown - render(); - if (m_hover_volume_id != -1) - { - // if right clicking on volume, propagate event through callback (shows context menu) - if (m_volumes.volumes[m_hover_volume_id]->hover - && !m_volumes.volumes[m_hover_volume_id]->is_wipe_tower // no context menu for the wipe tower - && m_gizmos.get_current_type() != Gizmos::SlaSupports) // disable context menu when the gizmo is open - { - // forces the selection of the volume - /** #ys_FIXME_to_delete after testing: - * Next condition allows a multiple instance selection for the context menu, - * which has no reason. So it's commented till next testing - */ -// if (!m_selection.is_multiple_full_instance()) // #ys_FIXME_to_delete - m_selection.add(m_hover_volume_id); - m_gizmos.update_on_off_state(m_selection); - post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); - _update_gizmos_data(); - wxGetApp().obj_manipul()->update_settings_value(m_selection); - // forces a frame render to update the view before the context menu is shown - render(); - - Vec2d logical_pos = pos.cast(); -#if ENABLE_RETINA_GL - const float factor = m_retina_helper->get_scale_factor(); - logical_pos = logical_pos.cwiseQuotient(Vec2d(factor, factor)); -#endif // ENABLE_RETINA_GL - post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, logical_pos)); - } - } - } } } } @@ -5521,6 +5485,37 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); m_camera.set_scene_box(scene_bounding_box()); } + else if (evt.RightUp()) + { + m_mouse.position = pos.cast(); + // forces a frame render to ensure that m_hover_volume_id is updated even when the user right clicks while + // the context menu is already shown + render(); + if (m_hover_volume_id != -1) + { + // if right clicking on volume, propagate event through callback (shows context menu) + if (m_volumes.volumes[m_hover_volume_id]->hover + && !m_volumes.volumes[m_hover_volume_id]->is_wipe_tower // no context menu for the wipe tower + && m_gizmos.get_current_type() != Gizmos::SlaSupports) // disable context menu when the gizmo is open + { + // forces the selection of the volume + m_selection.add(m_hover_volume_id); + m_gizmos.update_on_off_state(m_selection); + post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT)); + _update_gizmos_data(); + wxGetApp().obj_manipul()->update_settings_value(m_selection); + // forces a frame render to update the view before the context menu is shown + render(); + + Vec2d logical_pos = pos.cast(); +#if ENABLE_RETINA_GL + const float factor = m_retina_helper->get_scale_factor(); + logical_pos = logical_pos.cwiseQuotient(Vec2d(factor, factor)); +#endif // ENABLE_RETINA_GL + post_event(Vec2dEvent(EVT_GLCANVAS_RIGHT_CLICK, logical_pos)); + } + } + } m_moving = false; m_mouse.drag.move_volume_idx = -1; From 0d9a74bb6d9406e438308a801a231c4699a6c8bf Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 18 Mar 2019 10:48:23 +0100 Subject: [PATCH 19/23] Fix for ugly code. --- src/libslic3r/SLA/SLASupportTree.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index 437f07fcb..a5fcaf3f3 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -755,9 +755,12 @@ public: return m_compact_bridges; } - template inline - typename std::enable_if::value, const Pillar&>::type - pillar(T id) const { assert(id >= 0); return m_pillars.at(size_t(id)); } + template inline const Pillar& pillar(T id) const { + static_assert(std::is_integral::value, "Invalid index type"); + assert(id >= 0 && id < m_pillars.size() && + id < std::numerix_limits::max()); + return m_pillars[size_t(id)]; + } const Pad& create_pad(const TriangleMesh& object_supports, const ExPolygons& baseplate, From 160d708ecdaccd3e5097672a4f1b42083e378f7c Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 18 Mar 2019 11:27:27 +0100 Subject: [PATCH 20/23] Typo fix.... sorry guys --- src/libslic3r/SLA/SLASupportTree.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index a5fcaf3f3..650dfe2e7 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -758,7 +758,7 @@ public: template inline const Pillar& pillar(T id) const { static_assert(std::is_integral::value, "Invalid index type"); assert(id >= 0 && id < m_pillars.size() && - id < std::numerix_limits::max()); + id < std::numeric_limits::max()); return m_pillars[size_t(id)]; } From d3c8e3166eea156bb9049269a7100ec1d8346e39 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 15 Mar 2019 12:53:15 +0100 Subject: [PATCH 21/23] Separated gizmos into individual files --- src/slic3r/CMakeLists.txt | 16 +- src/slic3r/GUI/GLCanvas3D.cpp | 5 +- src/slic3r/GUI/GLGizmo.cpp | 2908 ------------------ src/slic3r/GUI/GLGizmo.hpp | 647 ---- src/slic3r/GUI/GLTexture.hpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 286 ++ src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 196 ++ src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 288 ++ src/slic3r/GUI/Gizmos/GLGizmoCut.hpp | 68 + src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp | 357 +++ src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp | 67 + src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 257 ++ src/slic3r/GUI/Gizmos/GLGizmoMove.hpp | 60 + src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 505 +++ src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp | 144 + src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 364 +++ src/slic3r/GUI/Gizmos/GLGizmoScale.hpp | 65 + src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 912 ++++++ src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp | 137 + src/slic3r/GUI/Gizmos/GLGizmos.hpp | 11 + 20 files changed, 3734 insertions(+), 3560 deletions(-) delete mode 100644 src/slic3r/GUI/GLGizmo.cpp delete mode 100644 src/slic3r/GUI/GLGizmo.hpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoBase.cpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoBase.hpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoCut.cpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoCut.hpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoMove.cpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoMove.hpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoScale.cpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoScale.hpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp create mode 100644 src/slic3r/GUI/Gizmos/GLGizmos.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index e4a8c9678..219f17082 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -28,8 +28,20 @@ set(SLIC3R_GUI_SOURCES GUI/GLCanvas3D.cpp GUI/GLCanvas3DManager.hpp GUI/GLCanvas3DManager.cpp - GUI/GLGizmo.hpp - GUI/GLGizmo.cpp + GUI/Gizmos/GLGizmoBase.cpp + GUI/Gizmos/GLGizmoBase.hpp + GUI/Gizmos/GLGizmoMove.cpp + GUI/Gizmos/GLGizmoMove.hpp + GUI/Gizmos/GLGizmoRotate.cpp + GUI/Gizmos/GLGizmoRotate.hpp + GUI/Gizmos/GLGizmoScale.cpp + GUI/Gizmos/GLGizmoScale.hpp + GUI/Gizmos/GLGizmoSlaSupports.cpp + GUI/Gizmos/GLGizmoSlaSupports.hpp + GUI/Gizmos/GLGizmoFlatten.cpp + GUI/Gizmos/GLGizmoFlatten.hpp + GUI/Gizmos/GLGizmoCut.cpp + GUI/Gizmos/GLGizmoCut.hpp GUI/GLTexture.hpp GUI/GLTexture.cpp GUI/GLToolbar.hpp diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index dff68d21d..902c68b59 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1,4 +1,4 @@ -#include "slic3r/GUI/GLGizmo.hpp" +#include "slic3r/GUI/Gizmos/GLGizmos.hpp" #include "GLCanvas3D.hpp" #include "admesh/stl.h" @@ -16,7 +16,6 @@ #include "slic3r/GUI/GLShader.hpp" #include "slic3r/GUI/GUI.hpp" #include "slic3r/GUI/PresetBundle.hpp" -//#include "slic3r/GUI/GLGizmo.hpp" #include "GUI_App.hpp" #include "GUI_ObjectList.hpp" #include "GUI_ObjectManipulation.hpp" @@ -78,7 +77,7 @@ static const float DEFAULT_BG_LIGHT_COLOR[3] = { 0.753f, 0.753f, 0.753f }; static const float ERROR_BG_DARK_COLOR[3] = { 0.478f, 0.192f, 0.039f }; static const float ERROR_BG_LIGHT_COLOR[3] = { 0.753f, 0.192f, 0.039f }; static const float UNIFORM_SCALE_COLOR[3] = { 1.0f, 0.38f, 0.0f }; -static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } }; +//static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } }; namespace Slic3r { namespace GUI { diff --git a/src/slic3r/GUI/GLGizmo.cpp b/src/slic3r/GUI/GLGizmo.cpp deleted file mode 100644 index 34d0c746a..000000000 --- a/src/slic3r/GUI/GLGizmo.cpp +++ /dev/null @@ -1,2908 +0,0 @@ -// Include GLGizmo.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. -#include "GLGizmo.hpp" - -#include -#include - -#include "libslic3r/libslic3r.h" -#include "libslic3r/Geometry.hpp" -#include "libslic3r/Utils.hpp" -#include "libslic3r/SLA/SLACommon.hpp" -#include "libslic3r/SLAPrint.hpp" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "Tab.hpp" -#include "GUI.hpp" -#include "GUI_Utils.hpp" -#include "GUI_App.hpp" -#include "GUI_ObjectSettings.hpp" -#include "GUI_ObjectList.hpp" -#include "I18N.hpp" -#include "PresetBundle.hpp" - -#include - -// TODO: Display tooltips quicker on Linux - -static const float DEFAULT_BASE_COLOR[3] = { 0.625f, 0.625f, 0.625f }; -static const float DEFAULT_DRAG_COLOR[3] = { 1.0f, 1.0f, 1.0f }; -static const float DEFAULT_HIGHLIGHT_COLOR[3] = { 1.0f, 0.38f, 0.0f }; - -static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } }; - -namespace Slic3r { -namespace GUI { - -const float GLGizmoBase::Grabber::SizeFactor = 0.025f; -const float GLGizmoBase::Grabber::MinHalfSize = 1.5f; -const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; - -GLGizmoBase::Grabber::Grabber() - : center(Vec3d::Zero()) - , angles(Vec3d::Zero()) - , dragging(false) - , enabled(true) -{ - color[0] = 1.0f; - color[1] = 1.0f; - color[2] = 1.0f; -} - -void GLGizmoBase::Grabber::render(bool hover, float size) const -{ - float render_color[3]; - if (hover) - { - render_color[0] = 1.0f - color[0]; - render_color[1] = 1.0f - color[1]; - render_color[2] = 1.0f - color[2]; - } - else - ::memcpy((void*)render_color, (const void*)color, 3 * sizeof(float)); - - render(size, render_color, true); -} - -float GLGizmoBase::Grabber::get_half_size(float size) const -{ - return std::max(size * SizeFactor, MinHalfSize); -} - -float GLGizmoBase::Grabber::get_dragging_half_size(float size) const -{ - return std::max(size * SizeFactor * DraggingScaleFactor, MinHalfSize); -} - -void GLGizmoBase::Grabber::render(float size, const float* render_color, bool use_lighting) const -{ - float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size); - - if (use_lighting) - ::glEnable(GL_LIGHTING); - - ::glColor3fv(render_color); - - ::glPushMatrix(); - ::glTranslated(center(0), center(1), center(2)); - - ::glRotated(Geometry::rad2deg(angles(2)), 0.0, 0.0, 1.0); - ::glRotated(Geometry::rad2deg(angles(1)), 0.0, 1.0, 0.0); - ::glRotated(Geometry::rad2deg(angles(0)), 1.0, 0.0, 0.0); - - // face min x - ::glPushMatrix(); - ::glTranslatef(-(GLfloat)half_size, 0.0f, 0.0f); - ::glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); - render_face(half_size); - ::glPopMatrix(); - - // face max x - ::glPushMatrix(); - ::glTranslatef((GLfloat)half_size, 0.0f, 0.0f); - ::glRotatef(90.0f, 0.0f, 1.0f, 0.0f); - render_face(half_size); - ::glPopMatrix(); - - // face min y - ::glPushMatrix(); - ::glTranslatef(0.0f, -(GLfloat)half_size, 0.0f); - ::glRotatef(90.0f, 1.0f, 0.0f, 0.0f); - render_face(half_size); - ::glPopMatrix(); - - // face max y - ::glPushMatrix(); - ::glTranslatef(0.0f, (GLfloat)half_size, 0.0f); - ::glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); - render_face(half_size); - ::glPopMatrix(); - - // face min z - ::glPushMatrix(); - ::glTranslatef(0.0f, 0.0f, -(GLfloat)half_size); - ::glRotatef(180.0f, 1.0f, 0.0f, 0.0f); - render_face(half_size); - ::glPopMatrix(); - - // face max z - ::glPushMatrix(); - ::glTranslatef(0.0f, 0.0f, (GLfloat)half_size); - render_face(half_size); - ::glPopMatrix(); - - ::glPopMatrix(); - - if (use_lighting) - ::glDisable(GL_LIGHTING); -} - -void GLGizmoBase::Grabber::render_face(float half_size) const -{ - ::glBegin(GL_TRIANGLES); - ::glNormal3f(0.0f, 0.0f, 1.0f); - ::glVertex3f(-(GLfloat)half_size, -(GLfloat)half_size, 0.0f); - ::glVertex3f((GLfloat)half_size, -(GLfloat)half_size, 0.0f); - ::glVertex3f((GLfloat)half_size, (GLfloat)half_size, 0.0f); - ::glVertex3f((GLfloat)half_size, (GLfloat)half_size, 0.0f); - ::glVertex3f(-(GLfloat)half_size, (GLfloat)half_size, 0.0f); - ::glVertex3f(-(GLfloat)half_size, -(GLfloat)half_size, 0.0f); - ::glEnd(); -} - -#if ENABLE_SVG_ICONS -GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) -#else -GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id) -#endif // ENABLE_SVG_ICONS - : m_parent(parent) - , m_group_id(-1) - , m_state(Off) - , m_shortcut_key(0) -#if ENABLE_SVG_ICONS - , m_icon_filename(icon_filename) -#endif // ENABLE_SVG_ICONS - , m_sprite_id(sprite_id) - , m_hover_id(-1) - , m_dragging(false) -#if ENABLE_IMGUI - , m_imgui(wxGetApp().imgui()) -#endif // ENABLE_IMGUI -{ - ::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 3 * sizeof(float)); - ::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 3 * sizeof(float)); - ::memcpy((void*)m_highlight_color, (const void*)DEFAULT_HIGHLIGHT_COLOR, 3 * sizeof(float)); -} - -void GLGizmoBase::set_hover_id(int id) -{ - if (m_grabbers.empty() || (id < (int)m_grabbers.size())) - { - m_hover_id = id; - on_set_hover_id(); - } -} - -void GLGizmoBase::set_highlight_color(const float* color) -{ - if (color != nullptr) - ::memcpy((void*)m_highlight_color, (const void*)color, 3 * sizeof(float)); -} - -void GLGizmoBase::enable_grabber(unsigned int id) -{ - if ((0 <= id) && (id < (unsigned int)m_grabbers.size())) - m_grabbers[id].enabled = true; - - on_enable_grabber(id); -} - -void GLGizmoBase::disable_grabber(unsigned int id) -{ - if ((0 <= id) && (id < (unsigned int)m_grabbers.size())) - m_grabbers[id].enabled = false; - - on_disable_grabber(id); -} - -void GLGizmoBase::start_dragging(const GLCanvas3D::Selection& selection) -{ - m_dragging = true; - - for (int i = 0; i < (int)m_grabbers.size(); ++i) - { - m_grabbers[i].dragging = (m_hover_id == i); - } - - on_start_dragging(selection); -} - -void GLGizmoBase::stop_dragging() -{ - m_dragging = false; - - for (int i = 0; i < (int)m_grabbers.size(); ++i) - { - m_grabbers[i].dragging = false; - } - - on_stop_dragging(); -} - -void GLGizmoBase::update(const UpdateData& data, const GLCanvas3D::Selection& selection) -{ - if (m_hover_id != -1) - on_update(data, selection); -} - -std::array GLGizmoBase::picking_color_component(unsigned int id) const -{ - static const float INV_255 = 1.0f / 255.0f; - - id = BASE_ID - id; - - if (m_group_id > -1) - id -= m_group_id; - - // color components are encoded to match the calculation of volume_id made into GLCanvas3D::_picking_pass() - return std::array { (float)((id >> 0) & 0xff) * INV_255, // red - (float)((id >> 8) & 0xff) * INV_255, // green - (float)((id >> 16) & 0xff) * INV_255 }; // blue -} - -void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const -{ - float size = (float)box.max_size(); - - for (int i = 0; i < (int)m_grabbers.size(); ++i) - { - if (m_grabbers[i].enabled) - m_grabbers[i].render((m_hover_id == i), size); - } -} - -void GLGizmoBase::render_grabbers(float size) const -{ - for (int i = 0; i < (int)m_grabbers.size(); ++i) - { - if (m_grabbers[i].enabled) - m_grabbers[i].render((m_hover_id == i), size); - } -} - -void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const -{ - float size = (float)box.max_size(); - - for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) - { - if (m_grabbers[i].enabled) - { - std::array color = picking_color_component(i); - m_grabbers[i].color[0] = color[0]; - m_grabbers[i].color[1] = color[1]; - m_grabbers[i].color[2] = color[2]; - m_grabbers[i].render_for_picking(size); - } - } -} - -#if !ENABLE_IMGUI -void GLGizmoBase::create_external_gizmo_widgets(wxWindow *parent) {} -#endif // not ENABLE_IMGUI - -void GLGizmoBase::set_tooltip(const std::string& tooltip) const -{ - m_parent.set_tooltip(tooltip); -} - -std::string GLGizmoBase::format(float value, unsigned int decimals) const -{ - return Slic3r::string_printf("%.*f", decimals, value); -} - -const float GLGizmoRotate::Offset = 5.0f; -const unsigned int GLGizmoRotate::CircleResolution = 64; -const unsigned int GLGizmoRotate::AngleResolution = 64; -const unsigned int GLGizmoRotate::ScaleStepsCount = 72; -const float GLGizmoRotate::ScaleStepRad = 2.0f * (float)PI / GLGizmoRotate::ScaleStepsCount; -const unsigned int GLGizmoRotate::ScaleLongEvery = 2; -const float GLGizmoRotate::ScaleLongTooth = 0.1f; // in percent of radius -const unsigned int GLGizmoRotate::SnapRegionsCount = 8; -const float GLGizmoRotate::GrabberOffset = 0.15f; // in percent of radius - -GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis) -#if ENABLE_SVG_ICONS - : GLGizmoBase(parent, "", -1) -#else - : GLGizmoBase(parent, -1) -#endif // ENABLE_SVG_ICONS - , m_axis(axis) - , m_angle(0.0) - , m_quadric(nullptr) - , m_center(0.0, 0.0, 0.0) - , m_radius(0.0f) - , m_snap_coarse_in_radius(0.0f) - , m_snap_coarse_out_radius(0.0f) - , m_snap_fine_in_radius(0.0f) - , m_snap_fine_out_radius(0.0f) -{ - m_quadric = ::gluNewQuadric(); - if (m_quadric != nullptr) - ::gluQuadricDrawStyle(m_quadric, GLU_FILL); -} - -GLGizmoRotate::GLGizmoRotate(const GLGizmoRotate& other) -#if ENABLE_SVG_ICONS - : GLGizmoBase(other.m_parent, other.m_icon_filename, other.m_sprite_id) -#else - : GLGizmoBase(other.m_parent, other.m_sprite_id) -#endif // ENABLE_SVG_ICONS - , m_axis(other.m_axis) - , m_angle(other.m_angle) - , m_quadric(nullptr) - , m_center(other.m_center) - , m_radius(other.m_radius) - , m_snap_coarse_in_radius(other.m_snap_coarse_in_radius) - , m_snap_coarse_out_radius(other.m_snap_coarse_out_radius) - , m_snap_fine_in_radius(other.m_snap_fine_in_radius) - , m_snap_fine_out_radius(other.m_snap_fine_out_radius) -{ - m_quadric = ::gluNewQuadric(); - if (m_quadric != nullptr) - ::gluQuadricDrawStyle(m_quadric, GLU_FILL); -} - -GLGizmoRotate::~GLGizmoRotate() -{ - if (m_quadric != nullptr) - ::gluDeleteQuadric(m_quadric); -} - -void GLGizmoRotate::set_angle(double angle) -{ - if (std::abs(angle - 2.0 * (double)PI) < EPSILON) - angle = 0.0; - - m_angle = angle; -} - -bool GLGizmoRotate::on_init() -{ - m_grabbers.push_back(Grabber()); - return true; -} - -void GLGizmoRotate::on_start_dragging(const GLCanvas3D::Selection& selection) -{ - const BoundingBoxf3& box = selection.get_bounding_box(); - m_center = box.center(); - m_radius = Offset + box.radius(); - m_snap_coarse_in_radius = m_radius / 3.0f; - m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius; - m_snap_fine_in_radius = m_radius; - m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth; -} - -void GLGizmoRotate::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) -{ - Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, selection)); - - Vec2d orig_dir = Vec2d::UnitX(); - Vec2d new_dir = mouse_pos.normalized(); - - double theta = ::acos(clamp(-1.0, 1.0, new_dir.dot(orig_dir))); - if (cross2(orig_dir, new_dir) < 0.0) - theta = 2.0 * (double)PI - theta; - - double len = mouse_pos.norm(); - - // snap to coarse snap region - if ((m_snap_coarse_in_radius <= len) && (len <= m_snap_coarse_out_radius)) - { - double step = 2.0 * (double)PI / (double)SnapRegionsCount; - theta = step * (double)std::round(theta / step); - } - else - { - // snap to fine snap region (scale) - if ((m_snap_fine_in_radius <= len) && (len <= m_snap_fine_out_radius)) - { - double step = 2.0 * (double)PI / (double)ScaleStepsCount; - theta = step * (double)std::round(theta / step); - } - } - - if (theta == 2.0 * (double)PI) - theta = 0.0; - - m_angle = theta; -} - -void GLGizmoRotate::on_render(const GLCanvas3D::Selection& selection) const -{ - if (!m_grabbers[0].enabled) - return; - - const BoundingBoxf3& box = selection.get_bounding_box(); - - std::string axis; - switch (m_axis) - { - case X: { axis = "X"; break; } - case Y: { axis = "Y"; break; } - case Z: { axis = "Z"; break; } - } - - if (!m_dragging && (m_hover_id == 0)) - set_tooltip(axis); - else if (m_dragging) - set_tooltip(axis + ": " + format((float)Geometry::rad2deg(m_angle), 4) + "\u00B0"); - else - { - m_center = box.center(); - m_radius = Offset + box.radius(); - m_snap_coarse_in_radius = m_radius / 3.0f; - m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius; - m_snap_fine_in_radius = m_radius; - m_snap_fine_out_radius = m_radius * (1.0f + ScaleLongTooth); - } - - ::glEnable(GL_DEPTH_TEST); - - ::glPushMatrix(); - transform_to_local(selection); - - ::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f); - ::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color); - - render_circle(); - - if (m_hover_id != -1) - { - render_scale(); - render_snap_radii(); - render_reference_radius(); - } - - ::glColor3fv(m_highlight_color); - - if (m_hover_id != -1) - render_angle(); - - render_grabber(box); - render_grabber_extension(box, false); - - ::glPopMatrix(); -} - -void GLGizmoRotate::on_render_for_picking(const GLCanvas3D::Selection& selection) const -{ - ::glDisable(GL_DEPTH_TEST); - - ::glPushMatrix(); - - transform_to_local(selection); - - const BoundingBoxf3& box = selection.get_bounding_box(); - render_grabbers_for_picking(box); - render_grabber_extension(box, true); - - ::glPopMatrix(); -} - -void GLGizmoRotate::render_circle() const -{ - ::glBegin(GL_LINE_LOOP); - for (unsigned int i = 0; i < ScaleStepsCount; ++i) - { - float angle = (float)i * ScaleStepRad; - float x = ::cos(angle) * m_radius; - float y = ::sin(angle) * m_radius; - float z = 0.0f; - ::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z); - } - ::glEnd(); -} - -void GLGizmoRotate::render_scale() const -{ - float out_radius_long = m_snap_fine_out_radius; - float out_radius_short = m_radius * (1.0f + 0.5f * ScaleLongTooth); - - ::glBegin(GL_LINES); - for (unsigned int i = 0; i < ScaleStepsCount; ++i) - { - float angle = (float)i * ScaleStepRad; - float cosa = ::cos(angle); - float sina = ::sin(angle); - float in_x = cosa * m_radius; - float in_y = sina * m_radius; - float in_z = 0.0f; - float out_x = (i % ScaleLongEvery == 0) ? cosa * out_radius_long : cosa * out_radius_short; - float out_y = (i % ScaleLongEvery == 0) ? sina * out_radius_long : sina * out_radius_short; - float out_z = 0.0f; - ::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z); - ::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z); - } - ::glEnd(); -} - -void GLGizmoRotate::render_snap_radii() const -{ - float step = 2.0f * (float)PI / (float)SnapRegionsCount; - - float in_radius = m_radius / 3.0f; - float out_radius = 2.0f * in_radius; - - ::glBegin(GL_LINES); - for (unsigned int i = 0; i < SnapRegionsCount; ++i) - { - float angle = (float)i * step; - float cosa = ::cos(angle); - float sina = ::sin(angle); - float in_x = cosa * in_radius; - float in_y = sina * in_radius; - float in_z = 0.0f; - float out_x = cosa * out_radius; - float out_y = sina * out_radius; - float out_z = 0.0f; - ::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z); - ::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z); - } - ::glEnd(); -} - -void GLGizmoRotate::render_reference_radius() const -{ - ::glBegin(GL_LINES); - ::glVertex3f(0.0f, 0.0f, 0.0f); - ::glVertex3f((GLfloat)(m_radius * (1.0f + GrabberOffset)), 0.0f, 0.0f); - ::glEnd(); -} - -void GLGizmoRotate::render_angle() const -{ - float step_angle = (float)m_angle / AngleResolution; - float ex_radius = m_radius * (1.0f + GrabberOffset); - - ::glBegin(GL_LINE_STRIP); - for (unsigned int i = 0; i <= AngleResolution; ++i) - { - float angle = (float)i * step_angle; - float x = ::cos(angle) * ex_radius; - float y = ::sin(angle) * ex_radius; - float z = 0.0f; - ::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z); - } - ::glEnd(); -} - -void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const -{ - double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset); - m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); - m_grabbers[0].angles(2) = m_angle; - - ::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color); - - ::glBegin(GL_LINES); - ::glVertex3f(0.0f, 0.0f, 0.0f); - ::glVertex3dv(m_grabbers[0].center.data()); - ::glEnd(); - - ::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float)); - render_grabbers(box); -} - -void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool picking) const -{ - if (m_quadric == nullptr) - return; - - double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size((float)box.max_size()) : (double)m_grabbers[0].get_half_size((float)box.max_size()); - - float color[3]; - ::memcpy((void*)color, (const void*)m_grabbers[0].color, 3 * sizeof(float)); - if (!picking && (m_hover_id != -1)) - { - color[0] = 1.0f - color[0]; - color[1] = 1.0f - color[1]; - color[2] = 1.0f - color[2]; - } - - if (!picking) - ::glEnable(GL_LIGHTING); - - ::glColor3fv(color); - ::glPushMatrix(); - ::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2)); - ::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0); - ::glRotated(90.0, 1.0, 0.0, 0.0); - ::glTranslated(0.0, 0.0, 2.0 * size); - ::gluQuadricOrientation(m_quadric, GLU_OUTSIDE); - ::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1); - ::gluQuadricOrientation(m_quadric, GLU_INSIDE); - ::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1); - ::glPopMatrix(); - ::glPushMatrix(); - ::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2)); - ::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0); - ::glRotated(-90.0, 1.0, 0.0, 0.0); - ::glTranslated(0.0, 0.0, 2.0 * size); - ::gluQuadricOrientation(m_quadric, GLU_OUTSIDE); - ::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1); - ::gluQuadricOrientation(m_quadric, GLU_INSIDE); - ::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1); - ::glPopMatrix(); - - if (!picking) - ::glDisable(GL_LIGHTING); -} - -void GLGizmoRotate::transform_to_local(const GLCanvas3D::Selection& selection) const -{ - ::glTranslated(m_center(0), m_center(1), m_center(2)); - - if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) - { - Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true); - ::glMultMatrixd(orient_matrix.data()); - } - - switch (m_axis) - { - case X: - { - ::glRotatef(90.0f, 0.0f, 1.0f, 0.0f); - ::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f); - break; - } - case Y: - { - ::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f); - ::glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); - break; - } - default: - case Z: - { - // no rotation - break; - } - } -} - -Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const -{ - double half_pi = 0.5 * (double)PI; - - Transform3d m = Transform3d::Identity(); - - switch (m_axis) - { - case X: - { - m.rotate(Eigen::AngleAxisd(half_pi, Vec3d::UnitZ())); - m.rotate(Eigen::AngleAxisd(-half_pi, Vec3d::UnitY())); - break; - } - case Y: - { - m.rotate(Eigen::AngleAxisd(half_pi, Vec3d::UnitY())); - m.rotate(Eigen::AngleAxisd(half_pi, Vec3d::UnitZ())); - break; - } - default: - case Z: - { - // no rotation applied - break; - } - } - - if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) - m = m * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true).inverse(); - - m.translate(-m_center); - - return transform(mouse_ray, m).intersect_plane(0.0); -} - -#if ENABLE_SVG_ICONS -GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) -#else -GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id) - : GLGizmoBase(parent, sprite_id) -#endif // ENABLE_SVG_ICONS -{ - m_gizmos.emplace_back(parent, GLGizmoRotate::X); - m_gizmos.emplace_back(parent, GLGizmoRotate::Y); - m_gizmos.emplace_back(parent, GLGizmoRotate::Z); - - for (unsigned int i = 0; i < 3; ++i) - { - m_gizmos[i].set_group_id(i); - } -} - -bool GLGizmoRotate3D::on_init() -{ - for (GLGizmoRotate& g : m_gizmos) - { - if (!g.init()) - return false; - } - - for (unsigned int i = 0; i < 3; ++i) - { - m_gizmos[i].set_highlight_color(AXES_COLOR[i]); - } - - m_shortcut_key = WXK_CONTROL_R; - - return true; -} - -std::string GLGizmoRotate3D::on_get_name() const -{ - return L("Rotate [R]"); -} - -void GLGizmoRotate3D::on_start_dragging(const GLCanvas3D::Selection& selection) -{ - if ((0 <= m_hover_id) && (m_hover_id < 3)) - m_gizmos[m_hover_id].start_dragging(selection); -} - -void GLGizmoRotate3D::on_stop_dragging() -{ - if ((0 <= m_hover_id) && (m_hover_id < 3)) - m_gizmos[m_hover_id].stop_dragging(); -} - -void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const -{ - ::glClear(GL_DEPTH_BUFFER_BIT); - - if ((m_hover_id == -1) || (m_hover_id == 0)) - m_gizmos[X].render(selection); - - if ((m_hover_id == -1) || (m_hover_id == 1)) - m_gizmos[Y].render(selection); - - if ((m_hover_id == -1) || (m_hover_id == 2)) - m_gizmos[Z].render(selection); -} - -#if ENABLE_IMGUI -void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) -{ -#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI - Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle())); - wxString label = _(L("Rotation (deg)")); - - m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - m_imgui->set_next_window_bg_alpha(0.5f); - m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); - m_imgui->input_vec3("", rotation, 100.0f, "%.2f"); - m_imgui->end(); -#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI -} -#endif // ENABLE_IMGUI - -const float GLGizmoScale3D::Offset = 5.0f; - -#if ENABLE_SVG_ICONS -GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) -#else -GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id) - : GLGizmoBase(parent, sprite_id) -#endif // ENABLE_SVG_ICONS - , m_scale(Vec3d::Ones()) - , m_snap_step(0.05) - , m_starting_scale(Vec3d::Ones()) -{ -} - -bool GLGizmoScale3D::on_init() -{ - for (int i = 0; i < 10; ++i) - { - m_grabbers.push_back(Grabber()); - } - - double half_pi = 0.5 * (double)PI; - - // x axis - m_grabbers[0].angles(1) = half_pi; - m_grabbers[1].angles(1) = half_pi; - - // y axis - m_grabbers[2].angles(0) = half_pi; - m_grabbers[3].angles(0) = half_pi; - - m_shortcut_key = WXK_CONTROL_S; - - return true; -} - -std::string GLGizmoScale3D::on_get_name() const -{ - return L("Scale [S]"); -} - -void GLGizmoScale3D::on_start_dragging(const GLCanvas3D::Selection& selection) -{ - if (m_hover_id != -1) - { - m_starting_drag_position = m_grabbers[m_hover_id].center; - m_starting_box = selection.get_bounding_box(); - } -} - -void GLGizmoScale3D::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) -{ - if ((m_hover_id == 0) || (m_hover_id == 1)) - do_scale_x(data); - else if ((m_hover_id == 2) || (m_hover_id == 3)) - do_scale_y(data); - else if ((m_hover_id == 4) || (m_hover_id == 5)) - do_scale_z(data); - else if (m_hover_id >= 6) - do_scale_uniform(data); -} - -void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const -{ - bool single_instance = selection.is_single_full_instance(); - bool single_volume = selection.is_single_modifier() || selection.is_single_volume(); - bool single_selection = single_instance || single_volume; - - Vec3f scale = 100.0f * Vec3f::Ones(); - if (single_instance) - scale = 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor().cast(); - else if (single_volume) - scale = 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_scaling_factor().cast(); - - if ((single_selection && ((m_hover_id == 0) || (m_hover_id == 1))) || m_grabbers[0].dragging || m_grabbers[1].dragging) - set_tooltip("X: " + format(scale(0), 4) + "%"); - else if (!m_grabbers[0].dragging && !m_grabbers[1].dragging && ((m_hover_id == 0) || (m_hover_id == 1))) - set_tooltip("X"); - else if ((single_selection && ((m_hover_id == 2) || (m_hover_id == 3))) || m_grabbers[2].dragging || m_grabbers[3].dragging) - set_tooltip("Y: " + format(scale(1), 4) + "%"); - else if (!m_grabbers[2].dragging && !m_grabbers[3].dragging && ((m_hover_id == 2) || (m_hover_id == 3))) - set_tooltip("Y"); - else if ((single_selection && ((m_hover_id == 4) || (m_hover_id == 5))) || m_grabbers[4].dragging || m_grabbers[5].dragging) - set_tooltip("Z: " + format(scale(2), 4) + "%"); - else if (!m_grabbers[4].dragging && !m_grabbers[5].dragging && ((m_hover_id == 4) || (m_hover_id == 5))) - set_tooltip("Z"); - else if ((single_selection && ((m_hover_id == 6) || (m_hover_id == 7) || (m_hover_id == 8) || (m_hover_id == 9))) - || m_grabbers[6].dragging || m_grabbers[7].dragging || m_grabbers[8].dragging || m_grabbers[9].dragging) - { - std::string tooltip = "X: " + format(scale(0), 4) + "%\n"; - tooltip += "Y: " + format(scale(1), 4) + "%\n"; - tooltip += "Z: " + format(scale(2), 4) + "%"; - set_tooltip(tooltip); - } - else if (!m_grabbers[6].dragging && !m_grabbers[7].dragging && !m_grabbers[8].dragging && !m_grabbers[9].dragging && - ((m_hover_id == 6) || (m_hover_id == 7) || (m_hover_id == 8) || (m_hover_id == 9))) - set_tooltip("X/Y/Z"); - - ::glClear(GL_DEPTH_BUFFER_BIT); - ::glEnable(GL_DEPTH_TEST); - - BoundingBoxf3 box; - Transform3d transform = Transform3d::Identity(); - Vec3d angles = Vec3d::Zero(); - Transform3d offsets_transform = Transform3d::Identity(); - - Vec3d grabber_size = Vec3d::Zero(); - - if (single_instance) - { - // calculate bounding box in instance local reference system - const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); - for (unsigned int idx : idxs) - { - const GLVolume* vol = selection.get_volume(idx); - box.merge(vol->bounding_box.transformed(vol->get_volume_transformation().get_matrix())); - } - - // gets transform from first selected volume - const GLVolume* v = selection.get_volume(*idxs.begin()); - transform = v->get_instance_transformation().get_matrix(); - // gets angles from first selected volume - angles = v->get_instance_rotation(); - // consider rotation+mirror only components of the transform for offsets - offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror()); - grabber_size = v->get_instance_transformation().get_matrix(true, true, false, true) * box.size(); - } - else if (single_volume) - { - const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin()); - box = v->bounding_box; - transform = v->world_matrix(); - angles = Geometry::extract_euler_angles(transform); - // consider rotation+mirror only components of the transform for offsets - offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror()); - grabber_size = v->get_volume_transformation().get_matrix(true, true, false, true) * box.size(); - } - else - { - box = selection.get_bounding_box(); - grabber_size = box.size(); - } - - m_box = box; - - const Vec3d& center = m_box.center(); - Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0); - Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0); - Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset); - - // x axis - m_grabbers[0].center = transform * Vec3d(m_box.min(0), center(1), center(2)) - offset_x; - m_grabbers[1].center = transform * Vec3d(m_box.max(0), center(1), center(2)) + offset_x; - ::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); - ::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); - - // y axis - m_grabbers[2].center = transform * Vec3d(center(0), m_box.min(1), center(2)) - offset_y; - m_grabbers[3].center = transform * Vec3d(center(0), m_box.max(1), center(2)) + offset_y; - ::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); - ::memcpy((void*)m_grabbers[3].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); - - // z axis - m_grabbers[4].center = transform * Vec3d(center(0), center(1), m_box.min(2)) - offset_z; - m_grabbers[5].center = transform * Vec3d(center(0), center(1), m_box.max(2)) + offset_z; - ::memcpy((void*)m_grabbers[4].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); - ::memcpy((void*)m_grabbers[5].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); - - // uniform - m_grabbers[6].center = transform * Vec3d(m_box.min(0), m_box.min(1), center(2)) - offset_x - offset_y; - m_grabbers[7].center = transform * Vec3d(m_box.max(0), m_box.min(1), center(2)) + offset_x - offset_y; - m_grabbers[8].center = transform * Vec3d(m_box.max(0), m_box.max(1), center(2)) + offset_x + offset_y; - m_grabbers[9].center = transform * Vec3d(m_box.min(0), m_box.max(1), center(2)) - offset_x + offset_y; - for (int i = 6; i < 10; ++i) - { - ::memcpy((void*)m_grabbers[i].color, (const void*)m_highlight_color, 3 * sizeof(float)); - } - - // sets grabbers orientation - for (int i = 0; i < 10; ++i) - { - m_grabbers[i].angles = angles; - } - - ::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f); - - float grabber_mean_size = (float)(grabber_size(0) + grabber_size(1) + grabber_size(2)) / 3.0f; - - if (m_hover_id == -1) - { - // draw connections - if (m_grabbers[0].enabled && m_grabbers[1].enabled) - { - ::glColor3fv(m_grabbers[0].color); - render_grabbers_connection(0, 1); - } - if (m_grabbers[2].enabled && m_grabbers[3].enabled) - { - ::glColor3fv(m_grabbers[2].color); - render_grabbers_connection(2, 3); - } - if (m_grabbers[4].enabled && m_grabbers[5].enabled) - { - ::glColor3fv(m_grabbers[4].color); - render_grabbers_connection(4, 5); - } - ::glColor3fv(m_base_color); - render_grabbers_connection(6, 7); - render_grabbers_connection(7, 8); - render_grabbers_connection(8, 9); - render_grabbers_connection(9, 6); - // draw grabbers - render_grabbers(grabber_mean_size); - } - else if ((m_hover_id == 0) || (m_hover_id == 1)) - { - // draw connection - ::glColor3fv(m_grabbers[0].color); - render_grabbers_connection(0, 1); - // draw grabbers - m_grabbers[0].render(true, grabber_mean_size); - m_grabbers[1].render(true, grabber_mean_size); - } - else if ((m_hover_id == 2) || (m_hover_id == 3)) - { - // draw connection - ::glColor3fv(m_grabbers[2].color); - render_grabbers_connection(2, 3); - // draw grabbers - m_grabbers[2].render(true, grabber_mean_size); - m_grabbers[3].render(true, grabber_mean_size); - } - else if ((m_hover_id == 4) || (m_hover_id == 5)) - { - // draw connection - ::glColor3fv(m_grabbers[4].color); - render_grabbers_connection(4, 5); - // draw grabbers - m_grabbers[4].render(true, grabber_mean_size); - m_grabbers[5].render(true, grabber_mean_size); - } - else if (m_hover_id >= 6) - { - // draw connection - ::glColor3fv(m_drag_color); - render_grabbers_connection(6, 7); - render_grabbers_connection(7, 8); - render_grabbers_connection(8, 9); - render_grabbers_connection(9, 6); - // draw grabbers - for (int i = 6; i < 10; ++i) - { - m_grabbers[i].render(true, grabber_mean_size); - } - } -} - -void GLGizmoScale3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const -{ - ::glDisable(GL_DEPTH_TEST); - - render_grabbers_for_picking(selection.get_bounding_box()); -} - -#if ENABLE_IMGUI -void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) -{ -#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI - bool single_instance = selection.is_single_full_instance(); - wxString label = _(L("Scale (%)")); - - m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - m_imgui->set_next_window_bg_alpha(0.5f); - m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); - m_imgui->input_vec3("", m_scale * 100.f, 100.0f, "%.2f"); - m_imgui->end(); -#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI -} -#endif // ENABLE_IMGUI - -void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2) const -{ - unsigned int grabbers_count = (unsigned int)m_grabbers.size(); - if ((id_1 < grabbers_count) && (id_2 < grabbers_count)) - { - ::glBegin(GL_LINES); - ::glVertex3dv(m_grabbers[id_1].center.data()); - ::glVertex3dv(m_grabbers[id_2].center.data()); - ::glEnd(); - } -} - -void GLGizmoScale3D::do_scale_x(const UpdateData& data) -{ - double ratio = calc_ratio(data); - if (ratio > 0.0) - m_scale(0) = m_starting_scale(0) * ratio; -} - -void GLGizmoScale3D::do_scale_y(const UpdateData& data) -{ - double ratio = calc_ratio(data); - if (ratio > 0.0) - m_scale(1) = m_starting_scale(1) * ratio; -} - -void GLGizmoScale3D::do_scale_z(const UpdateData& data) -{ - double ratio = calc_ratio(data); - if (ratio > 0.0) - m_scale(2) = m_starting_scale(2) * ratio; -} - -void GLGizmoScale3D::do_scale_uniform(const UpdateData& data) -{ - double ratio = calc_ratio(data); - if (ratio > 0.0) - m_scale = m_starting_scale * ratio; -} - -double GLGizmoScale3D::calc_ratio(const UpdateData& data) const -{ - double ratio = 0.0; - - // vector from the center to the starting position - Vec3d starting_vec = m_starting_drag_position - m_starting_box.center(); - double len_starting_vec = starting_vec.norm(); - if (len_starting_vec != 0.0) - { - Vec3d mouse_dir = data.mouse_ray.unit_vector(); - // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position - // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form - // in our case plane normal and ray direction are the same (orthogonal view) - // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal - Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; - // vector from the starting position to the found intersection - Vec3d inters_vec = inters - m_starting_drag_position; - - // finds projection of the vector along the staring direction - double proj = inters_vec.dot(starting_vec.normalized()); - - ratio = (len_starting_vec + proj) / len_starting_vec; - } - - if (data.shift_down) - ratio = m_snap_step * (double)std::round(ratio / m_snap_step); - - return ratio; -} - -const double GLGizmoMove3D::Offset = 10.0; - -#if ENABLE_SVG_ICONS -GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) -#else -GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id) - : GLGizmoBase(parent, sprite_id) -#endif // ENABLE_SVG_ICONS - , m_displacement(Vec3d::Zero()) - , m_snap_step(1.0) - , m_starting_drag_position(Vec3d::Zero()) - , m_starting_box_center(Vec3d::Zero()) - , m_starting_box_bottom_center(Vec3d::Zero()) - , m_quadric(nullptr) -{ - m_quadric = ::gluNewQuadric(); - if (m_quadric != nullptr) - ::gluQuadricDrawStyle(m_quadric, GLU_FILL); -} - -GLGizmoMove3D::~GLGizmoMove3D() -{ - if (m_quadric != nullptr) - ::gluDeleteQuadric(m_quadric); -} - -bool GLGizmoMove3D::on_init() -{ - for (int i = 0; i < 3; ++i) - { - m_grabbers.push_back(Grabber()); - } - - m_shortcut_key = WXK_CONTROL_M; - - return true; -} - -std::string GLGizmoMove3D::on_get_name() const -{ - return L("Move [M]"); -} - -void GLGizmoMove3D::on_start_dragging(const GLCanvas3D::Selection& selection) -{ - if (m_hover_id != -1) - { - m_displacement = Vec3d::Zero(); - const BoundingBoxf3& box = selection.get_bounding_box(); - m_starting_drag_position = m_grabbers[m_hover_id].center; - m_starting_box_center = box.center(); - m_starting_box_bottom_center = box.center(); - m_starting_box_bottom_center(2) = box.min(2); - } -} - -void GLGizmoMove3D::on_stop_dragging() -{ - m_displacement = Vec3d::Zero(); -} - -void GLGizmoMove3D::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) -{ - if (m_hover_id == 0) - m_displacement(0) = calc_projection(data); - else if (m_hover_id == 1) - m_displacement(1) = calc_projection(data); - else if (m_hover_id == 2) - m_displacement(2) = calc_projection(data); -} - -void GLGizmoMove3D::on_render(const GLCanvas3D::Selection& selection) const -{ - bool show_position = selection.is_single_full_instance(); - const Vec3d& position = selection.get_bounding_box().center(); - - if ((show_position && (m_hover_id == 0)) || m_grabbers[0].dragging) - set_tooltip("X: " + format(show_position ? position(0) : m_displacement(0), 2)); - else if (!m_grabbers[0].dragging && (m_hover_id == 0)) - set_tooltip("X"); - else if ((show_position && (m_hover_id == 1)) || m_grabbers[1].dragging) - set_tooltip("Y: " + format(show_position ? position(1) : m_displacement(1), 2)); - else if (!m_grabbers[1].dragging && (m_hover_id == 1)) - set_tooltip("Y"); - else if ((show_position && (m_hover_id == 2)) || m_grabbers[2].dragging) - set_tooltip("Z: " + format(show_position ? position(2) : m_displacement(2), 2)); - else if (!m_grabbers[2].dragging && (m_hover_id == 2)) - set_tooltip("Z"); - - ::glClear(GL_DEPTH_BUFFER_BIT); - ::glEnable(GL_DEPTH_TEST); - - const BoundingBoxf3& box = selection.get_bounding_box(); - const Vec3d& center = box.center(); - - // x axis - m_grabbers[0].center = Vec3d(box.max(0) + Offset, center(1), center(2)); - ::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); - - // y axis - m_grabbers[1].center = Vec3d(center(0), box.max(1) + Offset, center(2)); - ::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); - - // z axis - m_grabbers[2].center = Vec3d(center(0), center(1), box.max(2) + Offset); - ::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); - - ::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f); - - if (m_hover_id == -1) - { - // draw axes - for (unsigned int i = 0; i < 3; ++i) - { - if (m_grabbers[i].enabled) - { - ::glColor3fv(AXES_COLOR[i]); - ::glBegin(GL_LINES); - ::glVertex3dv(center.data()); - ::glVertex3dv(m_grabbers[i].center.data()); - ::glEnd(); - } - } - - // draw grabbers - render_grabbers(box); - for (unsigned int i = 0; i < 3; ++i) - { - if (m_grabbers[i].enabled) - render_grabber_extension((Axis)i, box, false); - } - } - else - { - // draw axis - ::glColor3fv(AXES_COLOR[m_hover_id]); - ::glBegin(GL_LINES); - ::glVertex3dv(center.data()); - ::glVertex3dv(m_grabbers[m_hover_id].center.data()); - ::glEnd(); - - // draw grabber - m_grabbers[m_hover_id].render(true, box.max_size()); - render_grabber_extension((Axis)m_hover_id, box, false); - } -} - -void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const -{ - ::glDisable(GL_DEPTH_TEST); - - const BoundingBoxf3& box = selection.get_bounding_box(); - render_grabbers_for_picking(box); - render_grabber_extension(X, box, true); - render_grabber_extension(Y, box, true); - render_grabber_extension(Z, box, true); -} - -#if ENABLE_IMGUI -void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) -{ -#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI - bool show_position = selection.is_single_full_instance(); - const Vec3d& position = selection.get_bounding_box().center(); - - Vec3d displacement = show_position ? position : m_displacement; - wxString label = show_position ? _(L("Position (mm)")) : _(L("Displacement (mm)")); - - m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - m_imgui->set_next_window_bg_alpha(0.5f); - m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); - m_imgui->input_vec3("", displacement, 100.0f, "%.2f"); - - m_imgui->end(); -#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI -} -#endif // ENABLE_IMGUI - -double GLGizmoMove3D::calc_projection(const UpdateData& data) const -{ - double projection = 0.0; - - Vec3d starting_vec = m_starting_drag_position - m_starting_box_center; - double len_starting_vec = starting_vec.norm(); - if (len_starting_vec != 0.0) - { - Vec3d mouse_dir = data.mouse_ray.unit_vector(); - // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position - // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form - // in our case plane normal and ray direction are the same (orthogonal view) - // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal - Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; - // vector from the starting position to the found intersection - Vec3d inters_vec = inters - m_starting_drag_position; - - // finds projection of the vector along the staring direction - projection = inters_vec.dot(starting_vec.normalized()); - } - - if (data.shift_down) - projection = m_snap_step * (double)std::round(projection / m_snap_step); - - return projection; -} - -void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const -{ - if (m_quadric == nullptr) - return; - - double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size((float)box.max_size()) : (double)m_grabbers[axis].get_half_size((float)box.max_size()); - - float color[3]; - ::memcpy((void*)color, (const void*)m_grabbers[axis].color, 3 * sizeof(float)); - if (!picking && (m_hover_id != -1)) - { - color[0] = 1.0f - color[0]; - color[1] = 1.0f - color[1]; - color[2] = 1.0f - color[2]; - } - - if (!picking) - ::glEnable(GL_LIGHTING); - - ::glColor3fv(color); - ::glPushMatrix(); - ::glTranslated(m_grabbers[axis].center(0), m_grabbers[axis].center(1), m_grabbers[axis].center(2)); - if (axis == X) - ::glRotated(90.0, 0.0, 1.0, 0.0); - else if (axis == Y) - ::glRotated(-90.0, 1.0, 0.0, 0.0); - - ::glTranslated(0.0, 0.0, 2.0 * size); - ::gluQuadricOrientation(m_quadric, GLU_OUTSIDE); - ::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1); - ::gluQuadricOrientation(m_quadric, GLU_INSIDE); - ::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1); - ::glPopMatrix(); - - if (!picking) - ::glDisable(GL_LIGHTING); -} - -#if ENABLE_SVG_ICONS -GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) -#else -GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id) - : GLGizmoBase(parent, sprite_id) -#endif // ENABLE_SVG_ICONS - , m_normal(Vec3d::Zero()) - , m_starting_center(Vec3d::Zero()) -{ -} - -bool GLGizmoFlatten::on_init() -{ - m_shortcut_key = WXK_CONTROL_F; - return true; -} - -std::string GLGizmoFlatten::on_get_name() const -{ - return L("Place on face [F]"); -} - -bool GLGizmoFlatten::on_is_activable(const GLCanvas3D::Selection& selection) const -{ - return selection.is_single_full_instance(); -} - -void GLGizmoFlatten::on_start_dragging(const GLCanvas3D::Selection& selection) -{ - if (m_hover_id != -1) - { - assert(m_planes_valid); - m_normal = m_planes[m_hover_id].normal; - m_starting_center = selection.get_bounding_box().center(); - } -} - -void GLGizmoFlatten::on_render(const GLCanvas3D::Selection& selection) const -{ - ::glClear(GL_DEPTH_BUFFER_BIT); - - ::glEnable(GL_DEPTH_TEST); - ::glEnable(GL_BLEND); - - if (selection.is_single_full_instance()) - { - const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); - ::glPushMatrix(); - ::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z()); - ::glMultMatrixd(m.data()); - if (this->is_plane_update_necessary()) - const_cast(this)->update_planes(); - for (int i = 0; i < (int)m_planes.size(); ++i) - { - if (i == m_hover_id) - ::glColor4f(0.9f, 0.9f, 0.9f, 0.75f); - else - ::glColor4f(0.9f, 0.9f, 0.9f, 0.5f); - - ::glBegin(GL_POLYGON); - for (const Vec3d& vertex : m_planes[i].vertices) - { - ::glVertex3dv(vertex.data()); - } - ::glEnd(); - } - ::glPopMatrix(); - } - - ::glEnable(GL_CULL_FACE); - ::glDisable(GL_BLEND); -} - -void GLGizmoFlatten::on_render_for_picking(const GLCanvas3D::Selection& selection) const -{ - ::glDisable(GL_DEPTH_TEST); - ::glDisable(GL_BLEND); - - if (selection.is_single_full_instance()) - { - const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); - ::glPushMatrix(); - ::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z()); - ::glMultMatrixd(m.data()); - if (this->is_plane_update_necessary()) - const_cast(this)->update_planes(); - for (int i = 0; i < (int)m_planes.size(); ++i) - { - ::glColor3fv(picking_color_component(i).data()); - ::glBegin(GL_POLYGON); - for (const Vec3d& vertex : m_planes[i].vertices) - { - ::glVertex3dv(vertex.data()); - } - ::glEnd(); - } - ::glPopMatrix(); - } - - ::glEnable(GL_CULL_FACE); -} - -void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) -{ - m_starting_center = Vec3d::Zero(); - if (m_model_object != model_object) { - m_planes.clear(); - m_planes_valid = false; - } - m_model_object = model_object; -} - -void GLGizmoFlatten::update_planes() -{ - TriangleMesh ch; - for (const ModelVolume* vol : m_model_object->volumes) - { - if (vol->type() != ModelVolumeType::MODEL_PART) - continue; - TriangleMesh vol_ch = vol->get_convex_hull(); - vol_ch.transform(vol->get_matrix()); - ch.merge(vol_ch); - } - ch = ch.convex_hull_3d(); - m_planes.clear(); - const Transform3d& inst_matrix = m_model_object->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) - const float minimal_side = 1.f; // mm - - // Now we'll go through all the facets and append Points of facets sharing the same normal. - // This part is still performed in mesh coordinate system. - const int num_of_facets = ch.stl.stats.number_of_facets; - std::vector facet_queue(num_of_facets, 0); - std::vector facet_visited(num_of_facets, false); - int facet_queue_cnt = 0; - const stl_normal* normal_ptr = nullptr; - while (1) { - // Find next unvisited triangle: - int facet_idx = 0; - for (; facet_idx < num_of_facets; ++ facet_idx) - if (!facet_visited[facet_idx]) { - facet_queue[facet_queue_cnt ++] = facet_idx; - facet_visited[facet_idx] = true; - normal_ptr = &ch.stl.facet_start[facet_idx].normal; - m_planes.emplace_back(); - break; - } - if (facet_idx == num_of_facets) - break; // Everything was visited already - - while (facet_queue_cnt > 0) { - int facet_idx = facet_queue[-- facet_queue_cnt]; - const stl_normal& this_normal = ch.stl.facet_start[facet_idx].normal; - if (std::abs(this_normal(0) - (*normal_ptr)(0)) < 0.001 && std::abs(this_normal(1) - (*normal_ptr)(1)) < 0.001 && std::abs(this_normal(2) - (*normal_ptr)(2)) < 0.001) { - stl_vertex* first_vertex = ch.stl.facet_start[facet_idx].vertex; - for (int j=0; j<3; ++j) - m_planes.back().vertices.emplace_back((double)first_vertex[j](0), (double)first_vertex[j](1), (double)first_vertex[j](2)); - - facet_visited[facet_idx] = true; - for (int j = 0; j < 3; ++ j) { - int neighbor_idx = ch.stl.neighbors_start[facet_idx].neighbor[j]; - if (! facet_visited[neighbor_idx]) - facet_queue[facet_queue_cnt ++] = neighbor_idx; - } - } - } - m_planes.back().normal = normal_ptr->cast(); - - // Now we'll transform all the points into world coordinates, so that the areas, angles and distances - // make real sense. - m_planes.back().vertices = transform(m_planes.back().vertices, inst_matrix); - - // if this is a just a very small triangle, remove it to speed up further calculations (it would be rejected later anyway): - if (m_planes.back().vertices.size() == 3 && - ((m_planes.back().vertices[0] - m_planes.back().vertices[1]).norm() < minimal_side - || (m_planes.back().vertices[0] - m_planes.back().vertices[2]).norm() < minimal_side - || (m_planes.back().vertices[1] - m_planes.back().vertices[2]).norm() < minimal_side)) - m_planes.pop_back(); - } - - // Let's prepare transformation of the normal vector from mesh to instance coordinates. - Geometry::Transformation t(inst_matrix); - Vec3d scaling = t.get_scaling_factor(); - t.set_scaling_factor(Vec3d(1./scaling(0), 1./scaling(1), 1./scaling(2))); - - // Now we'll go through all the polygons, transform the points into xy plane to process them: - for (unsigned int polygon_id=0; polygon_id < m_planes.size(); ++polygon_id) { - Pointf3s& polygon = m_planes[polygon_id].vertices; - const Vec3d& normal = m_planes[polygon_id].normal; - - // transform the normal according to the instance matrix: - Vec3d normal_transformed = t.get_matrix() * normal; - - // We are going to rotate about z and y to flatten the plane - Eigen::Quaterniond q; - Transform3d m = Transform3d::Identity(); - m.matrix().block(0, 0, 3, 3) = q.setFromTwoVectors(normal_transformed, Vec3d::UnitZ()).toRotationMatrix(); - polygon = transform(polygon, m); - - // Now to remove the inner points. We'll misuse Geometry::convex_hull for that, but since - // it works in fixed point representation, we will rescale the polygon to avoid overflows. - // And yes, it is a nasty thing to do. Whoever has time is free to refactor. - Vec3d bb_size = BoundingBoxf3(polygon).size(); - float sf = std::min(1./bb_size(0), 1./bb_size(1)); - Transform3d tr = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), Vec3d(sf, sf, 1.f)); - polygon = transform(polygon, tr); - polygon = Slic3r::Geometry::convex_hull(polygon); - polygon = transform(polygon, tr.inverse()); - - // Calculate area of the polygons and discard ones that are too small - float& area = m_planes[polygon_id].area; - area = 0.f; - for (unsigned int i = 0; i < polygon.size(); i++) // Shoelace formula - area += polygon[i](0)*polygon[i + 1 < polygon.size() ? i + 1 : 0](1) - polygon[i + 1 < polygon.size() ? i + 1 : 0](0)*polygon[i](1); - area = 0.5f * std::abs(area); - - bool discard = false; - if (area < minimal_area) - discard = true; - else { - // We also check the inner angles and discard polygons with angles smaller than the following threshold - const double angle_threshold = ::cos(10.0 * (double)PI / 180.0); - - for (unsigned int i = 0; i < polygon.size(); ++i) { - const Vec3d& prec = polygon[(i == 0) ? polygon.size() - 1 : i - 1]; - const Vec3d& curr = polygon[i]; - const Vec3d& next = polygon[(i == polygon.size() - 1) ? 0 : i + 1]; - - if ((prec - curr).normalized().dot((next - curr).normalized()) > angle_threshold) { - discard = true; - break; - } - } - } - - if (discard) { - m_planes.erase(m_planes.begin() + (polygon_id--)); - continue; - } - - // We will shrink the polygon a little bit so it does not touch the object edges: - Vec3d centroid = std::accumulate(polygon.begin(), polygon.end(), Vec3d(0.0, 0.0, 0.0)); - centroid /= (double)polygon.size(); - for (auto& vertex : polygon) - vertex = 0.9f*vertex + 0.1f*centroid; - - // Polygon is now simple and convex, we'll round the corners to make them look nicer. - // The algorithm takes a vertex, calculates middles of respective sides and moves the vertex - // towards their average (controlled by 'aggressivity'). This is repeated k times. - // In next iterations, the neighbours are not always taken at the middle (to increase the - // rounding effect at the corners, where we need it most). - const unsigned int k = 10; // number of iterations - const float aggressivity = 0.2f; // agressivity - const unsigned int N = polygon.size(); - std::vector> neighbours; - if (k != 0) { - Pointf3s points_out(2*k*N); // vector long enough to store the future vertices - for (unsigned int j=0; jvolumes) { - 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_planes_valid = true; -} - - -bool GLGizmoFlatten::is_plane_update_necessary() const -{ - if (m_state != On || !m_model_object || m_model_object->instances.empty()) - return false; - - if (! m_planes_valid || m_model_object->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)) - 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]) - return true; - - return false; -} - -Vec3d GLGizmoFlatten::get_flattening_normal() const -{ - Vec3d out = m_normal; - m_normal = Vec3d::Zero(); - m_starting_center = Vec3d::Zero(); - return out; -} - -#if ENABLE_SVG_ICONS -GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) -#else -GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id) - : GLGizmoBase(parent, sprite_id) -#endif // ENABLE_SVG_ICONS - , m_starting_center(Vec3d::Zero()), m_quadric(nullptr) -{ - m_quadric = ::gluNewQuadric(); - if (m_quadric != nullptr) - // using GLU_FILL does not work when the instance's transformation - // contains mirroring (normals are reverted) - ::gluQuadricDrawStyle(m_quadric, GLU_FILL); -} - -GLGizmoSlaSupports::~GLGizmoSlaSupports() -{ - if (m_quadric != nullptr) - ::gluDeleteQuadric(m_quadric); -} - -bool GLGizmoSlaSupports::on_init() -{ - m_shortcut_key = WXK_CONTROL_L; - return true; -} - -void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection) -{ - m_starting_center = Vec3d::Zero(); - m_old_model_object = m_model_object; - m_model_object = model_object; - if (selection.is_empty()) - m_old_instance_id = -1; - - m_active_instance = selection.get_instance_idx(); - - if (model_object && selection.is_from_single_instance()) - { - if (is_mesh_update_necessary()) { - update_mesh(); - editing_mode_reload_cache(); - } - - if (m_model_object != m_old_model_object) - m_editing_mode = false; - - if (m_editing_mode_cache.empty() && m_model_object->sla_points_status != sla::PointsStatus::UserModified) - get_data_from_backend(); - - if (m_state == On) { - m_parent.toggle_model_objects_visibility(false); - m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance); - } - } -} - -void GLGizmoSlaSupports::on_render(const GLCanvas3D::Selection& selection) const -{ - ::glEnable(GL_BLEND); - ::glEnable(GL_DEPTH_TEST); - - render_points(selection, false); - render_selection_rectangle(); - -#if !ENABLE_IMGUI - render_tooltip_texture(); -#endif // not ENABLE_IMGUI - - ::glDisable(GL_BLEND); -} - -void GLGizmoSlaSupports::render_selection_rectangle() const -{ - if (!m_selection_rectangle_active) - return; - - ::glLineWidth(1.5f); - float render_color[3] = {1.f, 0.f, 0.f}; - ::glColor3fv(render_color); - - ::glPushAttrib(GL_TRANSFORM_BIT); // remember current MatrixMode - - ::glMatrixMode(GL_MODELVIEW); // cache modelview matrix and set to identity - ::glPushMatrix(); - ::glLoadIdentity(); - - ::glMatrixMode(GL_PROJECTION); // cache projection matrix and set to identity - ::glPushMatrix(); - ::glLoadIdentity(); - - ::glOrtho(0.f, m_canvas_width, m_canvas_height, 0.f, -1.f, 1.f); // set projection matrix so that world coords = window coords - - // render the selection rectangle (window coordinates): - ::glPushAttrib(GL_ENABLE_BIT); - ::glLineStipple(4, 0xAAAA); - ::glEnable(GL_LINE_STIPPLE); - - ::glBegin(GL_LINE_LOOP); - ::glVertex3f((GLfloat)m_selection_rectangle_start_corner(0), (GLfloat)m_selection_rectangle_start_corner(1), (GLfloat)0.5f); - ::glVertex3f((GLfloat)m_selection_rectangle_end_corner(0), (GLfloat)m_selection_rectangle_start_corner(1), (GLfloat)0.5f); - ::glVertex3f((GLfloat)m_selection_rectangle_end_corner(0), (GLfloat)m_selection_rectangle_end_corner(1), (GLfloat)0.5f); - ::glVertex3f((GLfloat)m_selection_rectangle_start_corner(0), (GLfloat)m_selection_rectangle_end_corner(1), (GLfloat)0.5f); - ::glEnd(); - ::glPopAttrib(); - - ::glPopMatrix(); // restore former projection matrix - ::glMatrixMode(GL_MODELVIEW); - ::glPopMatrix(); // restore former modelview matrix - ::glPopAttrib(); // restore former MatrixMode -} - -void GLGizmoSlaSupports::on_render_for_picking(const GLCanvas3D::Selection& selection) const -{ - ::glEnable(GL_DEPTH_TEST); - - render_points(selection, true); -} - -void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, bool picking) const -{ - if (m_quadric == nullptr || !selection.is_from_single_instance()) - return; - - if (!picking) - ::glEnable(GL_LIGHTING); - - const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); - double z_shift = vol->get_sla_shift_z(); - const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); - const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); - - ::glPushMatrix(); - ::glTranslated(0.0, 0.0, z_shift); - ::glMultMatrixd(instance_matrix.data()); - - float render_color[3]; - for (int i = 0; i < (int)m_editing_mode_cache.size(); ++i) - { - const sla::SupportPoint& support_point = m_editing_mode_cache[i].support_point; - const bool& point_selected = m_editing_mode_cache[i].selected; - - // First decide about the color of the point. - if (picking) { - std::array color = picking_color_component(i); - render_color[0] = color[0]; - render_color[1] = color[1]; - render_color[2] = color[2]; - } - else { - if ((m_hover_id == i && m_editing_mode)) { // ignore hover state unless editing mode is active - render_color[0] = 0.f; - render_color[1] = 1.0f; - render_color[2] = 1.0f; - } - else { // neigher hover nor picking - bool supports_new_island = m_lock_unique_islands && m_editing_mode_cache[i].support_point.is_new_island; - if (m_editing_mode) { - render_color[0] = point_selected ? 1.0f : (supports_new_island ? 0.3f : 0.7f); - render_color[1] = point_selected ? 0.3f : (supports_new_island ? 0.3f : 0.7f); - render_color[2] = point_selected ? 0.3f : (supports_new_island ? 1.0f : 0.7f); - } - else - for (unsigned char i=0; i<3; ++i) render_color[i] = 0.5f; - } - } - ::glColor3fv(render_color); - float render_color_emissive[4] = { 0.5f * render_color[0], 0.5f * render_color[1], 0.5f * render_color[2], 1.f}; - ::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive); - - // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. - ::glPushMatrix(); - ::glTranslated(support_point.pos(0), support_point.pos(1), support_point.pos(2)); - ::glMultMatrixd(instance_scaling_matrix_inverse.data()); - - // Matrices set, we can render the point mark now. - // If in editing mode, we'll also render a cone pointing to the sphere. - if (m_editing_mode) { - if (m_editing_mode_cache[i].normal == Vec3f::Zero()) - update_cache_entry_normal(i); // in case the normal is not yet cached, find and cache it - - Eigen::Quaterniond q; - q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * m_editing_mode_cache[i].normal.cast()); - Eigen::AngleAxisd aa(q); - ::glRotated(aa.angle() * (180./M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)); - - const float cone_radius = 0.25f; // mm - const float cone_height = 0.75f; - ::glPushMatrix(); - ::glTranslatef(0.f, 0.f, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale); - ::gluCylinder(m_quadric, 0.f, cone_radius, cone_height, 36, 1); - ::glTranslatef(0.f, 0.f, cone_height); - ::gluDisk(m_quadric, 0.0, cone_radius, 36, 1); - ::glPopMatrix(); - } - ::gluSphere(m_quadric, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale, 64, 36); - ::glPopMatrix(); - } - - { - // Reset emissive component to zero (the default value) - float render_color_emissive[4] = { 0.f, 0.f, 0.f, 1.f }; - ::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive); - } - - if (!picking) - ::glDisable(GL_LIGHTING); - - ::glPopMatrix(); -} - -bool GLGizmoSlaSupports::is_mesh_update_necessary() const -{ - return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty()) - && ((m_model_object != m_old_model_object) || m_V.size()==0); - - //if (m_state != On || !m_model_object || m_model_object->instances.empty() || ! m_instance_matrix.isApprox(m_source_data.matrix)) - // return false; -} - -void GLGizmoSlaSupports::update_mesh() -{ - wxBusyCursor wait; - Eigen::MatrixXf& V = m_V; - Eigen::MatrixXi& F = m_F; - // Composite mesh of all instances in the world coordinate system. - // This mesh does not account for the possible Z up SLA offset. - TriangleMesh mesh = m_model_object->raw_mesh(); - const stl_file& stl = mesh.stl; - V.resize(3 * stl.stats.number_of_facets, 3); - F.resize(stl.stats.number_of_facets, 3); - for (unsigned int i=0; ivertex[0](0); V(3*i+0, 1) = facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2); - V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) = facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2); - V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) = facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2); - F(i, 0) = 3*i+0; - F(i, 1) = 3*i+1; - F(i, 2) = 3*i+2; - } - - m_AABB = igl::AABB(); - m_AABB.init(m_V, m_F); -} - -std::pair GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos) -{ - // if the gizmo doesn't have the V, F structures for igl, calculate them first: - if (m_V.size() == 0) - update_mesh(); - - Eigen::Matrix viewport; - ::glGetIntegerv(GL_VIEWPORT, viewport.data()); - Eigen::Matrix modelview_matrix; - ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data()); - Eigen::Matrix projection_matrix; - ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix.data()); - - Vec3d point1; - Vec3d point2; - ::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 0.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point1(0), &point1(1), &point1(2)); - ::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 1.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point2(0), &point2(1), &point2(2)); - - igl::Hit hit; - - const GLCanvas3D::Selection& selection = m_parent.get_selection(); - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - double z_offset = volume->get_sla_shift_z(); - - point1(2) -= z_offset; - point2(2) -= z_offset; - - Transform3d inv = volume->get_instance_transformation().get_matrix().inverse(); - - point1 = inv * point1; - point2 = inv * point2; - - if (!m_AABB.intersect_ray(m_V, m_F, point1.cast(), (point2-point1).cast(), hit)) - throw std::invalid_argument("unproject_on_mesh(): No intersection found."); - - int fid = hit.id; // facet id - Vec3f bc(1-hit.u-hit.v, hit.u, hit.v); // barycentric coordinates of the hit - Vec3f a = (m_V.row(m_F(fid, 1)) - m_V.row(m_F(fid, 0))); - Vec3f b = (m_V.row(m_F(fid, 2)) - m_V.row(m_F(fid, 0))); - - // Calculate and return both the point and the facet normal. - return std::make_pair( - bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2)), - a.cross(b) - ); -} - -// Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event. -// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is -// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo -// concludes that the event was not intended for it, it should return false. -bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down) -{ - if (m_editing_mode) { - - // left down - show the selection rectangle: - if (action == SLAGizmoEventType::LeftDown && shift_down) { - if (m_hover_id == -1) { - m_selection_rectangle_active = true; - m_selection_rectangle_start_corner = mouse_position; - m_selection_rectangle_end_corner = mouse_position; - m_canvas_width = m_parent.get_canvas_size().get_width(); - m_canvas_height = m_parent.get_canvas_size().get_height(); - } - else - select_point(m_hover_id); - - return true; - } - - // dragging the selection rectangle: - if (action == SLAGizmoEventType::Dragging && m_selection_rectangle_active) { - m_selection_rectangle_end_corner = mouse_position; - return true; - } - - // mouse up without selection rectangle - place point on the mesh: - if (action == SLAGizmoEventType::LeftUp && !m_selection_rectangle_active && !shift_down) { - if (m_ignore_up_event) { - m_ignore_up_event = false; - return false; - } - - int instance_id = m_parent.get_selection().get_instance_idx(); - if (m_old_instance_id != instance_id) - { - bool something_selected = (m_old_instance_id != -1); - m_old_instance_id = instance_id; - if (something_selected) - return false; - } - if (instance_id == -1) - return false; - - // If there is some selection, don't add new point and deselect everything instead. - if (m_selection_empty) { - try { - std::pair pos_and_normal = unproject_on_mesh(mouse_position); // don't create anything if this throws - m_editing_mode_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second); - m_unsaved_changes = true; - } - catch (...) { // not clicked on object - return true; // prevents deselection of the gizmo by GLCanvas3D - } - } - else - select_point(NoPoints); - - return true; - } - - // left up with selection rectangle - select points inside the rectangle: - if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp) - && m_selection_rectangle_active) { - if (action == SLAGizmoEventType::ShiftUp) - m_ignore_up_event = true; - const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix(); - GLint viewport[4]; - ::glGetIntegerv(GL_VIEWPORT, viewport); - GLdouble modelview_matrix[16]; - ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix); - GLdouble projection_matrix[16]; - ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix); - - const GLCanvas3D::Selection& selection = m_parent.get_selection(); - const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); - double z_offset = volume->get_sla_shift_z(); - - // bounding box created from the rectangle corners - will take care of order of the corners - BoundingBox rectangle(Points{Point(m_selection_rectangle_start_corner.cast()), Point(m_selection_rectangle_end_corner.cast())}); - - const Transform3d& instance_matrix_no_translation = volume->get_instance_transformation().get_matrix(true); - // we'll recover current look direction from the modelview matrix (in world coords)... - Vec3f direction_to_camera(modelview_matrix[2], modelview_matrix[6], modelview_matrix[10]); - // ...and transform it to model coords. - direction_to_camera = (instance_matrix_no_translation.inverse().cast() * direction_to_camera).normalized().eval(); - - // Iterate over all points, check if they're in the rectangle and if so, check that they are not obscured by the mesh: - for (unsigned int i=0; i() * support_point.pos; - pos(2) += z_offset; - GLdouble out_x, out_y, out_z; - ::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z); - out_y = m_canvas_height - out_y; - - if (rectangle.contains(Point(out_x, out_y))) { - bool is_obscured = false; - // Cast a ray in the direction of the camera and look for intersection with the mesh: - std::vector hits; - // Offset the start of the ray to the front of the ball + EPSILON to account for numerical inaccuracies. - if (m_AABB.intersect_ray(m_V, m_F, support_point.pos + direction_to_camera * (support_point.head_front_radius + EPSILON), direction_to_camera, hits)) - // FIXME: the intersection could in theory be behind the camera, but as of now we only have camera direction. - // Also, the threshold is in mesh coordinates, not in actual dimensions. - if (hits.size() > 1 || hits.front().t > 0.001f) - is_obscured = true; - - if (!is_obscured) - select_point(i); - } - } - m_selection_rectangle_active = false; - return true; - } - - if (action == SLAGizmoEventType::Delete) { - // delete key pressed - delete_selected_points(); - return true; - } - - if (action == SLAGizmoEventType::ApplyChanges) { - editing_mode_apply_changes(); - return true; - } - - if (action == SLAGizmoEventType::DiscardChanges) { - editing_mode_discard_changes(); - return true; - } - - if (action == SLAGizmoEventType::RightDown) { - if (m_hover_id != -1) { - select_point(NoPoints); - select_point(m_hover_id); - delete_selected_points(); - return true; - } - return false; - } - - if (action == SLAGizmoEventType::SelectAll) { - select_point(AllPoints); - return true; - } - } - - if (!m_editing_mode) { - if (action == SLAGizmoEventType::AutomaticGeneration) { - auto_generate(); - return true; - } - - if (action == SLAGizmoEventType::ManualEditing) { - switch_to_editing_mode(); - return true; - } - } - - return false; -} - -void GLGizmoSlaSupports::delete_selected_points(bool force) -{ - for (unsigned int idx=0; idxreslice_SLA_supports(*m_model_object); - } - - select_point(NoPoints); - - //m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); -} - -void GLGizmoSlaSupports::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) -{ - if (m_editing_mode && m_hover_id != -1 && data.mouse_pos && (!m_editing_mode_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) { - std::pair pos_and_normal; - try { - pos_and_normal = unproject_on_mesh(Vec2d((*data.mouse_pos)(0), (*data.mouse_pos)(1))); - } - catch (...) { return; } - m_editing_mode_cache[m_hover_id].support_point.pos = pos_and_normal.first; - m_editing_mode_cache[m_hover_id].support_point.is_new_island = false; - m_editing_mode_cache[m_hover_id].normal = pos_and_normal.second; - m_unsaved_changes = true; - // Do not update immediately, wait until the mouse is released. - // m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); - } -} - -#if !ENABLE_IMGUI -void GLGizmoSlaSupports::render_tooltip_texture() const { - if (m_tooltip_texture.get_id() == 0) - if (!m_tooltip_texture.load_from_file(resources_dir() + "/icons/sla_support_points_tooltip.png", false)) - return; - if (m_reset_texture.get_id() == 0) - if (!m_reset_texture.load_from_file(resources_dir() + "/icons/sla_support_points_reset.png", false)) - return; - - float zoom = m_parent.get_camera_zoom(); - float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; - float gap = 30.0f * inv_zoom; - - const Size& cnv_size = m_parent.get_canvas_size(); - float l = gap - cnv_size.get_width()/2.f * inv_zoom; - float r = l + (float)m_tooltip_texture.get_width() * inv_zoom; - float b = gap - cnv_size.get_height()/2.f * inv_zoom; - float t = b + (float)m_tooltip_texture.get_height() * inv_zoom; - - Rect reset_rect = m_parent.get_gizmo_reset_rect(m_parent, true); - - ::glDisable(GL_DEPTH_TEST); - ::glPushMatrix(); - ::glLoadIdentity(); - GLTexture::render_texture(m_tooltip_texture.get_id(), l, r, b, t); - GLTexture::render_texture(m_reset_texture.get_id(), reset_rect.get_left(), reset_rect.get_right(), reset_rect.get_bottom(), reset_rect.get_top()); - ::glPopMatrix(); - ::glEnable(GL_DEPTH_TEST); -} -#endif // not ENABLE_IMGUI - - -std::vector GLGizmoSlaSupports::get_config_options(const std::vector& keys) const -{ - std::vector out; - - if (!m_model_object) - return out; - - const DynamicPrintConfig& object_cfg = m_model_object->config; - const DynamicPrintConfig& print_cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config; - std::unique_ptr default_cfg = nullptr; - - for (const std::string& key : keys) { - if (object_cfg.has(key)) - out.push_back(object_cfg.option(key)); - else - if (print_cfg.has(key)) - out.push_back(print_cfg.option(key)); - else { // we must get it from defaults - if (default_cfg == nullptr) - default_cfg.reset(DynamicPrintConfig::new_from_defaults_keys(keys)); - out.push_back(default_cfg->option(key)); - } - } - - return out; -} - - -void GLGizmoSlaSupports::update_cache_entry_normal(unsigned int i) const -{ - int idx = 0; - Eigen::Matrix pp = m_editing_mode_cache[i].support_point.pos; - Eigen::Matrix cc; - m_AABB.squared_distance(m_V, m_F, pp, idx, cc); - Vec3f a = (m_V.row(m_F(idx, 1)) - m_V.row(m_F(idx, 0))); - Vec3f b = (m_V.row(m_F(idx, 2)) - m_V.row(m_F(idx, 0))); - m_editing_mode_cache[i].normal = a.cross(b); -} - - - -#if ENABLE_IMGUI -void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) -{ - if (!m_model_object) - return; - - bool first_run = true; // This is a hack to redraw the button when all points are removed, - // so it is not delayed until the background process finishes. -RENDER_AGAIN: - m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - - const float scaling = m_imgui->get_style_scaling(); - const ImVec2 window_size(285.f * scaling, 300.f * scaling); - ImGui::SetNextWindowPos(ImVec2(x, y - std::max(0.f, y+window_size.y-bottom_limit) )); - ImGui::SetNextWindowSize(ImVec2(window_size)); - - m_imgui->set_next_window_bg_alpha(0.5f); - m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); - - ImGui::PushItemWidth(100.0f); - - bool force_refresh = false; - bool remove_selected = false; - bool remove_all = false; - - if (m_editing_mode) { - m_imgui->text(_(L("Left mouse click - add point"))); - m_imgui->text(_(L("Right mouse click - remove point"))); - m_imgui->text(_(L("Shift + Left (+ drag) - select point(s)"))); - m_imgui->text(" "); // vertical gap - - float diameter_upper_cap = static_cast(wxGetApp().preset_bundle->sla_prints.get_edited_preset().config.option("support_pillar_diameter"))->value; - if (m_new_point_head_diameter > diameter_upper_cap) - m_new_point_head_diameter = diameter_upper_cap; - - m_imgui->text(_(L("Head diameter: "))); - ImGui::SameLine(); - if (ImGui::SliderFloat("", &m_new_point_head_diameter, 0.1f, diameter_upper_cap, "%.1f")) { - // value was changed - for (auto& cache_entry : m_editing_mode_cache) - if (cache_entry.selected) { - cache_entry.support_point.head_front_radius = m_new_point_head_diameter / 2.f; - m_unsaved_changes = true; - } - } - - bool changed = m_lock_unique_islands; - m_imgui->checkbox(_(L("Lock supports under new islands")), m_lock_unique_islands); - force_refresh |= changed != m_lock_unique_islands; - - m_imgui->disabled_begin(m_selection_empty); - remove_selected = m_imgui->button(_(L("Remove selected points"))); - m_imgui->disabled_end(); - - m_imgui->disabled_begin(m_editing_mode_cache.empty()); - remove_all = m_imgui->button(_(L("Remove all points"))); - m_imgui->disabled_end(); - - m_imgui->text(" "); // vertical gap - - if (m_imgui->button(_(L("Apply changes")))) { - editing_mode_apply_changes(); - force_refresh = true; - } - ImGui::SameLine(); - bool discard_changes = m_imgui->button(_(L("Discard changes"))); - if (discard_changes) { - editing_mode_discard_changes(); - force_refresh = true; - } - } - else { // not in editing mode: - ImGui::PushItemWidth(100.0f); - m_imgui->text(_(L("Minimal points distance: "))); - ImGui::SameLine(); - - std::vector opts = get_config_options({"support_points_density_relative", "support_points_minimal_distance"}); - float density = static_cast(opts[0])->value; - float minimal_point_distance = static_cast(opts[1])->value; - - bool value_changed = ImGui::SliderFloat("", &minimal_point_distance, 0.f, 20.f, "%.f mm"); - if (value_changed) - m_model_object->config.opt("support_points_minimal_distance", true)->value = minimal_point_distance; - - m_imgui->text(_(L("Support points density: "))); - ImGui::SameLine(); - if (ImGui::SliderFloat(" ", &density, 0.f, 200.f, "%.f %%")) { - value_changed = true; - m_model_object->config.opt("support_points_density_relative", true)->value = (int)density; - } - - if (value_changed) { // Update side panel - wxTheApp->CallAfter([]() { - wxGetApp().obj_settings()->UpdateAndShow(true); - wxGetApp().obj_list()->update_settings_items(); - }); - } - - bool generate = m_imgui->button(_(L("Auto-generate points [A]"))); - - if (generate) - auto_generate(); - - m_imgui->text(""); - if (m_imgui->button(_(L("Manual editing [M]")))) - switch_to_editing_mode(); - - m_imgui->disabled_begin(m_editing_mode_cache.empty()); - remove_all = m_imgui->button(_(L("Remove all points"))); - m_imgui->disabled_end(); - - m_imgui->text(""); - - m_imgui->text(m_model_object->sla_points_status == sla::PointsStatus::None ? "No points (will be autogenerated)" : - (m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated ? "Autogenerated points (no modifications)" : - (m_model_object->sla_points_status == sla::PointsStatus::UserModified ? "User-modified points" : - (m_model_object->sla_points_status == sla::PointsStatus::Generating ? "Generation in progress..." : "UNKNOWN STATUS")))); - } - - m_imgui->end(); - - if (m_editing_mode != m_old_editing_state) { // user toggled between editing/non-editing mode - m_parent.toggle_sla_auxiliaries_visibility(!m_editing_mode); - force_refresh = true; - } - m_old_editing_state = m_editing_mode; - - if (remove_selected || remove_all) { - force_refresh = false; - m_parent.set_as_dirty(); - if (remove_all) - select_point(AllPoints); - delete_selected_points(remove_all); - if (remove_all && !m_editing_mode) - editing_mode_apply_changes(); - if (first_run) { - first_run = false; - goto RENDER_AGAIN; - } - } - - if (force_refresh) - m_parent.set_as_dirty(); -} -#endif // ENABLE_IMGUI - -bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const -{ - if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA - || !selection.is_from_single_instance()) - return false; - - // Check that none of the selected volumes is outside. - const GLCanvas3D::Selection::IndicesList& list = selection.get_volume_idxs(); - for (const auto& idx : list) - if (selection.get_volume(idx)->is_outside) - return false; - - return true; -} - -bool GLGizmoSlaSupports::on_is_selectable() const -{ - return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA); -} - -std::string GLGizmoSlaSupports::on_get_name() const -{ - return L("SLA Support Points [L]"); -} - -void GLGizmoSlaSupports::on_set_state() -{ - if (m_state == On && m_old_state != On) { // the gizmo was just turned on - if (is_mesh_update_necessary()) - update_mesh(); - - // we'll now reload support points: - if (m_model_object) - editing_mode_reload_cache(); - - m_parent.toggle_model_objects_visibility(false); - if (m_model_object) - m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance); - - // Set default head diameter from config. - const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config; - m_new_point_head_diameter = static_cast(cfg.option("support_head_front_diameter"))->value; - } - if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off - if (m_model_object) { - if (m_unsaved_changes) { - wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")), - _(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO); - if (dlg.ShowModal() == wxID_YES) - editing_mode_apply_changes(); - else - editing_mode_discard_changes(); - } - } - - m_parent.toggle_model_objects_visibility(true); - m_editing_mode = false; // so it is not active next time the gizmo opens - m_editing_mode_cache.clear(); - } - m_old_state = m_state; -} - - - -void GLGizmoSlaSupports::on_start_dragging(const GLCanvas3D::Selection& selection) -{ - if (m_hover_id != -1) { - select_point(NoPoints); - select_point(m_hover_id); - } -} - - - -void GLGizmoSlaSupports::select_point(int i) -{ - if (i == AllPoints || i == NoPoints) { - for (auto& point_and_selection : m_editing_mode_cache) - point_and_selection.selected = ( i == AllPoints ); - m_selection_empty = (i == NoPoints); - - if (i == AllPoints) - m_new_point_head_diameter = m_editing_mode_cache[0].support_point.head_front_radius * 2.f; - } - else { - m_editing_mode_cache[i].selected = true; - m_selection_empty = false; - m_new_point_head_diameter = m_editing_mode_cache[i].support_point.head_front_radius * 2.f; - } -} - - - -void GLGizmoSlaSupports::editing_mode_discard_changes() -{ - m_editing_mode_cache.clear(); - for (const sla::SupportPoint& point : m_model_object->sla_support_points) - m_editing_mode_cache.emplace_back(point, false); - m_editing_mode = false; - m_unsaved_changes = false; -} - - - -void GLGizmoSlaSupports::editing_mode_apply_changes() -{ - // If there are no changes, don't touch the front-end. The data in the cache could have been - // taken from the backend and copying them to ModelObject would needlessly invalidate them. - if (m_unsaved_changes) { - m_model_object->sla_points_status = sla::PointsStatus::UserModified; - m_model_object->sla_support_points.clear(); - for (const CacheEntry& cache_entry : m_editing_mode_cache) - m_model_object->sla_support_points.push_back(cache_entry.support_point); - - // Recalculate support structures once the editing mode is left. - // m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); - // m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); - wxGetApp().plater()->reslice_SLA_supports(*m_model_object); - } - m_editing_mode = false; - m_unsaved_changes = false; -} - - - -void GLGizmoSlaSupports::editing_mode_reload_cache() -{ - m_editing_mode_cache.clear(); - for (const sla::SupportPoint& point : m_model_object->sla_support_points) - m_editing_mode_cache.emplace_back(point, false); - - m_unsaved_changes = false; -} - - - -void GLGizmoSlaSupports::get_data_from_backend() -{ - for (const SLAPrintObject* po : m_parent.sla_print()->objects()) { - if (po->model_object()->id() == m_model_object->id() && po->is_step_done(slaposSupportPoints)) { - m_editing_mode_cache.clear(); - const std::vector& points = po->get_support_points(); - auto mat = po->trafo().inverse().cast(); - for (unsigned int i=0; isla_points_status != sla::PointsStatus::UserModified) - m_model_object->sla_points_status = sla::PointsStatus::AutoGenerated; - - break; - } - } - m_unsaved_changes = false; - - // We don't copy the data into ModelObject, as this would stop the background processing. -} - - - -void GLGizmoSlaSupports::auto_generate() -{ - wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L( - "Autogeneration will erase all manually edited points.\n\n" - "Are you sure you want to do it?\n" - )), _(L("Warning")), wxICON_WARNING | wxYES | wxNO); - - if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || m_editing_mode_cache.empty() || dlg.ShowModal() == wxID_YES) { - m_model_object->sla_support_points.clear(); - m_model_object->sla_points_status = sla::PointsStatus::Generating; - m_editing_mode_cache.clear(); - wxGetApp().plater()->reslice_SLA_supports(*m_model_object); - } -} - - - -void GLGizmoSlaSupports::switch_to_editing_mode() -{ - if (m_model_object->sla_points_status != sla::PointsStatus::AutoGenerated) - editing_mode_reload_cache(); - m_unsaved_changes = false; - m_editing_mode = true; -} - - - - - - -// GLGizmoCut - -class GLGizmoCutPanel : public wxPanel -{ -public: - GLGizmoCutPanel(wxWindow *parent); - - void display(bool display); -private: - bool m_active; - wxCheckBox *m_cb_rotate; - wxButton *m_btn_cut; - wxButton *m_btn_cancel; -}; - -GLGizmoCutPanel::GLGizmoCutPanel(wxWindow *parent) - : wxPanel(parent) - , m_active(false) - , m_cb_rotate(new wxCheckBox(this, wxID_ANY, _(L("Rotate lower part upwards")))) - , m_btn_cut(new wxButton(this, wxID_OK, _(L("Perform cut")))) - , m_btn_cancel(new wxButton(this, wxID_CANCEL, _(L("Cancel")))) -{ - enum { MARGIN = 5 }; - - auto *sizer = new wxBoxSizer(wxHORIZONTAL); - - auto *label = new wxStaticText(this, wxID_ANY, _(L("Cut object:"))); - sizer->Add(label, 0, wxALL | wxALIGN_CENTER, MARGIN); - sizer->Add(m_cb_rotate, 0, wxALL | wxALIGN_CENTER, MARGIN); - sizer->AddStretchSpacer(); - sizer->Add(m_btn_cut, 0, wxALL | wxALIGN_CENTER, MARGIN); - sizer->Add(m_btn_cancel, 0, wxALL | wxALIGN_CENTER, MARGIN); - - SetSizer(sizer); -} - -void GLGizmoCutPanel::display(bool display) -{ - Show(display); - GetParent()->Layout(); -} - - -const double GLGizmoCut::Offset = 10.0; -const double GLGizmoCut::Margin = 20.0; -const std::array GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0 }; - -#if ENABLE_SVG_ICONS -GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) - : GLGizmoBase(parent, icon_filename, sprite_id) -#else -GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id) - : GLGizmoBase(parent, sprite_id) -#endif // ENABLE_SVG_ICONS - , m_cut_z(0.0) - , m_max_z(0.0) -#if !ENABLE_IMGUI - , m_panel(nullptr) -#endif // not ENABLE_IMGUI - , m_keep_upper(true) - , m_keep_lower(true) - , m_rotate_lower(false) -{} - -#if !ENABLE_IMGUI -void GLGizmoCut::create_external_gizmo_widgets(wxWindow *parent) -{ - wxASSERT(m_panel == nullptr); - - m_panel = new GLGizmoCutPanel(parent); - parent->GetSizer()->Add(m_panel, 0, wxEXPAND); - - parent->Layout(); - parent->Fit(); - auto prev_heigh = parent->GetMinSize().GetHeight(); - parent->SetMinSize(wxSize(-1, std::max(prev_heigh, m_panel->GetSize().GetHeight()))); - - m_panel->Hide(); - m_panel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { - perform_cut(m_parent.get_selection()); - }, wxID_OK); -} -#endif // not ENABLE_IMGUI - -bool GLGizmoCut::on_init() -{ - m_grabbers.emplace_back(); - m_shortcut_key = WXK_CONTROL_C; - return true; -} - -std::string GLGizmoCut::on_get_name() const -{ - return L("Cut [C]"); -} - -void GLGizmoCut::on_set_state() -{ - // Reset m_cut_z on gizmo activation - if (get_state() == On) { - m_cut_z = m_parent.get_selection().get_bounding_box().size()(2) / 2.0; - } - -#if !ENABLE_IMGUI - // Display or hide the extra panel - if (m_panel != nullptr) { - m_panel->display(get_state() == On); - } -#endif // not ENABLE_IMGUI -} - -bool GLGizmoCut::on_is_activable(const GLCanvas3D::Selection& selection) const -{ - return selection.is_single_full_instance() && !selection.is_wipe_tower(); -} - -void GLGizmoCut::on_start_dragging(const GLCanvas3D::Selection& selection) -{ - if (m_hover_id == -1) { return; } - - const BoundingBoxf3& box = selection.get_bounding_box(); - m_start_z = m_cut_z; - update_max_z(selection); - m_drag_pos = m_grabbers[m_hover_id].center; - m_drag_center = box.center(); - m_drag_center(2) = m_cut_z; -} - -void GLGizmoCut::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) -{ - if (m_hover_id != -1) { - set_cut_z(m_start_z + calc_projection(data.mouse_ray)); - } -} - -void GLGizmoCut::on_render(const GLCanvas3D::Selection& selection) const -{ - if (m_grabbers[0].dragging) { - set_tooltip("Z: " + format(m_cut_z, 2)); - } - - update_max_z(selection); - - const BoundingBoxf3& box = selection.get_bounding_box(); - Vec3d plane_center = box.center(); - plane_center(2) = m_cut_z; - - const float min_x = box.min(0) - Margin; - const float max_x = box.max(0) + Margin; - const float min_y = box.min(1) - Margin; - const float max_y = box.max(1) + Margin; - ::glEnable(GL_DEPTH_TEST); - ::glDisable(GL_CULL_FACE); - ::glEnable(GL_BLEND); - ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // Draw the cutting plane - ::glBegin(GL_QUADS); - ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); - ::glVertex3f(min_x, min_y, plane_center(2)); - ::glVertex3f(max_x, min_y, plane_center(2)); - ::glVertex3f(max_x, max_y, plane_center(2)); - ::glVertex3f(min_x, max_y, plane_center(2)); - ::glEnd(); - - ::glEnable(GL_CULL_FACE); - ::glDisable(GL_BLEND); - - // TODO: draw cut part contour? - - // Draw the grabber and the connecting line - m_grabbers[0].center = plane_center; - m_grabbers[0].center(2) = plane_center(2) + Offset; - - ::glDisable(GL_DEPTH_TEST); - ::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f); - ::glColor3f(1.0, 1.0, 0.0); - ::glBegin(GL_LINES); - ::glVertex3dv(plane_center.data()); - ::glVertex3dv(m_grabbers[0].center.data()); - ::glEnd(); - - std::copy(std::begin(GrabberColor), std::end(GrabberColor), m_grabbers[0].color); - m_grabbers[0].render(m_hover_id == 0, box.max_size()); -} - -void GLGizmoCut::on_render_for_picking(const GLCanvas3D::Selection& selection) const -{ - ::glDisable(GL_DEPTH_TEST); - - render_grabbers_for_picking(selection.get_bounding_box()); -} - -#if ENABLE_IMGUI -void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) -{ - m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); - m_imgui->set_next_window_bg_alpha(0.5f); - m_imgui->begin(_(L("Cut")), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); - - ImGui::PushItemWidth(100.0f); - bool _value_changed = ImGui::InputDouble("Z", &m_cut_z, 0.0f, 0.0f, "%.2f"); - - m_imgui->checkbox(_(L("Keep upper part")), m_keep_upper); - m_imgui->checkbox(_(L("Keep lower part")), m_keep_lower); - m_imgui->checkbox(_(L("Rotate lower part upwards")), m_rotate_lower); - - m_imgui->disabled_begin(!m_keep_upper && !m_keep_lower); - const bool cut_clicked = m_imgui->button(_(L("Perform cut"))); - m_imgui->disabled_end(); - - m_imgui->end(); - - if (cut_clicked && (m_keep_upper || m_keep_lower)) { - perform_cut(selection); - } -} -#endif // ENABLE_IMGUI - -void GLGizmoCut::update_max_z(const GLCanvas3D::Selection& selection) const -{ - m_max_z = selection.get_bounding_box().size()(2); - set_cut_z(m_cut_z); -} - -void GLGizmoCut::set_cut_z(double cut_z) const -{ - // Clamp the plane to the object's bounding box - m_cut_z = std::max(0.0, std::min(m_max_z, cut_z)); -} - -void GLGizmoCut::perform_cut(const GLCanvas3D::Selection& selection) -{ - const auto instance_idx = selection.get_instance_idx(); - const auto object_idx = selection.get_object_idx(); - - wxCHECK_RET(instance_idx >= 0 && object_idx >= 0, "GLGizmoCut: Invalid object selection"); - - wxGetApp().plater()->cut(object_idx, instance_idx, m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); -} - -double GLGizmoCut::calc_projection(const Linef3& mouse_ray) const -{ - double projection = 0.0; - - const Vec3d starting_vec = m_drag_pos - m_drag_center; - const double len_starting_vec = starting_vec.norm(); - if (len_starting_vec != 0.0) - { - Vec3d mouse_dir = mouse_ray.unit_vector(); - // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position - // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form - // in our case plane normal and ray direction are the same (orthogonal view) - // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal - Vec3d inters = mouse_ray.a + (m_drag_pos - mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; - // vector from the starting position to the found intersection - Vec3d inters_vec = inters - m_drag_pos; - - // finds projection of the vector along the staring direction - projection = inters_vec.dot(starting_vec.normalized()); - } - return projection; -} - - -} // namespace GUI -} // namespace Slic3r diff --git a/src/slic3r/GUI/GLGizmo.hpp b/src/slic3r/GUI/GLGizmo.hpp deleted file mode 100644 index 4e44da540..000000000 --- a/src/slic3r/GUI/GLGizmo.hpp +++ /dev/null @@ -1,647 +0,0 @@ -#ifndef slic3r_GLGizmo_hpp_ -#define slic3r_GLGizmo_hpp_ - -#include - -#include "../../slic3r/GUI/GLTexture.hpp" -#include "../../slic3r/GUI/GLCanvas3D.hpp" - -#include "libslic3r/Point.hpp" -#include "libslic3r/BoundingBox.hpp" -#include "libslic3r/SLA/SLAAutoSupports.hpp" - -#include -#include -#include - - -class wxWindow; -class GLUquadric; -typedef class GLUquadric GLUquadricObj; - - -namespace Slic3r { - -class BoundingBoxf3; -class Linef3; -class ModelObject; - -namespace GUI { - -class GLCanvas3D; -#if ENABLE_IMGUI -class ImGuiWrapper; -#endif // ENABLE_IMGUI - -class GLGizmoBase -{ -public: - // Starting value for ids to avoid clashing with ids used by GLVolumes - // (254 is choosen to leave some space for forward compatibility) - static const unsigned int BASE_ID = 255 * 255 * 254; - -protected: - struct Grabber - { - static const float SizeFactor; - static const float MinHalfSize; - static const float DraggingScaleFactor; - - Vec3d center; - Vec3d angles; - float color[3]; - bool enabled; - bool dragging; - - Grabber(); - - void render(bool hover, float size) const; - void render_for_picking(float size) const { render(size, color, false); } - - float get_half_size(float size) const; - float get_dragging_half_size(float size) const; - - private: - void render(float size, const float* render_color, bool use_lighting) const; - void render_face(float half_size) const; - }; - -public: - enum EState - { - Off, - Hover, - On, - Num_States - }; - - struct UpdateData - { - const Linef3 mouse_ray; - const Point* mouse_pos; - bool shift_down; - - UpdateData(const Linef3& mouse_ray, const Point* mouse_pos = nullptr, bool shift_down = false) - : mouse_ray(mouse_ray), mouse_pos(mouse_pos), shift_down(shift_down) - {} - }; - -protected: - GLCanvas3D& m_parent; - - int m_group_id; - EState m_state; - int m_shortcut_key; -#if ENABLE_SVG_ICONS - std::string m_icon_filename; -#endif // ENABLE_SVG_ICONS - unsigned int m_sprite_id; - int m_hover_id; - bool m_dragging; - float m_base_color[3]; - float m_drag_color[3]; - float m_highlight_color[3]; - mutable std::vector m_grabbers; -#if ENABLE_IMGUI - ImGuiWrapper* m_imgui; -#endif // ENABLE_IMGUI - -public: -#if ENABLE_SVG_ICONS - GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); -#else - GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id); -#endif // ENABLE_SVG_ICONS - virtual ~GLGizmoBase() {} - - bool init() { return on_init(); } - - std::string get_name() const { return on_get_name(); } - - int get_group_id() const { return m_group_id; } - void set_group_id(int id) { m_group_id = id; } - - EState get_state() const { return m_state; } - void set_state(EState state) { m_state = state; on_set_state(); } - - int get_shortcut_key() const { return m_shortcut_key; } - void set_shortcut_key(int key) { m_shortcut_key = key; } - -#if ENABLE_SVG_ICONS - const std::string& get_icon_filename() const { return m_icon_filename; } -#endif // ENABLE_SVG_ICONS - - bool is_activable(const GLCanvas3D::Selection& selection) const { return on_is_activable(selection); } - bool is_selectable() const { return on_is_selectable(); } - - unsigned int get_sprite_id() const { return m_sprite_id; } - - int get_hover_id() const { return m_hover_id; } - void set_hover_id(int id); - - void set_highlight_color(const float* color); - - void enable_grabber(unsigned int id); - void disable_grabber(unsigned int id); - - void start_dragging(const GLCanvas3D::Selection& selection); - void stop_dragging(); - bool is_dragging() const { return m_dragging; } - - void update(const UpdateData& data, const GLCanvas3D::Selection& selection); - - void render(const GLCanvas3D::Selection& selection) const { on_render(selection); } - void render_for_picking(const GLCanvas3D::Selection& selection) const { on_render_for_picking(selection); } - -#if !ENABLE_IMGUI - virtual void create_external_gizmo_widgets(wxWindow *parent); -#endif // not ENABLE_IMGUI - -#if ENABLE_IMGUI - void render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); } -#endif // ENABLE_IMGUI - -protected: - virtual bool on_init() = 0; - virtual std::string on_get_name() const = 0; - virtual void on_set_state() {} - virtual void on_set_hover_id() {} - virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return true; } - virtual bool on_is_selectable() const { return true; } - virtual void on_enable_grabber(unsigned int id) {} - virtual void on_disable_grabber(unsigned int id) {} - virtual void on_start_dragging(const GLCanvas3D::Selection& selection) {} - virtual void on_stop_dragging() {} - virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) = 0; - virtual void on_render(const GLCanvas3D::Selection& selection) const = 0; - virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const = 0; - -#if ENABLE_IMGUI - virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) {} -#endif // ENABLE_IMGUI - - // Returns the picking color for the given id, based on the BASE_ID constant - // No check is made for clashing with other picking color (i.e. GLVolumes) - std::array picking_color_component(unsigned int id) const; - void render_grabbers(const BoundingBoxf3& box) const; - void render_grabbers(float size) const; - void render_grabbers_for_picking(const BoundingBoxf3& box) const; - - void set_tooltip(const std::string& tooltip) const; - std::string format(float value, unsigned int decimals) const; -}; - -class GLGizmoRotate : public GLGizmoBase -{ - static const float Offset; - static const unsigned int CircleResolution; - static const unsigned int AngleResolution; - static const unsigned int ScaleStepsCount; - static const float ScaleStepRad; - static const unsigned int ScaleLongEvery; - static const float ScaleLongTooth; - static const unsigned int SnapRegionsCount; - static const float GrabberOffset; - -public: - enum Axis : unsigned char - { - X, - Y, - Z - }; - -private: - Axis m_axis; - double m_angle; - - GLUquadricObj* m_quadric; - - mutable Vec3d m_center; - mutable float m_radius; - - mutable float m_snap_coarse_in_radius; - mutable float m_snap_coarse_out_radius; - mutable float m_snap_fine_in_radius; - mutable float m_snap_fine_out_radius; - -public: - GLGizmoRotate(GLCanvas3D& parent, Axis axis); - GLGizmoRotate(const GLGizmoRotate& other); - virtual ~GLGizmoRotate(); - - double get_angle() const { return m_angle; } - void set_angle(double angle); - -protected: - virtual bool on_init(); - virtual std::string on_get_name() const { return ""; } - virtual void on_start_dragging(const GLCanvas3D::Selection& selection); - virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); - virtual void on_render(const GLCanvas3D::Selection& selection) const; - virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; - -private: - void render_circle() const; - void render_scale() const; - void render_snap_radii() const; - void render_reference_radius() const; - void render_angle() const; - void render_grabber(const BoundingBoxf3& box) const; - void render_grabber_extension(const BoundingBoxf3& box, bool picking) const; - - void transform_to_local(const GLCanvas3D::Selection& selection) const; - // returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate - Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const; -}; - -class GLGizmoRotate3D : public GLGizmoBase -{ - std::vector m_gizmos; - -public: -#if ENABLE_SVG_ICONS - GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); -#else - GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id); -#endif // ENABLE_SVG_ICONS - - Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); } - void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); } - -protected: - virtual bool on_init(); - virtual std::string on_get_name() const; - virtual void on_set_state() - { - for (GLGizmoRotate& g : m_gizmos) - { - g.set_state(m_state); - } - } - virtual void on_set_hover_id() - { - for (unsigned int i = 0; i < 3; ++i) - { - m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); - } - } - virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); } - virtual void on_enable_grabber(unsigned int id) - { - if ((0 <= id) && (id < 3)) - m_gizmos[id].enable_grabber(0); - } - virtual void on_disable_grabber(unsigned int id) - { - if ((0 <= id) && (id < 3)) - m_gizmos[id].disable_grabber(0); - } - virtual void on_start_dragging(const GLCanvas3D::Selection& selection); - virtual void on_stop_dragging(); - virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) - { - for (GLGizmoRotate& g : m_gizmos) - { - g.update(data, selection); - } - } - virtual void on_render(const GLCanvas3D::Selection& selection) const; - virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const - { - for (const GLGizmoRotate& g : m_gizmos) - { - g.render_for_picking(selection); - } - } - -#if ENABLE_IMGUI - virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); -#endif // ENABLE_IMGUI -}; - -class GLGizmoScale3D : public GLGizmoBase -{ - static const float Offset; - - mutable BoundingBoxf3 m_box; - - Vec3d m_scale; - - double m_snap_step; - - Vec3d m_starting_scale; - Vec3d m_starting_drag_position; - BoundingBoxf3 m_starting_box; - -public: -#if ENABLE_SVG_ICONS - GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); -#else - GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id); -#endif // ENABLE_SVG_ICONS - - double get_snap_step(double step) const { return m_snap_step; } - void set_snap_step(double step) { m_snap_step = step; } - - const Vec3d& get_scale() const { return m_scale; } - void set_scale(const Vec3d& scale) { m_starting_scale = scale; m_scale = scale; } - -protected: - virtual bool on_init(); - virtual std::string on_get_name() const; - virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); } - virtual void on_start_dragging(const GLCanvas3D::Selection& selection); - virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); - virtual void on_render(const GLCanvas3D::Selection& selection) const; - virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; - -#if ENABLE_IMGUI - virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); -#endif // ENABLE_IMGUI - -private: - void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const; - - void do_scale_x(const UpdateData& data); - void do_scale_y(const UpdateData& data); - void do_scale_z(const UpdateData& data); - void do_scale_uniform(const UpdateData& data); - - double calc_ratio(const UpdateData& data) const; -}; - -class GLGizmoMove3D : public GLGizmoBase -{ - static const double Offset; - - Vec3d m_displacement; - - double m_snap_step; - - Vec3d m_starting_drag_position; - Vec3d m_starting_box_center; - Vec3d m_starting_box_bottom_center; - - GLUquadricObj* m_quadric; - -public: -#if ENABLE_SVG_ICONS - GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); -#else - GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id); -#endif // ENABLE_SVG_ICONS - virtual ~GLGizmoMove3D(); - - double get_snap_step(double step) const { return m_snap_step; } - void set_snap_step(double step) { m_snap_step = step; } - - const Vec3d& get_displacement() const { return m_displacement; } - -protected: - virtual bool on_init(); - virtual std::string on_get_name() const; - virtual void on_start_dragging(const GLCanvas3D::Selection& selection); - virtual void on_stop_dragging(); - virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); - virtual void on_render(const GLCanvas3D::Selection& selection) const; - virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; - -#if ENABLE_IMGUI - virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); -#endif // ENABLE_IMGUI - -private: - double calc_projection(const UpdateData& data) const; - void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const; -}; - -class GLGizmoFlatten : public GLGizmoBase -{ -// This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself. - -private: - mutable Vec3d m_normal; - - struct PlaneData { - std::vector vertices; - Vec3d normal; - float area; - }; - - // This holds information to decide whether recalculation is necessary: - std::vector m_volumes_matrices; - std::vector m_volumes_types; - Vec3d m_first_instance_scale; - Vec3d m_first_instance_mirror; - - std::vector m_planes; - bool m_planes_valid = false; - mutable Vec3d m_starting_center; - const ModelObject* m_model_object = nullptr; - std::vector instances_matrices; - - void update_planes(); - bool is_plane_update_necessary() const; - -public: -#if ENABLE_SVG_ICONS - GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); -#else - GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id); -#endif // ENABLE_SVG_ICONS - - void set_flattening_data(const ModelObject* model_object); - Vec3d get_flattening_normal() const; - -protected: - virtual bool on_init(); - virtual std::string on_get_name() const; - virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const; - virtual void on_start_dragging(const GLCanvas3D::Selection& selection); - virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) {} - virtual void on_render(const GLCanvas3D::Selection& selection) const; - virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; - virtual void on_set_state() - { - if (m_state == On && is_plane_update_necessary()) - update_planes(); - } -}; - -#define SLAGIZMO_IMGUI_MODAL 0 - -class GLGizmoSlaSupports : public GLGizmoBase -{ -private: - ModelObject* m_model_object = nullptr; - ModelObject* m_old_model_object = nullptr; - int m_active_instance = -1; - int m_old_instance_id = -1; - std::pair unproject_on_mesh(const Vec2d& mouse_pos); - - const float RenderPointScale = 1.f; - - GLUquadricObj* m_quadric; - Eigen::MatrixXf m_V; // vertices - Eigen::MatrixXi m_F; // facets indices - igl::AABB m_AABB; - - struct SourceDataSummary { - Geometry::Transformation transformation; - }; - - class CacheEntry { - public: - CacheEntry(const sla::SupportPoint& point, bool sel, const Vec3f& norm = Vec3f::Zero()) : - support_point(point), selected(sel), normal(norm) {} - - sla::SupportPoint support_point; - bool selected; // whether the point is selected - Vec3f normal; - }; - - // This holds information to decide whether recalculation is necessary: - SourceDataSummary m_source_data; - - mutable Vec3d m_starting_center; - -public: -#if ENABLE_SVG_ICONS - GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); -#else - GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id); -#endif // ENABLE_SVG_ICONS - virtual ~GLGizmoSlaSupports(); - void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection); - bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down); - void delete_selected_points(bool force = false); - -private: - bool on_init(); - void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); - virtual void on_render(const GLCanvas3D::Selection& selection) const; - virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; - - void render_selection_rectangle() const; - void render_points(const GLCanvas3D::Selection& selection, bool picking = false) const; - bool is_mesh_update_necessary() const; - void update_mesh(); - void update_cache_entry_normal(unsigned int i) const; - -#if !ENABLE_IMGUI - void render_tooltip_texture() const; - mutable GLTexture m_tooltip_texture; - mutable GLTexture m_reset_texture; -#endif // not ENABLE_IMGUI - - bool m_lock_unique_islands = false; - bool m_editing_mode = false; // Is editing mode active? - bool m_old_editing_state = false; // To keep track of whether the user toggled between the modes (needed for imgui refreshes). - float m_new_point_head_diameter; // Size of a new point. - float m_minimal_point_distance = 20.f; - float m_density = 100.f; - mutable std::vector m_editing_mode_cache; // a support point and whether it is currently selected - - bool m_selection_rectangle_active = false; - Vec2d m_selection_rectangle_start_corner; - Vec2d m_selection_rectangle_end_corner; - bool m_ignore_up_event = false; - bool m_combo_box_open = false; // To ensure proper rendering of the imgui combobox. - bool m_unsaved_changes = false; // Are there unsaved changes in manual mode? - bool m_selection_empty = true; - EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state) - int m_canvas_width; - int m_canvas_height; - - std::vector get_config_options(const std::vector& keys) const; - - // Methods that do the model_object and editing cache synchronization, - // editing mode selection, etc: - enum { - AllPoints = -2, - NoPoints, - }; - void select_point(int i); - void editing_mode_apply_changes(); - void editing_mode_discard_changes(); - void editing_mode_reload_cache(); - void get_data_from_backend(); - void auto_generate(); - void switch_to_editing_mode(); - -protected: - void on_set_state() override; - void on_start_dragging(const GLCanvas3D::Selection& selection) override; - -#if ENABLE_IMGUI - virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) override; -#endif // ENABLE_IMGUI - - virtual std::string on_get_name() const; - virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const; - virtual bool on_is_selectable() const; -}; - - -#if !ENABLE_IMGUI -class GLGizmoCutPanel; -#endif // not ENABLE_IMGUI - -class GLGizmoCut : public GLGizmoBase -{ - static const double Offset; - static const double Margin; - static const std::array GrabberColor; - - mutable double m_cut_z; - double m_start_z; - mutable double m_max_z; - Vec3d m_drag_pos; - Vec3d m_drag_center; - bool m_keep_upper; - bool m_keep_lower; - bool m_rotate_lower; -#if !ENABLE_IMGUI - GLGizmoCutPanel *m_panel; -#endif // not ENABLE_IMGUI - -public: -#if ENABLE_SVG_ICONS - GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); -#else - GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id); -#endif // ENABLE_SVG_ICONS - -#if !ENABLE_IMGUI - virtual void create_external_gizmo_widgets(wxWindow *parent); -#endif // not ENABLE_IMGUI -#if !ENABLE_IMGUI -#endif // not ENABLE_IMGUI - -protected: - virtual bool on_init(); - virtual std::string on_get_name() const; - virtual void on_set_state(); - virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const; - virtual void on_start_dragging(const GLCanvas3D::Selection& selection); - virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); - virtual void on_render(const GLCanvas3D::Selection& selection) const; - virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; - -#if ENABLE_IMGUI - virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); -#endif // ENABLE_IMGUI -private: - void update_max_z(const GLCanvas3D::Selection& selection) const; - void set_cut_z(double cut_z) const; - void perform_cut(const GLCanvas3D::Selection& selection); - double calc_projection(const Linef3& mouse_ray) const; -}; - - -} // namespace GUI -} // namespace Slic3r - -#endif // slic3r_GLGizmo_hpp_ - diff --git a/src/slic3r/GUI/GLTexture.hpp b/src/slic3r/GUI/GLTexture.hpp index 017255647..e00b3a3be 100644 --- a/src/slic3r/GUI/GLTexture.hpp +++ b/src/slic3r/GUI/GLTexture.hpp @@ -2,6 +2,7 @@ #define slic3r_GLTexture_hpp_ #include +#include class wxImage; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp new file mode 100644 index 000000000..3c3f68371 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -0,0 +1,286 @@ +#include "GLGizmoBase.hpp" + +#include + +#include "slic3r/GUI/GUI_App.hpp" + + + + + +// TODO: Display tooltips quicker on Linux + + + +namespace Slic3r { +namespace GUI { + +const float GLGizmoBase::Grabber::SizeFactor = 0.025f; +const float GLGizmoBase::Grabber::MinHalfSize = 1.5f; +const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; + +GLGizmoBase::Grabber::Grabber() + : center(Vec3d::Zero()) + , angles(Vec3d::Zero()) + , dragging(false) + , enabled(true) +{ + color[0] = 1.0f; + color[1] = 1.0f; + color[2] = 1.0f; +} + +void GLGizmoBase::Grabber::render(bool hover, float size) const +{ + float render_color[3]; + if (hover) + { + render_color[0] = 1.0f - color[0]; + render_color[1] = 1.0f - color[1]; + render_color[2] = 1.0f - color[2]; + } + else + ::memcpy((void*)render_color, (const void*)color, 3 * sizeof(float)); + + render(size, render_color, true); +} + +float GLGizmoBase::Grabber::get_half_size(float size) const +{ + return std::max(size * SizeFactor, MinHalfSize); +} + +float GLGizmoBase::Grabber::get_dragging_half_size(float size) const +{ + return std::max(size * SizeFactor * DraggingScaleFactor, MinHalfSize); +} + +void GLGizmoBase::Grabber::render(float size, const float* render_color, bool use_lighting) const +{ + float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size); + + if (use_lighting) + ::glEnable(GL_LIGHTING); + + ::glColor3fv(render_color); + + ::glPushMatrix(); + ::glTranslated(center(0), center(1), center(2)); + + ::glRotated(Geometry::rad2deg(angles(2)), 0.0, 0.0, 1.0); + ::glRotated(Geometry::rad2deg(angles(1)), 0.0, 1.0, 0.0); + ::glRotated(Geometry::rad2deg(angles(0)), 1.0, 0.0, 0.0); + + // face min x + ::glPushMatrix(); + ::glTranslatef(-(GLfloat)half_size, 0.0f, 0.0f); + ::glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); + render_face(half_size); + ::glPopMatrix(); + + // face max x + ::glPushMatrix(); + ::glTranslatef((GLfloat)half_size, 0.0f, 0.0f); + ::glRotatef(90.0f, 0.0f, 1.0f, 0.0f); + render_face(half_size); + ::glPopMatrix(); + + // face min y + ::glPushMatrix(); + ::glTranslatef(0.0f, -(GLfloat)half_size, 0.0f); + ::glRotatef(90.0f, 1.0f, 0.0f, 0.0f); + render_face(half_size); + ::glPopMatrix(); + + // face max y + ::glPushMatrix(); + ::glTranslatef(0.0f, (GLfloat)half_size, 0.0f); + ::glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); + render_face(half_size); + ::glPopMatrix(); + + // face min z + ::glPushMatrix(); + ::glTranslatef(0.0f, 0.0f, -(GLfloat)half_size); + ::glRotatef(180.0f, 1.0f, 0.0f, 0.0f); + render_face(half_size); + ::glPopMatrix(); + + // face max z + ::glPushMatrix(); + ::glTranslatef(0.0f, 0.0f, (GLfloat)half_size); + render_face(half_size); + ::glPopMatrix(); + + ::glPopMatrix(); + + if (use_lighting) + ::glDisable(GL_LIGHTING); +} + +void GLGizmoBase::Grabber::render_face(float half_size) const +{ + ::glBegin(GL_TRIANGLES); + ::glNormal3f(0.0f, 0.0f, 1.0f); + ::glVertex3f(-(GLfloat)half_size, -(GLfloat)half_size, 0.0f); + ::glVertex3f((GLfloat)half_size, -(GLfloat)half_size, 0.0f); + ::glVertex3f((GLfloat)half_size, (GLfloat)half_size, 0.0f); + ::glVertex3f((GLfloat)half_size, (GLfloat)half_size, 0.0f); + ::glVertex3f(-(GLfloat)half_size, (GLfloat)half_size, 0.0f); + ::glVertex3f(-(GLfloat)half_size, -(GLfloat)half_size, 0.0f); + ::glEnd(); +} + +#if ENABLE_SVG_ICONS +GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) +#else +GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id) +#endif // ENABLE_SVG_ICONS + : m_parent(parent) + , m_group_id(-1) + , m_state(Off) + , m_shortcut_key(0) +#if ENABLE_SVG_ICONS + , m_icon_filename(icon_filename) +#endif // ENABLE_SVG_ICONS + , m_sprite_id(sprite_id) + , m_hover_id(-1) + , m_dragging(false) +#if ENABLE_IMGUI + , m_imgui(wxGetApp().imgui()) +#endif // ENABLE_IMGUI +{ + ::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 3 * sizeof(float)); + ::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 3 * sizeof(float)); + ::memcpy((void*)m_highlight_color, (const void*)DEFAULT_HIGHLIGHT_COLOR, 3 * sizeof(float)); +} + +void GLGizmoBase::set_hover_id(int id) +{ + if (m_grabbers.empty() || (id < (int)m_grabbers.size())) + { + m_hover_id = id; + on_set_hover_id(); + } +} + +void GLGizmoBase::set_highlight_color(const float* color) +{ + if (color != nullptr) + ::memcpy((void*)m_highlight_color, (const void*)color, 3 * sizeof(float)); +} + +void GLGizmoBase::enable_grabber(unsigned int id) +{ + if ((0 <= id) && (id < (unsigned int)m_grabbers.size())) + m_grabbers[id].enabled = true; + + on_enable_grabber(id); +} + +void GLGizmoBase::disable_grabber(unsigned int id) +{ + if ((0 <= id) && (id < (unsigned int)m_grabbers.size())) + m_grabbers[id].enabled = false; + + on_disable_grabber(id); +} + +void GLGizmoBase::start_dragging(const GLCanvas3D::Selection& selection) +{ + m_dragging = true; + + for (int i = 0; i < (int)m_grabbers.size(); ++i) + { + m_grabbers[i].dragging = (m_hover_id == i); + } + + on_start_dragging(selection); +} + +void GLGizmoBase::stop_dragging() +{ + m_dragging = false; + + for (int i = 0; i < (int)m_grabbers.size(); ++i) + { + m_grabbers[i].dragging = false; + } + + on_stop_dragging(); +} + +void GLGizmoBase::update(const UpdateData& data, const GLCanvas3D::Selection& selection) +{ + if (m_hover_id != -1) + on_update(data, selection); +} + +std::array GLGizmoBase::picking_color_component(unsigned int id) const +{ + static const float INV_255 = 1.0f / 255.0f; + + id = BASE_ID - id; + + if (m_group_id > -1) + id -= m_group_id; + + // color components are encoded to match the calculation of volume_id made into GLCanvas3D::_picking_pass() + return std::array { (float)((id >> 0) & 0xff) * INV_255, // red + (float)((id >> 8) & 0xff) * INV_255, // green + (float)((id >> 16) & 0xff) * INV_255 }; // blue +} + +void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const +{ + float size = (float)box.max_size(); + + for (int i = 0; i < (int)m_grabbers.size(); ++i) + { + if (m_grabbers[i].enabled) + m_grabbers[i].render((m_hover_id == i), size); + } +} + +void GLGizmoBase::render_grabbers(float size) const +{ + for (int i = 0; i < (int)m_grabbers.size(); ++i) + { + if (m_grabbers[i].enabled) + m_grabbers[i].render((m_hover_id == i), size); + } +} + +void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const +{ + float size = (float)box.max_size(); + + for (unsigned int i = 0; i < (unsigned int)m_grabbers.size(); ++i) + { + if (m_grabbers[i].enabled) + { + std::array color = picking_color_component(i); + m_grabbers[i].color[0] = color[0]; + m_grabbers[i].color[1] = color[1]; + m_grabbers[i].color[2] = color[2]; + m_grabbers[i].render_for_picking(size); + } + } +} + +#if !ENABLE_IMGUI +void GLGizmoBase::create_external_gizmo_widgets(wxWindow *parent) {} +#endif // not ENABLE_IMGUI + +void GLGizmoBase::set_tooltip(const std::string& tooltip) const +{ + m_parent.set_tooltip(tooltip); +} + +std::string GLGizmoBase::format(float value, unsigned int decimals) const +{ + return Slic3r::string_printf("%.*f", decimals, value); +} + +} // namespace GUI +} // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp new file mode 100644 index 000000000..3abd2e607 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -0,0 +1,196 @@ +#ifndef slic3r_GLGizmoBase_hpp_ +#define slic3r_GLGizmoBase_hpp_ + +#include "libslic3r/Point.hpp" + +#include "slic3r/GUI/GLCanvas3D.hpp" +#include "slic3r/GUI/I18N.hpp" + + +class wxWindow; +class GLUquadric; +typedef class GLUquadric GLUquadricObj; + + +namespace Slic3r { + +class BoundingBoxf3; +class Linef3; +class ModelObject; + +namespace GUI { + +static const float DEFAULT_BASE_COLOR[3] = { 0.625f, 0.625f, 0.625f }; +static const float DEFAULT_DRAG_COLOR[3] = { 1.0f, 1.0f, 1.0f }; +static const float DEFAULT_HIGHLIGHT_COLOR[3] = { 1.0f, 0.38f, 0.0f }; +static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } }; + + + +#if ENABLE_IMGUI +class ImGuiWrapper; +#endif // ENABLE_IMGUI + + +class GLGizmoBase +{ +public: + // Starting value for ids to avoid clashing with ids used by GLVolumes + // (254 is choosen to leave some space for forward compatibility) + static const unsigned int BASE_ID = 255 * 255 * 254; + +protected: + struct Grabber + { + static const float SizeFactor; + static const float MinHalfSize; + static const float DraggingScaleFactor; + + Vec3d center; + Vec3d angles; + float color[3]; + bool enabled; + bool dragging; + + Grabber(); + + void render(bool hover, float size) const; + void render_for_picking(float size) const { render(size, color, false); } + + float get_half_size(float size) const; + float get_dragging_half_size(float size) const; + + private: + void render(float size, const float* render_color, bool use_lighting) const; + void render_face(float half_size) const; + }; + +public: + enum EState + { + Off, + Hover, + On, + Num_States + }; + + struct UpdateData + { + const Linef3 mouse_ray; + const Point* mouse_pos; + bool shift_down; + + UpdateData(const Linef3& mouse_ray, const Point* mouse_pos = nullptr, bool shift_down = false) + : mouse_ray(mouse_ray), mouse_pos(mouse_pos), shift_down(shift_down) + {} + }; + +protected: + GLCanvas3D& m_parent; + + int m_group_id; + EState m_state; + int m_shortcut_key; +#if ENABLE_SVG_ICONS + std::string m_icon_filename; +#endif // ENABLE_SVG_ICONS + unsigned int m_sprite_id; + int m_hover_id; + bool m_dragging; + float m_base_color[3]; + float m_drag_color[3]; + float m_highlight_color[3]; + mutable std::vector m_grabbers; +#if ENABLE_IMGUI + ImGuiWrapper* m_imgui; +#endif // ENABLE_IMGUI + +public: +#if ENABLE_SVG_ICONS + GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); +#else + GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id); +#endif // ENABLE_SVG_ICONS + virtual ~GLGizmoBase() {} + + bool init() { return on_init(); } + + std::string get_name() const { return on_get_name(); } + + int get_group_id() const { return m_group_id; } + void set_group_id(int id) { m_group_id = id; } + + EState get_state() const { return m_state; } + void set_state(EState state) { m_state = state; on_set_state(); } + + int get_shortcut_key() const { return m_shortcut_key; } + void set_shortcut_key(int key) { m_shortcut_key = key; } + +#if ENABLE_SVG_ICONS + const std::string& get_icon_filename() const { return m_icon_filename; } +#endif // ENABLE_SVG_ICONS + + bool is_activable(const GLCanvas3D::Selection& selection) const { return on_is_activable(selection); } + bool is_selectable() const { return on_is_selectable(); } + + unsigned int get_sprite_id() const { return m_sprite_id; } + + int get_hover_id() const { return m_hover_id; } + void set_hover_id(int id); + + void set_highlight_color(const float* color); + + void enable_grabber(unsigned int id); + void disable_grabber(unsigned int id); + + void start_dragging(const GLCanvas3D::Selection& selection); + void stop_dragging(); + bool is_dragging() const { return m_dragging; } + + void update(const UpdateData& data, const GLCanvas3D::Selection& selection); + + void render(const GLCanvas3D::Selection& selection) const { on_render(selection); } + void render_for_picking(const GLCanvas3D::Selection& selection) const { on_render_for_picking(selection); } + +#if !ENABLE_IMGUI + virtual void create_external_gizmo_widgets(wxWindow *parent); +#endif // not ENABLE_IMGUI + +#if ENABLE_IMGUI + void render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); } +#endif // ENABLE_IMGUI + +protected: + virtual bool on_init() = 0; + virtual std::string on_get_name() const = 0; + virtual void on_set_state() {} + virtual void on_set_hover_id() {} + virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return true; } + virtual bool on_is_selectable() const { return true; } + virtual void on_enable_grabber(unsigned int id) {} + virtual void on_disable_grabber(unsigned int id) {} + virtual void on_start_dragging(const GLCanvas3D::Selection& selection) {} + virtual void on_stop_dragging() {} + virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) = 0; + virtual void on_render(const GLCanvas3D::Selection& selection) const = 0; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const = 0; + +#if ENABLE_IMGUI + virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) {} +#endif // ENABLE_IMGUI + + // Returns the picking color for the given id, based on the BASE_ID constant + // No check is made for clashing with other picking color (i.e. GLVolumes) + std::array picking_color_component(unsigned int id) const; + void render_grabbers(const BoundingBoxf3& box) const; + void render_grabbers(float size) const; + void render_grabbers_for_picking(const BoundingBoxf3& box) const; + + void set_tooltip(const std::string& tooltip) const; + std::string format(float value, unsigned int decimals) const; +}; + +} // namespace GUI +} // namespace Slic3r + +#endif // slic3r_GLGizmoBase_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp new file mode 100644 index 000000000..bd29b1288 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -0,0 +1,288 @@ +// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. +#include "GLGizmoCut.hpp" + +#include + +#include +#include +#include +#include + +#include "slic3r/GUI/GUI_App.hpp" + + +namespace Slic3r { +namespace GUI { + + + + + + +// GLGizmoCut + +class GLGizmoCutPanel : public wxPanel +{ +public: + GLGizmoCutPanel(wxWindow *parent); + + void display(bool display); +private: + bool m_active; + wxCheckBox *m_cb_rotate; + wxButton *m_btn_cut; + wxButton *m_btn_cancel; +}; + +GLGizmoCutPanel::GLGizmoCutPanel(wxWindow *parent) + : wxPanel(parent) + , m_active(false) + , m_cb_rotate(new wxCheckBox(this, wxID_ANY, _(L("Rotate lower part upwards")))) + , m_btn_cut(new wxButton(this, wxID_OK, _(L("Perform cut")))) + , m_btn_cancel(new wxButton(this, wxID_CANCEL, _(L("Cancel")))) +{ + enum { MARGIN = 5 }; + + auto *sizer = new wxBoxSizer(wxHORIZONTAL); + + auto *label = new wxStaticText(this, wxID_ANY, _(L("Cut object:"))); + sizer->Add(label, 0, wxALL | wxALIGN_CENTER, MARGIN); + sizer->Add(m_cb_rotate, 0, wxALL | wxALIGN_CENTER, MARGIN); + sizer->AddStretchSpacer(); + sizer->Add(m_btn_cut, 0, wxALL | wxALIGN_CENTER, MARGIN); + sizer->Add(m_btn_cancel, 0, wxALL | wxALIGN_CENTER, MARGIN); + + SetSizer(sizer); +} + +void GLGizmoCutPanel::display(bool display) +{ + Show(display); + GetParent()->Layout(); +} + + +const double GLGizmoCut::Offset = 10.0; +const double GLGizmoCut::Margin = 20.0; +const std::array GLGizmoCut::GrabberColor = { 1.0, 0.5, 0.0 }; + +#if ENABLE_SVG_ICONS +GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) + : GLGizmoBase(parent, icon_filename, sprite_id) +#else +GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) +#endif // ENABLE_SVG_ICONS + , m_cut_z(0.0) + , m_max_z(0.0) +#if !ENABLE_IMGUI + , m_panel(nullptr) +#endif // not ENABLE_IMGUI + , m_keep_upper(true) + , m_keep_lower(true) + , m_rotate_lower(false) +{} + +#if !ENABLE_IMGUI +void GLGizmoCut::create_external_gizmo_widgets(wxWindow *parent) +{ + wxASSERT(m_panel == nullptr); + + m_panel = new GLGizmoCutPanel(parent); + parent->GetSizer()->Add(m_panel, 0, wxEXPAND); + + parent->Layout(); + parent->Fit(); + auto prev_heigh = parent->GetMinSize().GetHeight(); + parent->SetMinSize(wxSize(-1, std::max(prev_heigh, m_panel->GetSize().GetHeight()))); + + m_panel->Hide(); + m_panel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + perform_cut(m_parent.get_selection()); + }, wxID_OK); +} +#endif // not ENABLE_IMGUI + +bool GLGizmoCut::on_init() +{ + m_grabbers.emplace_back(); + m_shortcut_key = WXK_CONTROL_C; + return true; +} + +std::string GLGizmoCut::on_get_name() const +{ + return L("Cut [C]"); +} + +void GLGizmoCut::on_set_state() +{ + // Reset m_cut_z on gizmo activation + if (get_state() == On) { + m_cut_z = m_parent.get_selection().get_bounding_box().size()(2) / 2.0; + } + +#if !ENABLE_IMGUI + // Display or hide the extra panel + if (m_panel != nullptr) { + m_panel->display(get_state() == On); + } +#endif // not ENABLE_IMGUI +} + +bool GLGizmoCut::on_is_activable(const GLCanvas3D::Selection& selection) const +{ + return selection.is_single_full_instance() && !selection.is_wipe_tower(); +} + +void GLGizmoCut::on_start_dragging(const GLCanvas3D::Selection& selection) +{ + if (m_hover_id == -1) { return; } + + const BoundingBoxf3& box = selection.get_bounding_box(); + m_start_z = m_cut_z; + update_max_z(selection); + m_drag_pos = m_grabbers[m_hover_id].center; + m_drag_center = box.center(); + m_drag_center(2) = m_cut_z; +} + +void GLGizmoCut::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) +{ + if (m_hover_id != -1) { + set_cut_z(m_start_z + calc_projection(data.mouse_ray)); + } +} + +void GLGizmoCut::on_render(const GLCanvas3D::Selection& selection) const +{ + if (m_grabbers[0].dragging) { + set_tooltip("Z: " + format(m_cut_z, 2)); + } + + update_max_z(selection); + + const BoundingBoxf3& box = selection.get_bounding_box(); + Vec3d plane_center = box.center(); + plane_center(2) = m_cut_z; + + const float min_x = box.min(0) - Margin; + const float max_x = box.max(0) + Margin; + const float min_y = box.min(1) - Margin; + const float max_y = box.max(1) + Margin; + ::glEnable(GL_DEPTH_TEST); + ::glDisable(GL_CULL_FACE); + ::glEnable(GL_BLEND); + ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Draw the cutting plane + ::glBegin(GL_QUADS); + ::glColor4f(0.8f, 0.8f, 0.8f, 0.5f); + ::glVertex3f(min_x, min_y, plane_center(2)); + ::glVertex3f(max_x, min_y, plane_center(2)); + ::glVertex3f(max_x, max_y, plane_center(2)); + ::glVertex3f(min_x, max_y, plane_center(2)); + ::glEnd(); + + ::glEnable(GL_CULL_FACE); + ::glDisable(GL_BLEND); + + // TODO: draw cut part contour? + + // Draw the grabber and the connecting line + m_grabbers[0].center = plane_center; + m_grabbers[0].center(2) = plane_center(2) + Offset; + + ::glDisable(GL_DEPTH_TEST); + ::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f); + ::glColor3f(1.0, 1.0, 0.0); + ::glBegin(GL_LINES); + ::glVertex3dv(plane_center.data()); + ::glVertex3dv(m_grabbers[0].center.data()); + ::glEnd(); + + std::copy(std::begin(GrabberColor), std::end(GrabberColor), m_grabbers[0].color); + m_grabbers[0].render(m_hover_id == 0, box.max_size()); +} + +void GLGizmoCut::on_render_for_picking(const GLCanvas3D::Selection& selection) const +{ + ::glDisable(GL_DEPTH_TEST); + + render_grabbers_for_picking(selection.get_bounding_box()); +} + +#if ENABLE_IMGUI +void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) +{ + m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); + m_imgui->set_next_window_bg_alpha(0.5f); + m_imgui->begin(_(L("Cut")), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + + ImGui::PushItemWidth(100.0f); + bool _value_changed = ImGui::InputDouble("Z", &m_cut_z, 0.0f, 0.0f, "%.2f"); + + m_imgui->checkbox(_(L("Keep upper part")), m_keep_upper); + m_imgui->checkbox(_(L("Keep lower part")), m_keep_lower); + m_imgui->checkbox(_(L("Rotate lower part upwards")), m_rotate_lower); + + m_imgui->disabled_begin(!m_keep_upper && !m_keep_lower); + const bool cut_clicked = m_imgui->button(_(L("Perform cut"))); + m_imgui->disabled_end(); + + m_imgui->end(); + + if (cut_clicked && (m_keep_upper || m_keep_lower)) { + perform_cut(selection); + } +} +#endif // ENABLE_IMGUI + +void GLGizmoCut::update_max_z(const GLCanvas3D::Selection& selection) const +{ + m_max_z = selection.get_bounding_box().size()(2); + set_cut_z(m_cut_z); +} + +void GLGizmoCut::set_cut_z(double cut_z) const +{ + // Clamp the plane to the object's bounding box + m_cut_z = std::max(0.0, std::min(m_max_z, cut_z)); +} + +void GLGizmoCut::perform_cut(const GLCanvas3D::Selection& selection) +{ + const auto instance_idx = selection.get_instance_idx(); + const auto object_idx = selection.get_object_idx(); + + wxCHECK_RET(instance_idx >= 0 && object_idx >= 0, "GLGizmoCut: Invalid object selection"); + + wxGetApp().plater()->cut(object_idx, instance_idx, m_cut_z, m_keep_upper, m_keep_lower, m_rotate_lower); +} + +double GLGizmoCut::calc_projection(const Linef3& mouse_ray) const +{ + double projection = 0.0; + + const Vec3d starting_vec = m_drag_pos - m_drag_center; + const double len_starting_vec = starting_vec.norm(); + if (len_starting_vec != 0.0) + { + Vec3d mouse_dir = mouse_ray.unit_vector(); + // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position + // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form + // in our case plane normal and ray direction are the same (orthogonal view) + // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal + Vec3d inters = mouse_ray.a + (m_drag_pos - mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; + // vector from the starting position to the found intersection + Vec3d inters_vec = inters - m_drag_pos; + + // finds projection of the vector along the staring direction + projection = inters_vec.dot(starting_vec.normalized()); + } + return projection; +} + + +} // namespace GUI +} // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp new file mode 100644 index 000000000..200e1c0df --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -0,0 +1,68 @@ +#ifndef slic3r_GLGizmoCut_hpp_ +#define slic3r_GLGizmoCut_hpp_ + +#include "GLGizmoBase.hpp" + + +namespace Slic3r { +namespace GUI { + +#if !ENABLE_IMGUI +class GLGizmoCutPanel; +#endif // not ENABLE_IMGUI + +class GLGizmoCut : public GLGizmoBase +{ + static const double Offset; + static const double Margin; + static const std::array GrabberColor; + + mutable double m_cut_z; + double m_start_z; + mutable double m_max_z; + Vec3d m_drag_pos; + Vec3d m_drag_center; + bool m_keep_upper; + bool m_keep_lower; + bool m_rotate_lower; +#if !ENABLE_IMGUI + GLGizmoCutPanel *m_panel; +#endif // not ENABLE_IMGUI + +public: +#if ENABLE_SVG_ICONS + GLGizmoCut(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); +#else + GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id); +#endif // ENABLE_SVG_ICONS + +#if !ENABLE_IMGUI + virtual void create_external_gizmo_widgets(wxWindow *parent); +#endif // not ENABLE_IMGUI +#if !ENABLE_IMGUI +#endif // not ENABLE_IMGUI + +protected: + virtual bool on_init(); + virtual std::string on_get_name() const; + virtual void on_set_state(); + virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const; + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); + virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; + +#if ENABLE_IMGUI + virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); +#endif // ENABLE_IMGUI +private: + void update_max_z(const GLCanvas3D::Selection& selection) const; + void set_cut_z(double cut_z) const; + void perform_cut(const GLCanvas3D::Selection& selection); + double calc_projection(const Linef3& mouse_ray) const; +}; + +} // namespace GUI +} // namespace Slic3r + +#endif // slic3r_GLGizmoCut_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp new file mode 100644 index 000000000..d72dc4913 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp @@ -0,0 +1,357 @@ +// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. +#include "GLGizmoFlatten.hpp" + +#include + +#include + +namespace Slic3r { +namespace GUI { + + +#if ENABLE_SVG_ICONS +GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) + : GLGizmoBase(parent, icon_filename, sprite_id) +#else +GLGizmoFlatten::GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) +#endif // ENABLE_SVG_ICONS + , m_normal(Vec3d::Zero()) + , m_starting_center(Vec3d::Zero()) +{ +} + +bool GLGizmoFlatten::on_init() +{ + m_shortcut_key = WXK_CONTROL_F; + return true; +} + +std::string GLGizmoFlatten::on_get_name() const +{ + return L("Place on face [F]"); +} + +bool GLGizmoFlatten::on_is_activable(const GLCanvas3D::Selection& selection) const +{ + return selection.is_single_full_instance(); +} + +void GLGizmoFlatten::on_start_dragging(const GLCanvas3D::Selection& selection) +{ + if (m_hover_id != -1) + { + assert(m_planes_valid); + m_normal = m_planes[m_hover_id].normal; + m_starting_center = selection.get_bounding_box().center(); + } +} + +void GLGizmoFlatten::on_render(const GLCanvas3D::Selection& selection) const +{ + ::glClear(GL_DEPTH_BUFFER_BIT); + + ::glEnable(GL_DEPTH_TEST); + ::glEnable(GL_BLEND); + + if (selection.is_single_full_instance()) + { + const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); + ::glPushMatrix(); + ::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z()); + ::glMultMatrixd(m.data()); + if (this->is_plane_update_necessary()) + const_cast(this)->update_planes(); + for (int i = 0; i < (int)m_planes.size(); ++i) + { + if (i == m_hover_id) + ::glColor4f(0.9f, 0.9f, 0.9f, 0.75f); + else + ::glColor4f(0.9f, 0.9f, 0.9f, 0.5f); + + ::glBegin(GL_POLYGON); + for (const Vec3d& vertex : m_planes[i].vertices) + { + ::glVertex3dv(vertex.data()); + } + ::glEnd(); + } + ::glPopMatrix(); + } + + ::glEnable(GL_CULL_FACE); + ::glDisable(GL_BLEND); +} + +void GLGizmoFlatten::on_render_for_picking(const GLCanvas3D::Selection& selection) const +{ + ::glDisable(GL_DEPTH_TEST); + ::glDisable(GL_BLEND); + + if (selection.is_single_full_instance()) + { + const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(); + ::glPushMatrix(); + ::glTranslatef(0.f, 0.f, selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z()); + ::glMultMatrixd(m.data()); + if (this->is_plane_update_necessary()) + const_cast(this)->update_planes(); + for (int i = 0; i < (int)m_planes.size(); ++i) + { + ::glColor3fv(picking_color_component(i).data()); + ::glBegin(GL_POLYGON); + for (const Vec3d& vertex : m_planes[i].vertices) + { + ::glVertex3dv(vertex.data()); + } + ::glEnd(); + } + ::glPopMatrix(); + } + + ::glEnable(GL_CULL_FACE); +} + +void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) +{ + m_starting_center = Vec3d::Zero(); + if (m_model_object != model_object) { + m_planes.clear(); + m_planes_valid = false; + } + m_model_object = model_object; +} + +void GLGizmoFlatten::update_planes() +{ + TriangleMesh ch; + for (const ModelVolume* vol : m_model_object->volumes) + { + if (vol->type() != ModelVolumeType::MODEL_PART) + continue; + TriangleMesh vol_ch = vol->get_convex_hull(); + vol_ch.transform(vol->get_matrix()); + ch.merge(vol_ch); + } + ch = ch.convex_hull_3d(); + m_planes.clear(); + const Transform3d& inst_matrix = m_model_object->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) + const float minimal_side = 1.f; // mm + + // Now we'll go through all the facets and append Points of facets sharing the same normal. + // This part is still performed in mesh coordinate system. + const int num_of_facets = ch.stl.stats.number_of_facets; + std::vector facet_queue(num_of_facets, 0); + std::vector facet_visited(num_of_facets, false); + int facet_queue_cnt = 0; + const stl_normal* normal_ptr = nullptr; + while (1) { + // Find next unvisited triangle: + int facet_idx = 0; + for (; facet_idx < num_of_facets; ++ facet_idx) + if (!facet_visited[facet_idx]) { + facet_queue[facet_queue_cnt ++] = facet_idx; + facet_visited[facet_idx] = true; + normal_ptr = &ch.stl.facet_start[facet_idx].normal; + m_planes.emplace_back(); + break; + } + if (facet_idx == num_of_facets) + break; // Everything was visited already + + while (facet_queue_cnt > 0) { + int facet_idx = facet_queue[-- facet_queue_cnt]; + const stl_normal& this_normal = ch.stl.facet_start[facet_idx].normal; + if (std::abs(this_normal(0) - (*normal_ptr)(0)) < 0.001 && std::abs(this_normal(1) - (*normal_ptr)(1)) < 0.001 && std::abs(this_normal(2) - (*normal_ptr)(2)) < 0.001) { + stl_vertex* first_vertex = ch.stl.facet_start[facet_idx].vertex; + for (int j=0; j<3; ++j) + m_planes.back().vertices.emplace_back((double)first_vertex[j](0), (double)first_vertex[j](1), (double)first_vertex[j](2)); + + facet_visited[facet_idx] = true; + for (int j = 0; j < 3; ++ j) { + int neighbor_idx = ch.stl.neighbors_start[facet_idx].neighbor[j]; + if (! facet_visited[neighbor_idx]) + facet_queue[facet_queue_cnt ++] = neighbor_idx; + } + } + } + m_planes.back().normal = normal_ptr->cast(); + + // Now we'll transform all the points into world coordinates, so that the areas, angles and distances + // make real sense. + m_planes.back().vertices = transform(m_planes.back().vertices, inst_matrix); + + // if this is a just a very small triangle, remove it to speed up further calculations (it would be rejected later anyway): + if (m_planes.back().vertices.size() == 3 && + ((m_planes.back().vertices[0] - m_planes.back().vertices[1]).norm() < minimal_side + || (m_planes.back().vertices[0] - m_planes.back().vertices[2]).norm() < minimal_side + || (m_planes.back().vertices[1] - m_planes.back().vertices[2]).norm() < minimal_side)) + m_planes.pop_back(); + } + + // Let's prepare transformation of the normal vector from mesh to instance coordinates. + Geometry::Transformation t(inst_matrix); + Vec3d scaling = t.get_scaling_factor(); + t.set_scaling_factor(Vec3d(1./scaling(0), 1./scaling(1), 1./scaling(2))); + + // Now we'll go through all the polygons, transform the points into xy plane to process them: + for (unsigned int polygon_id=0; polygon_id < m_planes.size(); ++polygon_id) { + Pointf3s& polygon = m_planes[polygon_id].vertices; + const Vec3d& normal = m_planes[polygon_id].normal; + + // transform the normal according to the instance matrix: + Vec3d normal_transformed = t.get_matrix() * normal; + + // We are going to rotate about z and y to flatten the plane + Eigen::Quaterniond q; + Transform3d m = Transform3d::Identity(); + m.matrix().block(0, 0, 3, 3) = q.setFromTwoVectors(normal_transformed, Vec3d::UnitZ()).toRotationMatrix(); + polygon = transform(polygon, m); + + // Now to remove the inner points. We'll misuse Geometry::convex_hull for that, but since + // it works in fixed point representation, we will rescale the polygon to avoid overflows. + // And yes, it is a nasty thing to do. Whoever has time is free to refactor. + Vec3d bb_size = BoundingBoxf3(polygon).size(); + float sf = std::min(1./bb_size(0), 1./bb_size(1)); + Transform3d tr = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), Vec3d(sf, sf, 1.f)); + polygon = transform(polygon, tr); + polygon = Slic3r::Geometry::convex_hull(polygon); + polygon = transform(polygon, tr.inverse()); + + // Calculate area of the polygons and discard ones that are too small + float& area = m_planes[polygon_id].area; + area = 0.f; + for (unsigned int i = 0; i < polygon.size(); i++) // Shoelace formula + area += polygon[i](0)*polygon[i + 1 < polygon.size() ? i + 1 : 0](1) - polygon[i + 1 < polygon.size() ? i + 1 : 0](0)*polygon[i](1); + area = 0.5f * std::abs(area); + + bool discard = false; + if (area < minimal_area) + discard = true; + else { + // We also check the inner angles and discard polygons with angles smaller than the following threshold + const double angle_threshold = ::cos(10.0 * (double)PI / 180.0); + + for (unsigned int i = 0; i < polygon.size(); ++i) { + const Vec3d& prec = polygon[(i == 0) ? polygon.size() - 1 : i - 1]; + const Vec3d& curr = polygon[i]; + const Vec3d& next = polygon[(i == polygon.size() - 1) ? 0 : i + 1]; + + if ((prec - curr).normalized().dot((next - curr).normalized()) > angle_threshold) { + discard = true; + break; + } + } + } + + if (discard) { + m_planes.erase(m_planes.begin() + (polygon_id--)); + continue; + } + + // We will shrink the polygon a little bit so it does not touch the object edges: + Vec3d centroid = std::accumulate(polygon.begin(), polygon.end(), Vec3d(0.0, 0.0, 0.0)); + centroid /= (double)polygon.size(); + for (auto& vertex : polygon) + vertex = 0.9f*vertex + 0.1f*centroid; + + // Polygon is now simple and convex, we'll round the corners to make them look nicer. + // The algorithm takes a vertex, calculates middles of respective sides and moves the vertex + // towards their average (controlled by 'aggressivity'). This is repeated k times. + // In next iterations, the neighbours are not always taken at the middle (to increase the + // rounding effect at the corners, where we need it most). + const unsigned int k = 10; // number of iterations + const float aggressivity = 0.2f; // agressivity + const unsigned int N = polygon.size(); + std::vector> neighbours; + if (k != 0) { + Pointf3s points_out(2*k*N); // vector long enough to store the future vertices + for (unsigned int j=0; jvolumes) { + 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_planes_valid = true; +} + + +bool GLGizmoFlatten::is_plane_update_necessary() const +{ + if (m_state != On || !m_model_object || m_model_object->instances.empty()) + return false; + + if (! m_planes_valid || m_model_object->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)) + 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]) + return true; + + return false; +} + +Vec3d GLGizmoFlatten::get_flattening_normal() const +{ + Vec3d out = m_normal; + m_normal = Vec3d::Zero(); + m_starting_center = Vec3d::Zero(); + return out; +} + +} // namespace GUI +} // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp new file mode 100644 index 000000000..c91924c5a --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp @@ -0,0 +1,67 @@ +#ifndef slic3r_GLGizmoFlatten_hpp_ +#define slic3r_GLGizmoFlatten_hpp_ + +#include "GLGizmoBase.hpp" + + +namespace Slic3r { +namespace GUI { + + +class GLGizmoFlatten : public GLGizmoBase +{ +// This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself. + +private: + mutable Vec3d m_normal; + + struct PlaneData { + std::vector vertices; + Vec3d normal; + float area; + }; + + // This holds information to decide whether recalculation is necessary: + std::vector m_volumes_matrices; + std::vector m_volumes_types; + Vec3d m_first_instance_scale; + Vec3d m_first_instance_mirror; + + std::vector m_planes; + bool m_planes_valid = false; + mutable Vec3d m_starting_center; + const ModelObject* m_model_object = nullptr; + std::vector instances_matrices; + + void update_planes(); + bool is_plane_update_necessary() const; + +public: +#if ENABLE_SVG_ICONS + GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); +#else + GLGizmoFlatten(GLCanvas3D& parent, unsigned int sprite_id); +#endif // ENABLE_SVG_ICONS + + void set_flattening_data(const ModelObject* model_object); + Vec3d get_flattening_normal() const; + +protected: + virtual bool on_init(); + virtual std::string on_get_name() const; + virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const; + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); + virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) {} + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; + virtual void on_set_state() + { + if (m_state == On && is_plane_update_necessary()) + update_planes(); + } +}; + +} // namespace GUI +} // namespace Slic3r + +#endif // slic3r_GLGizmoFlatten_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp new file mode 100644 index 000000000..38b0ce23b --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -0,0 +1,257 @@ +// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. +#include "GLGizmoMove.hpp" + +#include + + +namespace Slic3r { +namespace GUI { + +const double GLGizmoMove3D::Offset = 10.0; + +#if ENABLE_SVG_ICONS +GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) + : GLGizmoBase(parent, icon_filename, sprite_id) +#else +GLGizmoMove3D::GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) +#endif // ENABLE_SVG_ICONS + , m_displacement(Vec3d::Zero()) + , m_snap_step(1.0) + , m_starting_drag_position(Vec3d::Zero()) + , m_starting_box_center(Vec3d::Zero()) + , m_starting_box_bottom_center(Vec3d::Zero()) + , m_quadric(nullptr) +{ + m_quadric = ::gluNewQuadric(); + if (m_quadric != nullptr) + ::gluQuadricDrawStyle(m_quadric, GLU_FILL); +} + +GLGizmoMove3D::~GLGizmoMove3D() +{ + if (m_quadric != nullptr) + ::gluDeleteQuadric(m_quadric); +} + +bool GLGizmoMove3D::on_init() +{ + for (int i = 0; i < 3; ++i) + { + m_grabbers.push_back(Grabber()); + } + + m_shortcut_key = WXK_CONTROL_M; + + return true; +} + +std::string GLGizmoMove3D::on_get_name() const +{ + return L("Move [M]"); +} + +void GLGizmoMove3D::on_start_dragging(const GLCanvas3D::Selection& selection) +{ + if (m_hover_id != -1) + { + m_displacement = Vec3d::Zero(); + const BoundingBoxf3& box = selection.get_bounding_box(); + m_starting_drag_position = m_grabbers[m_hover_id].center; + m_starting_box_center = box.center(); + m_starting_box_bottom_center = box.center(); + m_starting_box_bottom_center(2) = box.min(2); + } +} + +void GLGizmoMove3D::on_stop_dragging() +{ + m_displacement = Vec3d::Zero(); +} + +void GLGizmoMove3D::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) +{ + if (m_hover_id == 0) + m_displacement(0) = calc_projection(data); + else if (m_hover_id == 1) + m_displacement(1) = calc_projection(data); + else if (m_hover_id == 2) + m_displacement(2) = calc_projection(data); +} + +void GLGizmoMove3D::on_render(const GLCanvas3D::Selection& selection) const +{ + bool show_position = selection.is_single_full_instance(); + const Vec3d& position = selection.get_bounding_box().center(); + + if ((show_position && (m_hover_id == 0)) || m_grabbers[0].dragging) + set_tooltip("X: " + format(show_position ? position(0) : m_displacement(0), 2)); + else if (!m_grabbers[0].dragging && (m_hover_id == 0)) + set_tooltip("X"); + else if ((show_position && (m_hover_id == 1)) || m_grabbers[1].dragging) + set_tooltip("Y: " + format(show_position ? position(1) : m_displacement(1), 2)); + else if (!m_grabbers[1].dragging && (m_hover_id == 1)) + set_tooltip("Y"); + else if ((show_position && (m_hover_id == 2)) || m_grabbers[2].dragging) + set_tooltip("Z: " + format(show_position ? position(2) : m_displacement(2), 2)); + else if (!m_grabbers[2].dragging && (m_hover_id == 2)) + set_tooltip("Z"); + + ::glClear(GL_DEPTH_BUFFER_BIT); + ::glEnable(GL_DEPTH_TEST); + + const BoundingBoxf3& box = selection.get_bounding_box(); + const Vec3d& center = box.center(); + + // x axis + m_grabbers[0].center = Vec3d(box.max(0) + Offset, center(1), center(2)); + ::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); + + // y axis + m_grabbers[1].center = Vec3d(center(0), box.max(1) + Offset, center(2)); + ::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); + + // z axis + m_grabbers[2].center = Vec3d(center(0), center(1), box.max(2) + Offset); + ::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); + + ::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f); + + if (m_hover_id == -1) + { + // draw axes + for (unsigned int i = 0; i < 3; ++i) + { + if (m_grabbers[i].enabled) + { + ::glColor3fv(AXES_COLOR[i]); + ::glBegin(GL_LINES); + ::glVertex3dv(center.data()); + ::glVertex3dv(m_grabbers[i].center.data()); + ::glEnd(); + } + } + + // draw grabbers + render_grabbers(box); + for (unsigned int i = 0; i < 3; ++i) + { + if (m_grabbers[i].enabled) + render_grabber_extension((Axis)i, box, false); + } + } + else + { + // draw axis + ::glColor3fv(AXES_COLOR[m_hover_id]); + ::glBegin(GL_LINES); + ::glVertex3dv(center.data()); + ::glVertex3dv(m_grabbers[m_hover_id].center.data()); + ::glEnd(); + + // draw grabber + m_grabbers[m_hover_id].render(true, box.max_size()); + render_grabber_extension((Axis)m_hover_id, box, false); + } +} + +void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const +{ + ::glDisable(GL_DEPTH_TEST); + + const BoundingBoxf3& box = selection.get_bounding_box(); + render_grabbers_for_picking(box); + render_grabber_extension(X, box, true); + render_grabber_extension(Y, box, true); + render_grabber_extension(Z, box, true); +} + +#if ENABLE_IMGUI +void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) +{ +#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI + bool show_position = selection.is_single_full_instance(); + const Vec3d& position = selection.get_bounding_box().center(); + + Vec3d displacement = show_position ? position : m_displacement; + wxString label = show_position ? _(L("Position (mm)")) : _(L("Displacement (mm)")); + + m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); + m_imgui->set_next_window_bg_alpha(0.5f); + m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + m_imgui->input_vec3("", displacement, 100.0f, "%.2f"); + + m_imgui->end(); +#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI +} +#endif // ENABLE_IMGUI + +double GLGizmoMove3D::calc_projection(const UpdateData& data) const +{ + double projection = 0.0; + + Vec3d starting_vec = m_starting_drag_position - m_starting_box_center; + double len_starting_vec = starting_vec.norm(); + if (len_starting_vec != 0.0) + { + Vec3d mouse_dir = data.mouse_ray.unit_vector(); + // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position + // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form + // in our case plane normal and ray direction are the same (orthogonal view) + // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal + Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; + // vector from the starting position to the found intersection + Vec3d inters_vec = inters - m_starting_drag_position; + + // finds projection of the vector along the staring direction + projection = inters_vec.dot(starting_vec.normalized()); + } + + if (data.shift_down) + projection = m_snap_step * (double)std::round(projection / m_snap_step); + + return projection; +} + +void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const +{ + if (m_quadric == nullptr) + return; + + double size = m_dragging ? (double)m_grabbers[axis].get_dragging_half_size((float)box.max_size()) : (double)m_grabbers[axis].get_half_size((float)box.max_size()); + + float color[3]; + ::memcpy((void*)color, (const void*)m_grabbers[axis].color, 3 * sizeof(float)); + if (!picking && (m_hover_id != -1)) + { + color[0] = 1.0f - color[0]; + color[1] = 1.0f - color[1]; + color[2] = 1.0f - color[2]; + } + + if (!picking) + ::glEnable(GL_LIGHTING); + + ::glColor3fv(color); + ::glPushMatrix(); + ::glTranslated(m_grabbers[axis].center(0), m_grabbers[axis].center(1), m_grabbers[axis].center(2)); + if (axis == X) + ::glRotated(90.0, 0.0, 1.0, 0.0); + else if (axis == Y) + ::glRotated(-90.0, 1.0, 0.0, 0.0); + + ::glTranslated(0.0, 0.0, 2.0 * size); + ::gluQuadricOrientation(m_quadric, GLU_OUTSIDE); + ::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1); + ::gluQuadricOrientation(m_quadric, GLU_INSIDE); + ::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1); + ::glPopMatrix(); + + if (!picking) + ::glDisable(GL_LIGHTING); +} + + + +} // namespace GUI +} // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp new file mode 100644 index 000000000..72b067ba9 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -0,0 +1,60 @@ +#ifndef slic3r_GLGizmoMove_hpp_ +#define slic3r_GLGizmoMove_hpp_ + +#include "GLGizmoBase.hpp" + + +namespace Slic3r { +namespace GUI { + +class GLGizmoMove3D : public GLGizmoBase +{ + static const double Offset; + + Vec3d m_displacement; + + double m_snap_step; + + Vec3d m_starting_drag_position; + Vec3d m_starting_box_center; + Vec3d m_starting_box_bottom_center; + + GLUquadricObj* m_quadric; + +public: +#if ENABLE_SVG_ICONS + GLGizmoMove3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); +#else + GLGizmoMove3D(GLCanvas3D& parent, unsigned int sprite_id); +#endif // ENABLE_SVG_ICONS + virtual ~GLGizmoMove3D(); + + double get_snap_step(double step) const { return m_snap_step; } + void set_snap_step(double step) { m_snap_step = step; } + + const Vec3d& get_displacement() const { return m_displacement; } + +protected: + virtual bool on_init(); + virtual std::string on_get_name() const; + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); + virtual void on_stop_dragging(); + virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; + +#if ENABLE_IMGUI + virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); +#endif // ENABLE_IMGUI + +private: + double calc_projection(const UpdateData& data) const; + void render_grabber_extension(Axis axis, const BoundingBoxf3& box, bool picking) const; +}; + + + +} // namespace GUI +} // namespace Slic3r + +#endif // slic3r_GLGizmoMove_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp new file mode 100644 index 000000000..89ca426e4 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -0,0 +1,505 @@ +// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. +#include "GLGizmoRotate.hpp" + +#include + + +namespace Slic3r { +namespace GUI { + + +const float GLGizmoRotate::Offset = 5.0f; +const unsigned int GLGizmoRotate::CircleResolution = 64; +const unsigned int GLGizmoRotate::AngleResolution = 64; +const unsigned int GLGizmoRotate::ScaleStepsCount = 72; +const float GLGizmoRotate::ScaleStepRad = 2.0f * (float)PI / GLGizmoRotate::ScaleStepsCount; +const unsigned int GLGizmoRotate::ScaleLongEvery = 2; +const float GLGizmoRotate::ScaleLongTooth = 0.1f; // in percent of radius +const unsigned int GLGizmoRotate::SnapRegionsCount = 8; +const float GLGizmoRotate::GrabberOffset = 0.15f; // in percent of radius + +GLGizmoRotate::GLGizmoRotate(GLCanvas3D& parent, GLGizmoRotate::Axis axis) +#if ENABLE_SVG_ICONS + : GLGizmoBase(parent, "", -1) +#else + : GLGizmoBase(parent, -1) +#endif // ENABLE_SVG_ICONS + , m_axis(axis) + , m_angle(0.0) + , m_quadric(nullptr) + , m_center(0.0, 0.0, 0.0) + , m_radius(0.0f) + , m_snap_coarse_in_radius(0.0f) + , m_snap_coarse_out_radius(0.0f) + , m_snap_fine_in_radius(0.0f) + , m_snap_fine_out_radius(0.0f) +{ + m_quadric = ::gluNewQuadric(); + if (m_quadric != nullptr) + ::gluQuadricDrawStyle(m_quadric, GLU_FILL); +} + +GLGizmoRotate::GLGizmoRotate(const GLGizmoRotate& other) +#if ENABLE_SVG_ICONS + : GLGizmoBase(other.m_parent, other.m_icon_filename, other.m_sprite_id) +#else + : GLGizmoBase(other.m_parent, other.m_sprite_id) +#endif // ENABLE_SVG_ICONS + , m_axis(other.m_axis) + , m_angle(other.m_angle) + , m_quadric(nullptr) + , m_center(other.m_center) + , m_radius(other.m_radius) + , m_snap_coarse_in_radius(other.m_snap_coarse_in_radius) + , m_snap_coarse_out_radius(other.m_snap_coarse_out_radius) + , m_snap_fine_in_radius(other.m_snap_fine_in_radius) + , m_snap_fine_out_radius(other.m_snap_fine_out_radius) +{ + m_quadric = ::gluNewQuadric(); + if (m_quadric != nullptr) + ::gluQuadricDrawStyle(m_quadric, GLU_FILL); +} + +GLGizmoRotate::~GLGizmoRotate() +{ + if (m_quadric != nullptr) + ::gluDeleteQuadric(m_quadric); +} + +void GLGizmoRotate::set_angle(double angle) +{ + if (std::abs(angle - 2.0 * (double)PI) < EPSILON) + angle = 0.0; + + m_angle = angle; +} + +bool GLGizmoRotate::on_init() +{ + m_grabbers.push_back(Grabber()); + return true; +} + +void GLGizmoRotate::on_start_dragging(const GLCanvas3D::Selection& selection) +{ + const BoundingBoxf3& box = selection.get_bounding_box(); + m_center = box.center(); + m_radius = Offset + box.radius(); + m_snap_coarse_in_radius = m_radius / 3.0f; + m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius; + m_snap_fine_in_radius = m_radius; + m_snap_fine_out_radius = m_snap_fine_in_radius + m_radius * ScaleLongTooth; +} + +void GLGizmoRotate::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) +{ + Vec2d mouse_pos = to_2d(mouse_position_in_local_plane(data.mouse_ray, selection)); + + Vec2d orig_dir = Vec2d::UnitX(); + Vec2d new_dir = mouse_pos.normalized(); + + double theta = ::acos(clamp(-1.0, 1.0, new_dir.dot(orig_dir))); + if (cross2(orig_dir, new_dir) < 0.0) + theta = 2.0 * (double)PI - theta; + + double len = mouse_pos.norm(); + + // snap to coarse snap region + if ((m_snap_coarse_in_radius <= len) && (len <= m_snap_coarse_out_radius)) + { + double step = 2.0 * (double)PI / (double)SnapRegionsCount; + theta = step * (double)std::round(theta / step); + } + else + { + // snap to fine snap region (scale) + if ((m_snap_fine_in_radius <= len) && (len <= m_snap_fine_out_radius)) + { + double step = 2.0 * (double)PI / (double)ScaleStepsCount; + theta = step * (double)std::round(theta / step); + } + } + + if (theta == 2.0 * (double)PI) + theta = 0.0; + + m_angle = theta; +} + +void GLGizmoRotate::on_render(const GLCanvas3D::Selection& selection) const +{ + if (!m_grabbers[0].enabled) + return; + + const BoundingBoxf3& box = selection.get_bounding_box(); + + std::string axis; + switch (m_axis) + { + case X: { axis = "X"; break; } + case Y: { axis = "Y"; break; } + case Z: { axis = "Z"; break; } + } + + if (!m_dragging && (m_hover_id == 0)) + set_tooltip(axis); + else if (m_dragging) + set_tooltip(axis + ": " + format((float)Geometry::rad2deg(m_angle), 4) + "\u00B0"); + else + { + m_center = box.center(); + m_radius = Offset + box.radius(); + m_snap_coarse_in_radius = m_radius / 3.0f; + m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius; + m_snap_fine_in_radius = m_radius; + m_snap_fine_out_radius = m_radius * (1.0f + ScaleLongTooth); + } + + ::glEnable(GL_DEPTH_TEST); + + ::glPushMatrix(); + transform_to_local(selection); + + ::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f); + ::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color); + + render_circle(); + + if (m_hover_id != -1) + { + render_scale(); + render_snap_radii(); + render_reference_radius(); + } + + ::glColor3fv(m_highlight_color); + + if (m_hover_id != -1) + render_angle(); + + render_grabber(box); + render_grabber_extension(box, false); + + ::glPopMatrix(); +} + +void GLGizmoRotate::on_render_for_picking(const GLCanvas3D::Selection& selection) const +{ + ::glDisable(GL_DEPTH_TEST); + + ::glPushMatrix(); + + transform_to_local(selection); + + const BoundingBoxf3& box = selection.get_bounding_box(); + render_grabbers_for_picking(box); + render_grabber_extension(box, true); + + ::glPopMatrix(); +} + +void GLGizmoRotate::render_circle() const +{ + ::glBegin(GL_LINE_LOOP); + for (unsigned int i = 0; i < ScaleStepsCount; ++i) + { + float angle = (float)i * ScaleStepRad; + float x = ::cos(angle) * m_radius; + float y = ::sin(angle) * m_radius; + float z = 0.0f; + ::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z); + } + ::glEnd(); +} + +void GLGizmoRotate::render_scale() const +{ + float out_radius_long = m_snap_fine_out_radius; + float out_radius_short = m_radius * (1.0f + 0.5f * ScaleLongTooth); + + ::glBegin(GL_LINES); + for (unsigned int i = 0; i < ScaleStepsCount; ++i) + { + float angle = (float)i * ScaleStepRad; + float cosa = ::cos(angle); + float sina = ::sin(angle); + float in_x = cosa * m_radius; + float in_y = sina * m_radius; + float in_z = 0.0f; + float out_x = (i % ScaleLongEvery == 0) ? cosa * out_radius_long : cosa * out_radius_short; + float out_y = (i % ScaleLongEvery == 0) ? sina * out_radius_long : sina * out_radius_short; + float out_z = 0.0f; + ::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z); + ::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z); + } + ::glEnd(); +} + +void GLGizmoRotate::render_snap_radii() const +{ + float step = 2.0f * (float)PI / (float)SnapRegionsCount; + + float in_radius = m_radius / 3.0f; + float out_radius = 2.0f * in_radius; + + ::glBegin(GL_LINES); + for (unsigned int i = 0; i < SnapRegionsCount; ++i) + { + float angle = (float)i * step; + float cosa = ::cos(angle); + float sina = ::sin(angle); + float in_x = cosa * in_radius; + float in_y = sina * in_radius; + float in_z = 0.0f; + float out_x = cosa * out_radius; + float out_y = sina * out_radius; + float out_z = 0.0f; + ::glVertex3f((GLfloat)in_x, (GLfloat)in_y, (GLfloat)in_z); + ::glVertex3f((GLfloat)out_x, (GLfloat)out_y, (GLfloat)out_z); + } + ::glEnd(); +} + +void GLGizmoRotate::render_reference_radius() const +{ + ::glBegin(GL_LINES); + ::glVertex3f(0.0f, 0.0f, 0.0f); + ::glVertex3f((GLfloat)(m_radius * (1.0f + GrabberOffset)), 0.0f, 0.0f); + ::glEnd(); +} + +void GLGizmoRotate::render_angle() const +{ + float step_angle = (float)m_angle / AngleResolution; + float ex_radius = m_radius * (1.0f + GrabberOffset); + + ::glBegin(GL_LINE_STRIP); + for (unsigned int i = 0; i <= AngleResolution; ++i) + { + float angle = (float)i * step_angle; + float x = ::cos(angle) * ex_radius; + float y = ::sin(angle) * ex_radius; + float z = 0.0f; + ::glVertex3f((GLfloat)x, (GLfloat)y, (GLfloat)z); + } + ::glEnd(); +} + +void GLGizmoRotate::render_grabber(const BoundingBoxf3& box) const +{ + double grabber_radius = (double)m_radius * (1.0 + (double)GrabberOffset); + m_grabbers[0].center = Vec3d(::cos(m_angle) * grabber_radius, ::sin(m_angle) * grabber_radius, 0.0); + m_grabbers[0].angles(2) = m_angle; + + ::glColor3fv((m_hover_id != -1) ? m_drag_color : m_highlight_color); + + ::glBegin(GL_LINES); + ::glVertex3f(0.0f, 0.0f, 0.0f); + ::glVertex3dv(m_grabbers[0].center.data()); + ::glEnd(); + + ::memcpy((void*)m_grabbers[0].color, (const void*)m_highlight_color, 3 * sizeof(float)); + render_grabbers(box); +} + +void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool picking) const +{ + if (m_quadric == nullptr) + return; + + double size = m_dragging ? (double)m_grabbers[0].get_dragging_half_size((float)box.max_size()) : (double)m_grabbers[0].get_half_size((float)box.max_size()); + + float color[3]; + ::memcpy((void*)color, (const void*)m_grabbers[0].color, 3 * sizeof(float)); + if (!picking && (m_hover_id != -1)) + { + color[0] = 1.0f - color[0]; + color[1] = 1.0f - color[1]; + color[2] = 1.0f - color[2]; + } + + if (!picking) + ::glEnable(GL_LIGHTING); + + ::glColor3fv(color); + ::glPushMatrix(); + ::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2)); + ::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0); + ::glRotated(90.0, 1.0, 0.0, 0.0); + ::glTranslated(0.0, 0.0, 2.0 * size); + ::gluQuadricOrientation(m_quadric, GLU_OUTSIDE); + ::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1); + ::gluQuadricOrientation(m_quadric, GLU_INSIDE); + ::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1); + ::glPopMatrix(); + ::glPushMatrix(); + ::glTranslated(m_grabbers[0].center(0), m_grabbers[0].center(1), m_grabbers[0].center(2)); + ::glRotated(Geometry::rad2deg(m_angle), 0.0, 0.0, 1.0); + ::glRotated(-90.0, 1.0, 0.0, 0.0); + ::glTranslated(0.0, 0.0, 2.0 * size); + ::gluQuadricOrientation(m_quadric, GLU_OUTSIDE); + ::gluCylinder(m_quadric, 0.75 * size, 0.0, 3.0 * size, 36, 1); + ::gluQuadricOrientation(m_quadric, GLU_INSIDE); + ::gluDisk(m_quadric, 0.0, 0.75 * size, 36, 1); + ::glPopMatrix(); + + if (!picking) + ::glDisable(GL_LIGHTING); +} + +void GLGizmoRotate::transform_to_local(const GLCanvas3D::Selection& selection) const +{ + ::glTranslated(m_center(0), m_center(1), m_center(2)); + + if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) + { + Transform3d orient_matrix = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true); + ::glMultMatrixd(orient_matrix.data()); + } + + switch (m_axis) + { + case X: + { + ::glRotatef(90.0f, 0.0f, 1.0f, 0.0f); + ::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f); + break; + } + case Y: + { + ::glRotatef(-90.0f, 0.0f, 0.0f, 1.0f); + ::glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); + break; + } + default: + case Z: + { + // no rotation + break; + } + } +} + +Vec3d GLGizmoRotate::mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const +{ + double half_pi = 0.5 * (double)PI; + + Transform3d m = Transform3d::Identity(); + + switch (m_axis) + { + case X: + { + m.rotate(Eigen::AngleAxisd(half_pi, Vec3d::UnitZ())); + m.rotate(Eigen::AngleAxisd(-half_pi, Vec3d::UnitY())); + break; + } + case Y: + { + m.rotate(Eigen::AngleAxisd(half_pi, Vec3d::UnitY())); + m.rotate(Eigen::AngleAxisd(half_pi, Vec3d::UnitZ())); + break; + } + default: + case Z: + { + // no rotation applied + break; + } + } + + if (selection.is_single_volume() || selection.is_single_modifier() || selection.requires_local_axes()) + m = m * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix(true, false, true, true).inverse(); + + m.translate(-m_center); + + return transform(mouse_ray, m).intersect_plane(0.0); +} + +#if ENABLE_SVG_ICONS +GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) + : GLGizmoBase(parent, icon_filename, sprite_id) +#else +GLGizmoRotate3D::GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) +#endif // ENABLE_SVG_ICONS +{ + m_gizmos.emplace_back(parent, GLGizmoRotate::X); + m_gizmos.emplace_back(parent, GLGizmoRotate::Y); + m_gizmos.emplace_back(parent, GLGizmoRotate::Z); + + for (unsigned int i = 0; i < 3; ++i) + { + m_gizmos[i].set_group_id(i); + } +} + +bool GLGizmoRotate3D::on_init() +{ + for (GLGizmoRotate& g : m_gizmos) + { + if (!g.init()) + return false; + } + + for (unsigned int i = 0; i < 3; ++i) + { + m_gizmos[i].set_highlight_color(AXES_COLOR[i]); + } + + m_shortcut_key = WXK_CONTROL_R; + + return true; +} + +std::string GLGizmoRotate3D::on_get_name() const +{ + return L("Rotate [R]"); +} + +void GLGizmoRotate3D::on_start_dragging(const GLCanvas3D::Selection& selection) +{ + if ((0 <= m_hover_id) && (m_hover_id < 3)) + m_gizmos[m_hover_id].start_dragging(selection); +} + +void GLGizmoRotate3D::on_stop_dragging() +{ + if ((0 <= m_hover_id) && (m_hover_id < 3)) + m_gizmos[m_hover_id].stop_dragging(); +} + +void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const +{ + ::glClear(GL_DEPTH_BUFFER_BIT); + + if ((m_hover_id == -1) || (m_hover_id == 0)) + m_gizmos[X].render(selection); + + if ((m_hover_id == -1) || (m_hover_id == 1)) + m_gizmos[Y].render(selection); + + if ((m_hover_id == -1) || (m_hover_id == 2)) + m_gizmos[Z].render(selection); +} + +#if ENABLE_IMGUI +void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) +{ +#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI + Vec3d rotation(Geometry::rad2deg(m_gizmos[0].get_angle()), Geometry::rad2deg(m_gizmos[1].get_angle()), Geometry::rad2deg(m_gizmos[2].get_angle())); + wxString label = _(L("Rotation (deg)")); + + m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); + m_imgui->set_next_window_bg_alpha(0.5f); + m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + m_imgui->input_vec3("", rotation, 100.0f, "%.2f"); + m_imgui->end(); +#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI +} +#endif // ENABLE_IMGUI + + + +} // namespace GUI +} // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp new file mode 100644 index 000000000..6281f98cb --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -0,0 +1,144 @@ +#ifndef slic3r_GLGizmoRotate_hpp_ +#define slic3r_GLGizmoRotate_hpp_ + +#include "GLGizmoBase.hpp" + + +namespace Slic3r { +namespace GUI { + +class GLGizmoRotate : public GLGizmoBase +{ + static const float Offset; + static const unsigned int CircleResolution; + static const unsigned int AngleResolution; + static const unsigned int ScaleStepsCount; + static const float ScaleStepRad; + static const unsigned int ScaleLongEvery; + static const float ScaleLongTooth; + static const unsigned int SnapRegionsCount; + static const float GrabberOffset; + +public: + enum Axis : unsigned char + { + X, + Y, + Z + }; + +private: + Axis m_axis; + double m_angle; + + GLUquadricObj* m_quadric; + + mutable Vec3d m_center; + mutable float m_radius; + + mutable float m_snap_coarse_in_radius; + mutable float m_snap_coarse_out_radius; + mutable float m_snap_fine_in_radius; + mutable float m_snap_fine_out_radius; + +public: + GLGizmoRotate(GLCanvas3D& parent, Axis axis); + GLGizmoRotate(const GLGizmoRotate& other); + virtual ~GLGizmoRotate(); + + double get_angle() const { return m_angle; } + void set_angle(double angle); + +protected: + virtual bool on_init(); + virtual std::string on_get_name() const { return ""; } + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); + virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; + +private: + void render_circle() const; + void render_scale() const; + void render_snap_radii() const; + void render_reference_radius() const; + void render_angle() const; + void render_grabber(const BoundingBoxf3& box) const; + void render_grabber_extension(const BoundingBoxf3& box, bool picking) const; + + void transform_to_local(const GLCanvas3D::Selection& selection) const; + // returns the intersection of the mouse ray with the plane perpendicular to the gizmo axis, in local coordinate + Vec3d mouse_position_in_local_plane(const Linef3& mouse_ray, const GLCanvas3D::Selection& selection) const; +}; + +class GLGizmoRotate3D : public GLGizmoBase +{ + std::vector m_gizmos; + +public: +#if ENABLE_SVG_ICONS + GLGizmoRotate3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); +#else + GLGizmoRotate3D(GLCanvas3D& parent, unsigned int sprite_id); +#endif // ENABLE_SVG_ICONS + + Vec3d get_rotation() const { return Vec3d(m_gizmos[X].get_angle(), m_gizmos[Y].get_angle(), m_gizmos[Z].get_angle()); } + void set_rotation(const Vec3d& rotation) { m_gizmos[X].set_angle(rotation(0)); m_gizmos[Y].set_angle(rotation(1)); m_gizmos[Z].set_angle(rotation(2)); } + +protected: + virtual bool on_init(); + virtual std::string on_get_name() const; + virtual void on_set_state() + { + for (GLGizmoRotate& g : m_gizmos) + { + g.set_state(m_state); + } + } + virtual void on_set_hover_id() + { + for (unsigned int i = 0; i < 3; ++i) + { + m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1); + } + } + virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); } + virtual void on_enable_grabber(unsigned int id) + { + if ((0 <= id) && (id < 3)) + m_gizmos[id].enable_grabber(0); + } + virtual void on_disable_grabber(unsigned int id) + { + if ((0 <= id) && (id < 3)) + m_gizmos[id].disable_grabber(0); + } + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); + virtual void on_stop_dragging(); + virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) + { + for (GLGizmoRotate& g : m_gizmos) + { + g.update(data, selection); + } + } + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const + { + for (const GLGizmoRotate& g : m_gizmos) + { + g.render_for_picking(selection); + } + } + +#if ENABLE_IMGUI + virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); +#endif // ENABLE_IMGUI +}; + + + +} // namespace GUI +} // namespace Slic3r + +#endif // slic3r_GLGizmoRotate_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp new file mode 100644 index 000000000..bb0663e36 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -0,0 +1,364 @@ + + +// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. +#include "GLGizmoScale.hpp" + +#include + +namespace Slic3r { +namespace GUI { + + +const float GLGizmoScale3D::Offset = 5.0f; + +#if ENABLE_SVG_ICONS +GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) + : GLGizmoBase(parent, icon_filename, sprite_id) +#else +GLGizmoScale3D::GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) +#endif // ENABLE_SVG_ICONS + , m_scale(Vec3d::Ones()) + , m_snap_step(0.05) + , m_starting_scale(Vec3d::Ones()) +{ +} + +bool GLGizmoScale3D::on_init() +{ + for (int i = 0; i < 10; ++i) + { + m_grabbers.push_back(Grabber()); + } + + double half_pi = 0.5 * (double)PI; + + // x axis + m_grabbers[0].angles(1) = half_pi; + m_grabbers[1].angles(1) = half_pi; + + // y axis + m_grabbers[2].angles(0) = half_pi; + m_grabbers[3].angles(0) = half_pi; + + m_shortcut_key = WXK_CONTROL_S; + + return true; +} + +std::string GLGizmoScale3D::on_get_name() const +{ + return L("Scale [S]"); +} + +void GLGizmoScale3D::on_start_dragging(const GLCanvas3D::Selection& selection) +{ + if (m_hover_id != -1) + { + m_starting_drag_position = m_grabbers[m_hover_id].center; + m_starting_box = selection.get_bounding_box(); + } +} + +void GLGizmoScale3D::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) +{ + if ((m_hover_id == 0) || (m_hover_id == 1)) + do_scale_x(data); + else if ((m_hover_id == 2) || (m_hover_id == 3)) + do_scale_y(data); + else if ((m_hover_id == 4) || (m_hover_id == 5)) + do_scale_z(data); + else if (m_hover_id >= 6) + do_scale_uniform(data); +} + +void GLGizmoScale3D::on_render(const GLCanvas3D::Selection& selection) const +{ + bool single_instance = selection.is_single_full_instance(); + bool single_volume = selection.is_single_modifier() || selection.is_single_volume(); + bool single_selection = single_instance || single_volume; + + Vec3f scale = 100.0f * Vec3f::Ones(); + if (single_instance) + scale = 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_scaling_factor().cast(); + else if (single_volume) + scale = 100.0f * selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_scaling_factor().cast(); + + if ((single_selection && ((m_hover_id == 0) || (m_hover_id == 1))) || m_grabbers[0].dragging || m_grabbers[1].dragging) + set_tooltip("X: " + format(scale(0), 4) + "%"); + else if (!m_grabbers[0].dragging && !m_grabbers[1].dragging && ((m_hover_id == 0) || (m_hover_id == 1))) + set_tooltip("X"); + else if ((single_selection && ((m_hover_id == 2) || (m_hover_id == 3))) || m_grabbers[2].dragging || m_grabbers[3].dragging) + set_tooltip("Y: " + format(scale(1), 4) + "%"); + else if (!m_grabbers[2].dragging && !m_grabbers[3].dragging && ((m_hover_id == 2) || (m_hover_id == 3))) + set_tooltip("Y"); + else if ((single_selection && ((m_hover_id == 4) || (m_hover_id == 5))) || m_grabbers[4].dragging || m_grabbers[5].dragging) + set_tooltip("Z: " + format(scale(2), 4) + "%"); + else if (!m_grabbers[4].dragging && !m_grabbers[5].dragging && ((m_hover_id == 4) || (m_hover_id == 5))) + set_tooltip("Z"); + else if ((single_selection && ((m_hover_id == 6) || (m_hover_id == 7) || (m_hover_id == 8) || (m_hover_id == 9))) + || m_grabbers[6].dragging || m_grabbers[7].dragging || m_grabbers[8].dragging || m_grabbers[9].dragging) + { + std::string tooltip = "X: " + format(scale(0), 4) + "%\n"; + tooltip += "Y: " + format(scale(1), 4) + "%\n"; + tooltip += "Z: " + format(scale(2), 4) + "%"; + set_tooltip(tooltip); + } + else if (!m_grabbers[6].dragging && !m_grabbers[7].dragging && !m_grabbers[8].dragging && !m_grabbers[9].dragging && + ((m_hover_id == 6) || (m_hover_id == 7) || (m_hover_id == 8) || (m_hover_id == 9))) + set_tooltip("X/Y/Z"); + + ::glClear(GL_DEPTH_BUFFER_BIT); + ::glEnable(GL_DEPTH_TEST); + + BoundingBoxf3 box; + Transform3d transform = Transform3d::Identity(); + Vec3d angles = Vec3d::Zero(); + Transform3d offsets_transform = Transform3d::Identity(); + + Vec3d grabber_size = Vec3d::Zero(); + + if (single_instance) + { + // calculate bounding box in instance local reference system + const GLCanvas3D::Selection::IndicesList& idxs = selection.get_volume_idxs(); + for (unsigned int idx : idxs) + { + const GLVolume* vol = selection.get_volume(idx); + box.merge(vol->bounding_box.transformed(vol->get_volume_transformation().get_matrix())); + } + + // gets transform from first selected volume + const GLVolume* v = selection.get_volume(*idxs.begin()); + transform = v->get_instance_transformation().get_matrix(); + // gets angles from first selected volume + angles = v->get_instance_rotation(); + // consider rotation+mirror only components of the transform for offsets + offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror()); + grabber_size = v->get_instance_transformation().get_matrix(true, true, false, true) * box.size(); + } + else if (single_volume) + { + const GLVolume* v = selection.get_volume(*selection.get_volume_idxs().begin()); + box = v->bounding_box; + transform = v->world_matrix(); + angles = Geometry::extract_euler_angles(transform); + // consider rotation+mirror only components of the transform for offsets + offsets_transform = Geometry::assemble_transform(Vec3d::Zero(), angles, Vec3d::Ones(), v->get_instance_mirror()); + grabber_size = v->get_volume_transformation().get_matrix(true, true, false, true) * box.size(); + } + else + { + box = selection.get_bounding_box(); + grabber_size = box.size(); + } + + m_box = box; + + const Vec3d& center = m_box.center(); + Vec3d offset_x = offsets_transform * Vec3d((double)Offset, 0.0, 0.0); + Vec3d offset_y = offsets_transform * Vec3d(0.0, (double)Offset, 0.0); + Vec3d offset_z = offsets_transform * Vec3d(0.0, 0.0, (double)Offset); + + // x axis + m_grabbers[0].center = transform * Vec3d(m_box.min(0), center(1), center(2)) - offset_x; + m_grabbers[1].center = transform * Vec3d(m_box.max(0), center(1), center(2)) + offset_x; + ::memcpy((void*)m_grabbers[0].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[1].color, (const void*)&AXES_COLOR[0], 3 * sizeof(float)); + + // y axis + m_grabbers[2].center = transform * Vec3d(center(0), m_box.min(1), center(2)) - offset_y; + m_grabbers[3].center = transform * Vec3d(center(0), m_box.max(1), center(2)) + offset_y; + ::memcpy((void*)m_grabbers[2].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[3].color, (const void*)&AXES_COLOR[1], 3 * sizeof(float)); + + // z axis + m_grabbers[4].center = transform * Vec3d(center(0), center(1), m_box.min(2)) - offset_z; + m_grabbers[5].center = transform * Vec3d(center(0), center(1), m_box.max(2)) + offset_z; + ::memcpy((void*)m_grabbers[4].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); + ::memcpy((void*)m_grabbers[5].color, (const void*)&AXES_COLOR[2], 3 * sizeof(float)); + + // uniform + m_grabbers[6].center = transform * Vec3d(m_box.min(0), m_box.min(1), center(2)) - offset_x - offset_y; + m_grabbers[7].center = transform * Vec3d(m_box.max(0), m_box.min(1), center(2)) + offset_x - offset_y; + m_grabbers[8].center = transform * Vec3d(m_box.max(0), m_box.max(1), center(2)) + offset_x + offset_y; + m_grabbers[9].center = transform * Vec3d(m_box.min(0), m_box.max(1), center(2)) - offset_x + offset_y; + for (int i = 6; i < 10; ++i) + { + ::memcpy((void*)m_grabbers[i].color, (const void*)m_highlight_color, 3 * sizeof(float)); + } + + // sets grabbers orientation + for (int i = 0; i < 10; ++i) + { + m_grabbers[i].angles = angles; + } + + ::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f); + + float grabber_mean_size = (float)(grabber_size(0) + grabber_size(1) + grabber_size(2)) / 3.0f; + + if (m_hover_id == -1) + { + // draw connections + if (m_grabbers[0].enabled && m_grabbers[1].enabled) + { + ::glColor3fv(m_grabbers[0].color); + render_grabbers_connection(0, 1); + } + if (m_grabbers[2].enabled && m_grabbers[3].enabled) + { + ::glColor3fv(m_grabbers[2].color); + render_grabbers_connection(2, 3); + } + if (m_grabbers[4].enabled && m_grabbers[5].enabled) + { + ::glColor3fv(m_grabbers[4].color); + render_grabbers_connection(4, 5); + } + ::glColor3fv(m_base_color); + render_grabbers_connection(6, 7); + render_grabbers_connection(7, 8); + render_grabbers_connection(8, 9); + render_grabbers_connection(9, 6); + // draw grabbers + render_grabbers(grabber_mean_size); + } + else if ((m_hover_id == 0) || (m_hover_id == 1)) + { + // draw connection + ::glColor3fv(m_grabbers[0].color); + render_grabbers_connection(0, 1); + // draw grabbers + m_grabbers[0].render(true, grabber_mean_size); + m_grabbers[1].render(true, grabber_mean_size); + } + else if ((m_hover_id == 2) || (m_hover_id == 3)) + { + // draw connection + ::glColor3fv(m_grabbers[2].color); + render_grabbers_connection(2, 3); + // draw grabbers + m_grabbers[2].render(true, grabber_mean_size); + m_grabbers[3].render(true, grabber_mean_size); + } + else if ((m_hover_id == 4) || (m_hover_id == 5)) + { + // draw connection + ::glColor3fv(m_grabbers[4].color); + render_grabbers_connection(4, 5); + // draw grabbers + m_grabbers[4].render(true, grabber_mean_size); + m_grabbers[5].render(true, grabber_mean_size); + } + else if (m_hover_id >= 6) + { + // draw connection + ::glColor3fv(m_drag_color); + render_grabbers_connection(6, 7); + render_grabbers_connection(7, 8); + render_grabbers_connection(8, 9); + render_grabbers_connection(9, 6); + // draw grabbers + for (int i = 6; i < 10; ++i) + { + m_grabbers[i].render(true, grabber_mean_size); + } + } +} + +void GLGizmoScale3D::on_render_for_picking(const GLCanvas3D::Selection& selection) const +{ + ::glDisable(GL_DEPTH_TEST); + + render_grabbers_for_picking(selection.get_bounding_box()); +} + +#if ENABLE_IMGUI +void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) +{ +#if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI + bool single_instance = selection.is_single_full_instance(); + wxString label = _(L("Scale (%)")); + + m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); + m_imgui->set_next_window_bg_alpha(0.5f); + m_imgui->begin(label, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + m_imgui->input_vec3("", m_scale * 100.f, 100.0f, "%.2f"); + m_imgui->end(); +#endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI +} +#endif // ENABLE_IMGUI + +void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2) const +{ + unsigned int grabbers_count = (unsigned int)m_grabbers.size(); + if ((id_1 < grabbers_count) && (id_2 < grabbers_count)) + { + ::glBegin(GL_LINES); + ::glVertex3dv(m_grabbers[id_1].center.data()); + ::glVertex3dv(m_grabbers[id_2].center.data()); + ::glEnd(); + } +} + +void GLGizmoScale3D::do_scale_x(const UpdateData& data) +{ + double ratio = calc_ratio(data); + if (ratio > 0.0) + m_scale(0) = m_starting_scale(0) * ratio; +} + +void GLGizmoScale3D::do_scale_y(const UpdateData& data) +{ + double ratio = calc_ratio(data); + if (ratio > 0.0) + m_scale(1) = m_starting_scale(1) * ratio; +} + +void GLGizmoScale3D::do_scale_z(const UpdateData& data) +{ + double ratio = calc_ratio(data); + if (ratio > 0.0) + m_scale(2) = m_starting_scale(2) * ratio; +} + +void GLGizmoScale3D::do_scale_uniform(const UpdateData& data) +{ + double ratio = calc_ratio(data); + if (ratio > 0.0) + m_scale = m_starting_scale * ratio; +} + +double GLGizmoScale3D::calc_ratio(const UpdateData& data) const +{ + double ratio = 0.0; + + // vector from the center to the starting position + Vec3d starting_vec = m_starting_drag_position - m_starting_box.center(); + double len_starting_vec = starting_vec.norm(); + if (len_starting_vec != 0.0) + { + Vec3d mouse_dir = data.mouse_ray.unit_vector(); + // finds the intersection of the mouse ray with the plane parallel to the camera viewport and passing throught the starting position + // use ray-plane intersection see i.e. https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection algebric form + // in our case plane normal and ray direction are the same (orthogonal view) + // when moving to perspective camera the negative z unit axis of the camera needs to be transformed in world space and used as plane normal + Vec3d inters = data.mouse_ray.a + (m_starting_drag_position - data.mouse_ray.a).dot(mouse_dir) / mouse_dir.squaredNorm() * mouse_dir; + // vector from the starting position to the found intersection + Vec3d inters_vec = inters - m_starting_drag_position; + + // finds projection of the vector along the staring direction + double proj = inters_vec.dot(starting_vec.normalized()); + + ratio = (len_starting_vec + proj) / len_starting_vec; + } + + if (data.shift_down) + ratio = m_snap_step * (double)std::round(ratio / m_snap_step); + + return ratio; +} + +} // namespace GUI +} // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp new file mode 100644 index 000000000..a6ee40c1a --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp @@ -0,0 +1,65 @@ +#ifndef slic3r_GLGizmoScale_hpp_ +#define slic3r_GLGizmoScale_hpp_ + +#include "GLGizmoBase.hpp" + + +namespace Slic3r { +namespace GUI { + +class GLGizmoScale3D : public GLGizmoBase +{ + static const float Offset; + + mutable BoundingBoxf3 m_box; + + Vec3d m_scale; + + double m_snap_step; + + Vec3d m_starting_scale; + Vec3d m_starting_drag_position; + BoundingBoxf3 m_starting_box; + +public: +#if ENABLE_SVG_ICONS + GLGizmoScale3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); +#else + GLGizmoScale3D(GLCanvas3D& parent, unsigned int sprite_id); +#endif // ENABLE_SVG_ICONS + + double get_snap_step(double step) const { return m_snap_step; } + void set_snap_step(double step) { m_snap_step = step; } + + const Vec3d& get_scale() const { return m_scale; } + void set_scale(const Vec3d& scale) { m_starting_scale = scale; m_scale = scale; } + +protected: + virtual bool on_init(); + virtual std::string on_get_name() const; + virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const { return !selection.is_wipe_tower(); } + virtual void on_start_dragging(const GLCanvas3D::Selection& selection); + virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; + +#if ENABLE_IMGUI + virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); +#endif // ENABLE_IMGUI + +private: + void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const; + + void do_scale_x(const UpdateData& data); + void do_scale_y(const UpdateData& data); + void do_scale_z(const UpdateData& data); + void do_scale_uniform(const UpdateData& data); + + double calc_ratio(const UpdateData& data) const; +}; + + +} // namespace GUI +} // namespace Slic3r + +#endif // slic3r_GLGizmoScale_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp new file mode 100644 index 000000000..c43f80de2 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -0,0 +1,912 @@ +// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro. +#include "GLGizmoSlaSupports.hpp" + +#include + +#include + +#include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/GUI_ObjectSettings.hpp" +#include "slic3r/GUI/GUI_ObjectList.hpp" +#include "slic3r/GUI/PresetBundle.hpp" + + +namespace Slic3r { +namespace GUI { + +#if ENABLE_SVG_ICONS +GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) + : GLGizmoBase(parent, icon_filename, sprite_id) +#else +GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id) + : GLGizmoBase(parent, sprite_id) +#endif // ENABLE_SVG_ICONS + , m_starting_center(Vec3d::Zero()), m_quadric(nullptr) +{ + m_quadric = ::gluNewQuadric(); + if (m_quadric != nullptr) + // using GLU_FILL does not work when the instance's transformation + // contains mirroring (normals are reverted) + ::gluQuadricDrawStyle(m_quadric, GLU_FILL); +} + +GLGizmoSlaSupports::~GLGizmoSlaSupports() +{ + if (m_quadric != nullptr) + ::gluDeleteQuadric(m_quadric); +} + +bool GLGizmoSlaSupports::on_init() +{ + m_shortcut_key = WXK_CONTROL_L; + return true; +} + +void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection) +{ + m_starting_center = Vec3d::Zero(); + m_old_model_object = m_model_object; + m_model_object = model_object; + if (selection.is_empty()) + m_old_instance_id = -1; + + m_active_instance = selection.get_instance_idx(); + + if (model_object && selection.is_from_single_instance()) + { + if (is_mesh_update_necessary()) { + update_mesh(); + editing_mode_reload_cache(); + } + + if (m_model_object != m_old_model_object) + m_editing_mode = false; + + if (m_editing_mode_cache.empty() && m_model_object->sla_points_status != sla::PointsStatus::UserModified) + get_data_from_backend(); + + if (m_state == On) { + m_parent.toggle_model_objects_visibility(false); + m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance); + } + } +} + +void GLGizmoSlaSupports::on_render(const GLCanvas3D::Selection& selection) const +{ + ::glEnable(GL_BLEND); + ::glEnable(GL_DEPTH_TEST); + + render_points(selection, false); + render_selection_rectangle(); + +#if !ENABLE_IMGUI + render_tooltip_texture(); +#endif // not ENABLE_IMGUI + + ::glDisable(GL_BLEND); +} + +void GLGizmoSlaSupports::render_selection_rectangle() const +{ + if (!m_selection_rectangle_active) + return; + + ::glLineWidth(1.5f); + float render_color[3] = {1.f, 0.f, 0.f}; + ::glColor3fv(render_color); + + ::glPushAttrib(GL_TRANSFORM_BIT); // remember current MatrixMode + + ::glMatrixMode(GL_MODELVIEW); // cache modelview matrix and set to identity + ::glPushMatrix(); + ::glLoadIdentity(); + + ::glMatrixMode(GL_PROJECTION); // cache projection matrix and set to identity + ::glPushMatrix(); + ::glLoadIdentity(); + + ::glOrtho(0.f, m_canvas_width, m_canvas_height, 0.f, -1.f, 1.f); // set projection matrix so that world coords = window coords + + // render the selection rectangle (window coordinates): + ::glPushAttrib(GL_ENABLE_BIT); + ::glLineStipple(4, 0xAAAA); + ::glEnable(GL_LINE_STIPPLE); + + ::glBegin(GL_LINE_LOOP); + ::glVertex3f((GLfloat)m_selection_rectangle_start_corner(0), (GLfloat)m_selection_rectangle_start_corner(1), (GLfloat)0.5f); + ::glVertex3f((GLfloat)m_selection_rectangle_end_corner(0), (GLfloat)m_selection_rectangle_start_corner(1), (GLfloat)0.5f); + ::glVertex3f((GLfloat)m_selection_rectangle_end_corner(0), (GLfloat)m_selection_rectangle_end_corner(1), (GLfloat)0.5f); + ::glVertex3f((GLfloat)m_selection_rectangle_start_corner(0), (GLfloat)m_selection_rectangle_end_corner(1), (GLfloat)0.5f); + ::glEnd(); + ::glPopAttrib(); + + ::glPopMatrix(); // restore former projection matrix + ::glMatrixMode(GL_MODELVIEW); + ::glPopMatrix(); // restore former modelview matrix + ::glPopAttrib(); // restore former MatrixMode +} + +void GLGizmoSlaSupports::on_render_for_picking(const GLCanvas3D::Selection& selection) const +{ + ::glEnable(GL_DEPTH_TEST); + + render_points(selection, true); +} + +void GLGizmoSlaSupports::render_points(const GLCanvas3D::Selection& selection, bool picking) const +{ + if (m_quadric == nullptr || !selection.is_from_single_instance()) + return; + + if (!picking) + ::glEnable(GL_LIGHTING); + + const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin()); + double z_shift = vol->get_sla_shift_z(); + const Transform3d& instance_scaling_matrix_inverse = vol->get_instance_transformation().get_matrix(true, true, false, true).inverse(); + const Transform3d& instance_matrix = vol->get_instance_transformation().get_matrix(); + + ::glPushMatrix(); + ::glTranslated(0.0, 0.0, z_shift); + ::glMultMatrixd(instance_matrix.data()); + + float render_color[3]; + for (int i = 0; i < (int)m_editing_mode_cache.size(); ++i) + { + const sla::SupportPoint& support_point = m_editing_mode_cache[i].support_point; + const bool& point_selected = m_editing_mode_cache[i].selected; + + // First decide about the color of the point. + if (picking) { + std::array color = picking_color_component(i); + render_color[0] = color[0]; + render_color[1] = color[1]; + render_color[2] = color[2]; + } + else { + if ((m_hover_id == i && m_editing_mode)) { // ignore hover state unless editing mode is active + render_color[0] = 0.f; + render_color[1] = 1.0f; + render_color[2] = 1.0f; + } + else { // neigher hover nor picking + bool supports_new_island = m_lock_unique_islands && m_editing_mode_cache[i].support_point.is_new_island; + if (m_editing_mode) { + render_color[0] = point_selected ? 1.0f : (supports_new_island ? 0.3f : 0.7f); + render_color[1] = point_selected ? 0.3f : (supports_new_island ? 0.3f : 0.7f); + render_color[2] = point_selected ? 0.3f : (supports_new_island ? 1.0f : 0.7f); + } + else + for (unsigned char i=0; i<3; ++i) render_color[i] = 0.5f; + } + } + ::glColor3fv(render_color); + float render_color_emissive[4] = { 0.5f * render_color[0], 0.5f * render_color[1], 0.5f * render_color[2], 1.f}; + ::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive); + + // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. + ::glPushMatrix(); + ::glTranslated(support_point.pos(0), support_point.pos(1), support_point.pos(2)); + ::glMultMatrixd(instance_scaling_matrix_inverse.data()); + + // Matrices set, we can render the point mark now. + // If in editing mode, we'll also render a cone pointing to the sphere. + if (m_editing_mode) { + if (m_editing_mode_cache[i].normal == Vec3f::Zero()) + update_cache_entry_normal(i); // in case the normal is not yet cached, find and cache it + + Eigen::Quaterniond q; + q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * m_editing_mode_cache[i].normal.cast()); + Eigen::AngleAxisd aa(q); + ::glRotated(aa.angle() * (180./M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)); + + const float cone_radius = 0.25f; // mm + const float cone_height = 0.75f; + ::glPushMatrix(); + ::glTranslatef(0.f, 0.f, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale); + ::gluCylinder(m_quadric, 0.f, cone_radius, cone_height, 36, 1); + ::glTranslatef(0.f, 0.f, cone_height); + ::gluDisk(m_quadric, 0.0, cone_radius, 36, 1); + ::glPopMatrix(); + } + ::gluSphere(m_quadric, m_editing_mode_cache[i].support_point.head_front_radius * RenderPointScale, 64, 36); + ::glPopMatrix(); + } + + { + // Reset emissive component to zero (the default value) + float render_color_emissive[4] = { 0.f, 0.f, 0.f, 1.f }; + ::glMaterialfv(GL_FRONT, GL_EMISSION, render_color_emissive); + } + + if (!picking) + ::glDisable(GL_LIGHTING); + + ::glPopMatrix(); +} + +bool GLGizmoSlaSupports::is_mesh_update_necessary() const +{ + return ((m_state == On) && (m_model_object != nullptr) && !m_model_object->instances.empty()) + && ((m_model_object != m_old_model_object) || m_V.size()==0); + + //if (m_state != On || !m_model_object || m_model_object->instances.empty() || ! m_instance_matrix.isApprox(m_source_data.matrix)) + // return false; +} + +void GLGizmoSlaSupports::update_mesh() +{ + wxBusyCursor wait; + Eigen::MatrixXf& V = m_V; + Eigen::MatrixXi& F = m_F; + // Composite mesh of all instances in the world coordinate system. + // This mesh does not account for the possible Z up SLA offset. + TriangleMesh mesh = m_model_object->raw_mesh(); + const stl_file& stl = mesh.stl; + V.resize(3 * stl.stats.number_of_facets, 3); + F.resize(stl.stats.number_of_facets, 3); + for (unsigned int i=0; ivertex[0](0); V(3*i+0, 1) = facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2); + V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) = facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2); + V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) = facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2); + F(i, 0) = 3*i+0; + F(i, 1) = 3*i+1; + F(i, 2) = 3*i+2; + } + + m_AABB = igl::AABB(); + m_AABB.init(m_V, m_F); +} + +std::pair GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos) +{ + // if the gizmo doesn't have the V, F structures for igl, calculate them first: + if (m_V.size() == 0) + update_mesh(); + + Eigen::Matrix viewport; + ::glGetIntegerv(GL_VIEWPORT, viewport.data()); + Eigen::Matrix modelview_matrix; + ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data()); + Eigen::Matrix projection_matrix; + ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix.data()); + + Vec3d point1; + Vec3d point2; + ::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 0.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point1(0), &point1(1), &point1(2)); + ::gluUnProject(mouse_pos(0), viewport(3)-mouse_pos(1), 1.f, modelview_matrix.data(), projection_matrix.data(), viewport.data(), &point2(0), &point2(1), &point2(2)); + + igl::Hit hit; + + const GLCanvas3D::Selection& selection = m_parent.get_selection(); + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + double z_offset = volume->get_sla_shift_z(); + + point1(2) -= z_offset; + point2(2) -= z_offset; + + Transform3d inv = volume->get_instance_transformation().get_matrix().inverse(); + + point1 = inv * point1; + point2 = inv * point2; + + if (!m_AABB.intersect_ray(m_V, m_F, point1.cast(), (point2-point1).cast(), hit)) + throw std::invalid_argument("unproject_on_mesh(): No intersection found."); + + int fid = hit.id; // facet id + Vec3f bc(1-hit.u-hit.v, hit.u, hit.v); // barycentric coordinates of the hit + Vec3f a = (m_V.row(m_F(fid, 1)) - m_V.row(m_F(fid, 0))); + Vec3f b = (m_V.row(m_F(fid, 2)) - m_V.row(m_F(fid, 0))); + + // Calculate and return both the point and the facet normal. + return std::make_pair( + bc(0) * m_V.row(m_F(fid, 0)) + bc(1) * m_V.row(m_F(fid, 1)) + bc(2)*m_V.row(m_F(fid, 2)), + a.cross(b) + ); +} + +// Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event. +// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is +// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo +// concludes that the event was not intended for it, it should return false. +bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down) +{ + if (m_editing_mode) { + + // left down - show the selection rectangle: + if (action == SLAGizmoEventType::LeftDown && shift_down) { + if (m_hover_id == -1) { + m_selection_rectangle_active = true; + m_selection_rectangle_start_corner = mouse_position; + m_selection_rectangle_end_corner = mouse_position; + m_canvas_width = m_parent.get_canvas_size().get_width(); + m_canvas_height = m_parent.get_canvas_size().get_height(); + } + else + select_point(m_hover_id); + + return true; + } + + // dragging the selection rectangle: + if (action == SLAGizmoEventType::Dragging && m_selection_rectangle_active) { + m_selection_rectangle_end_corner = mouse_position; + return true; + } + + // mouse up without selection rectangle - place point on the mesh: + if (action == SLAGizmoEventType::LeftUp && !m_selection_rectangle_active && !shift_down) { + if (m_ignore_up_event) { + m_ignore_up_event = false; + return false; + } + + int instance_id = m_parent.get_selection().get_instance_idx(); + if (m_old_instance_id != instance_id) + { + bool something_selected = (m_old_instance_id != -1); + m_old_instance_id = instance_id; + if (something_selected) + return false; + } + if (instance_id == -1) + return false; + + // If there is some selection, don't add new point and deselect everything instead. + if (m_selection_empty) { + try { + std::pair pos_and_normal = unproject_on_mesh(mouse_position); // don't create anything if this throws + m_editing_mode_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second); + m_unsaved_changes = true; + } + catch (...) { // not clicked on object + return true; // prevents deselection of the gizmo by GLCanvas3D + } + } + else + select_point(NoPoints); + + return true; + } + + // left up with selection rectangle - select points inside the rectangle: + if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp) + && m_selection_rectangle_active) { + if (action == SLAGizmoEventType::ShiftUp) + m_ignore_up_event = true; + const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix(); + GLint viewport[4]; + ::glGetIntegerv(GL_VIEWPORT, viewport); + GLdouble modelview_matrix[16]; + ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix); + GLdouble projection_matrix[16]; + ::glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix); + + const GLCanvas3D::Selection& selection = m_parent.get_selection(); + const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin()); + double z_offset = volume->get_sla_shift_z(); + + // bounding box created from the rectangle corners - will take care of order of the corners + BoundingBox rectangle(Points{Point(m_selection_rectangle_start_corner.cast()), Point(m_selection_rectangle_end_corner.cast())}); + + const Transform3d& instance_matrix_no_translation = volume->get_instance_transformation().get_matrix(true); + // we'll recover current look direction from the modelview matrix (in world coords)... + Vec3f direction_to_camera(modelview_matrix[2], modelview_matrix[6], modelview_matrix[10]); + // ...and transform it to model coords. + direction_to_camera = (instance_matrix_no_translation.inverse().cast() * direction_to_camera).normalized().eval(); + + // Iterate over all points, check if they're in the rectangle and if so, check that they are not obscured by the mesh: + for (unsigned int i=0; i() * support_point.pos; + pos(2) += z_offset; + GLdouble out_x, out_y, out_z; + ::gluProject((GLdouble)pos(0), (GLdouble)pos(1), (GLdouble)pos(2), modelview_matrix, projection_matrix, viewport, &out_x, &out_y, &out_z); + out_y = m_canvas_height - out_y; + + if (rectangle.contains(Point(out_x, out_y))) { + bool is_obscured = false; + // Cast a ray in the direction of the camera and look for intersection with the mesh: + std::vector hits; + // Offset the start of the ray to the front of the ball + EPSILON to account for numerical inaccuracies. + if (m_AABB.intersect_ray(m_V, m_F, support_point.pos + direction_to_camera * (support_point.head_front_radius + EPSILON), direction_to_camera, hits)) + // FIXME: the intersection could in theory be behind the camera, but as of now we only have camera direction. + // Also, the threshold is in mesh coordinates, not in actual dimensions. + if (hits.size() > 1 || hits.front().t > 0.001f) + is_obscured = true; + + if (!is_obscured) + select_point(i); + } + } + m_selection_rectangle_active = false; + return true; + } + + if (action == SLAGizmoEventType::Delete) { + // delete key pressed + delete_selected_points(); + return true; + } + + if (action == SLAGizmoEventType::ApplyChanges) { + editing_mode_apply_changes(); + return true; + } + + if (action == SLAGizmoEventType::DiscardChanges) { + editing_mode_discard_changes(); + return true; + } + + if (action == SLAGizmoEventType::RightDown) { + if (m_hover_id != -1) { + select_point(NoPoints); + select_point(m_hover_id); + delete_selected_points(); + return true; + } + return false; + } + + if (action == SLAGizmoEventType::SelectAll) { + select_point(AllPoints); + return true; + } + } + + if (!m_editing_mode) { + if (action == SLAGizmoEventType::AutomaticGeneration) { + auto_generate(); + return true; + } + + if (action == SLAGizmoEventType::ManualEditing) { + switch_to_editing_mode(); + return true; + } + } + + return false; +} + +void GLGizmoSlaSupports::delete_selected_points(bool force) +{ + for (unsigned int idx=0; idxreslice_SLA_supports(*m_model_object); + } + + select_point(NoPoints); + + //m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); +} + +void GLGizmoSlaSupports::on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) +{ + if (m_editing_mode && m_hover_id != -1 && data.mouse_pos && (!m_editing_mode_cache[m_hover_id].support_point.is_new_island || !m_lock_unique_islands)) { + std::pair pos_and_normal; + try { + pos_and_normal = unproject_on_mesh(Vec2d((*data.mouse_pos)(0), (*data.mouse_pos)(1))); + } + catch (...) { return; } + m_editing_mode_cache[m_hover_id].support_point.pos = pos_and_normal.first; + m_editing_mode_cache[m_hover_id].support_point.is_new_island = false; + m_editing_mode_cache[m_hover_id].normal = pos_and_normal.second; + m_unsaved_changes = true; + // Do not update immediately, wait until the mouse is released. + // m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); + } +} + +#if !ENABLE_IMGUI +void GLGizmoSlaSupports::render_tooltip_texture() const { + if (m_tooltip_texture.get_id() == 0) + if (!m_tooltip_texture.load_from_file(resources_dir() + "/icons/sla_support_points_tooltip.png", false)) + return; + if (m_reset_texture.get_id() == 0) + if (!m_reset_texture.load_from_file(resources_dir() + "/icons/sla_support_points_reset.png", false)) + return; + + float zoom = m_parent.get_camera_zoom(); + float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + float gap = 30.0f * inv_zoom; + + const Size& cnv_size = m_parent.get_canvas_size(); + float l = gap - cnv_size.get_width()/2.f * inv_zoom; + float r = l + (float)m_tooltip_texture.get_width() * inv_zoom; + float b = gap - cnv_size.get_height()/2.f * inv_zoom; + float t = b + (float)m_tooltip_texture.get_height() * inv_zoom; + + Rect reset_rect = m_parent.get_gizmo_reset_rect(m_parent, true); + + ::glDisable(GL_DEPTH_TEST); + ::glPushMatrix(); + ::glLoadIdentity(); + GLTexture::render_texture(m_tooltip_texture.get_id(), l, r, b, t); + GLTexture::render_texture(m_reset_texture.get_id(), reset_rect.get_left(), reset_rect.get_right(), reset_rect.get_bottom(), reset_rect.get_top()); + ::glPopMatrix(); + ::glEnable(GL_DEPTH_TEST); +} +#endif // not ENABLE_IMGUI + + +std::vector GLGizmoSlaSupports::get_config_options(const std::vector& keys) const +{ + std::vector out; + + if (!m_model_object) + return out; + + const DynamicPrintConfig& object_cfg = m_model_object->config; + const DynamicPrintConfig& print_cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config; + std::unique_ptr default_cfg = nullptr; + + for (const std::string& key : keys) { + if (object_cfg.has(key)) + out.push_back(object_cfg.option(key)); + else + if (print_cfg.has(key)) + out.push_back(print_cfg.option(key)); + else { // we must get it from defaults + if (default_cfg == nullptr) + default_cfg.reset(DynamicPrintConfig::new_from_defaults_keys(keys)); + out.push_back(default_cfg->option(key)); + } + } + + return out; +} + + +void GLGizmoSlaSupports::update_cache_entry_normal(unsigned int i) const +{ + int idx = 0; + Eigen::Matrix pp = m_editing_mode_cache[i].support_point.pos; + Eigen::Matrix cc; + m_AABB.squared_distance(m_V, m_F, pp, idx, cc); + Vec3f a = (m_V.row(m_F(idx, 1)) - m_V.row(m_F(idx, 0))); + Vec3f b = (m_V.row(m_F(idx, 2)) - m_V.row(m_F(idx, 0))); + m_editing_mode_cache[i].normal = a.cross(b); +} + + + +#if ENABLE_IMGUI +void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) +{ + if (!m_model_object) + return; + + bool first_run = true; // This is a hack to redraw the button when all points are removed, + // so it is not delayed until the background process finishes. +RENDER_AGAIN: + m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); + + const float scaling = m_imgui->get_style_scaling(); + const ImVec2 window_size(285.f * scaling, 300.f * scaling); + ImGui::SetNextWindowPos(ImVec2(x, y - std::max(0.f, y+window_size.y-bottom_limit) )); + ImGui::SetNextWindowSize(ImVec2(window_size)); + + m_imgui->set_next_window_bg_alpha(0.5f); + m_imgui->begin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + + ImGui::PushItemWidth(100.0f); + + bool force_refresh = false; + bool remove_selected = false; + bool remove_all = false; + + if (m_editing_mode) { + m_imgui->text(_(L("Left mouse click - add point"))); + m_imgui->text(_(L("Right mouse click - remove point"))); + m_imgui->text(_(L("Shift + Left (+ drag) - select point(s)"))); + m_imgui->text(" "); // vertical gap + + float diameter_upper_cap = static_cast(wxGetApp().preset_bundle->sla_prints.get_edited_preset().config.option("support_pillar_diameter"))->value; + if (m_new_point_head_diameter > diameter_upper_cap) + m_new_point_head_diameter = diameter_upper_cap; + + m_imgui->text(_(L("Head diameter: "))); + ImGui::SameLine(); + if (ImGui::SliderFloat("", &m_new_point_head_diameter, 0.1f, diameter_upper_cap, "%.1f")) { + // value was changed + for (auto& cache_entry : m_editing_mode_cache) + if (cache_entry.selected) { + cache_entry.support_point.head_front_radius = m_new_point_head_diameter / 2.f; + m_unsaved_changes = true; + } + } + + bool changed = m_lock_unique_islands; + m_imgui->checkbox(_(L("Lock supports under new islands")), m_lock_unique_islands); + force_refresh |= changed != m_lock_unique_islands; + + m_imgui->disabled_begin(m_selection_empty); + remove_selected = m_imgui->button(_(L("Remove selected points"))); + m_imgui->disabled_end(); + + m_imgui->disabled_begin(m_editing_mode_cache.empty()); + remove_all = m_imgui->button(_(L("Remove all points"))); + m_imgui->disabled_end(); + + m_imgui->text(" "); // vertical gap + + if (m_imgui->button(_(L("Apply changes")))) { + editing_mode_apply_changes(); + force_refresh = true; + } + ImGui::SameLine(); + bool discard_changes = m_imgui->button(_(L("Discard changes"))); + if (discard_changes) { + editing_mode_discard_changes(); + force_refresh = true; + } + } + else { // not in editing mode: + ImGui::PushItemWidth(100.0f); + m_imgui->text(_(L("Minimal points distance: "))); + ImGui::SameLine(); + + std::vector opts = get_config_options({"support_points_density_relative", "support_points_minimal_distance"}); + float density = static_cast(opts[0])->value; + float minimal_point_distance = static_cast(opts[1])->value; + + bool value_changed = ImGui::SliderFloat("", &minimal_point_distance, 0.f, 20.f, "%.f mm"); + if (value_changed) + m_model_object->config.opt("support_points_minimal_distance", true)->value = minimal_point_distance; + + m_imgui->text(_(L("Support points density: "))); + ImGui::SameLine(); + if (ImGui::SliderFloat(" ", &density, 0.f, 200.f, "%.f %%")) { + value_changed = true; + m_model_object->config.opt("support_points_density_relative", true)->value = (int)density; + } + + if (value_changed) { // Update side panel + wxTheApp->CallAfter([]() { + wxGetApp().obj_settings()->UpdateAndShow(true); + wxGetApp().obj_list()->update_settings_items(); + }); + } + + bool generate = m_imgui->button(_(L("Auto-generate points [A]"))); + + if (generate) + auto_generate(); + + m_imgui->text(""); + if (m_imgui->button(_(L("Manual editing [M]")))) + switch_to_editing_mode(); + + m_imgui->disabled_begin(m_editing_mode_cache.empty()); + remove_all = m_imgui->button(_(L("Remove all points"))); + m_imgui->disabled_end(); + + m_imgui->text(""); + + m_imgui->text(m_model_object->sla_points_status == sla::PointsStatus::None ? "No points (will be autogenerated)" : + (m_model_object->sla_points_status == sla::PointsStatus::AutoGenerated ? "Autogenerated points (no modifications)" : + (m_model_object->sla_points_status == sla::PointsStatus::UserModified ? "User-modified points" : + (m_model_object->sla_points_status == sla::PointsStatus::Generating ? "Generation in progress..." : "UNKNOWN STATUS")))); + } + + m_imgui->end(); + + if (m_editing_mode != m_old_editing_state) { // user toggled between editing/non-editing mode + m_parent.toggle_sla_auxiliaries_visibility(!m_editing_mode); + force_refresh = true; + } + m_old_editing_state = m_editing_mode; + + if (remove_selected || remove_all) { + force_refresh = false; + m_parent.set_as_dirty(); + if (remove_all) + select_point(AllPoints); + delete_selected_points(remove_all); + if (remove_all && !m_editing_mode) + editing_mode_apply_changes(); + if (first_run) { + first_run = false; + goto RENDER_AGAIN; + } + } + + if (force_refresh) + m_parent.set_as_dirty(); +} +#endif // ENABLE_IMGUI + +bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const +{ + if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA + || !selection.is_from_single_instance()) + return false; + + // Check that none of the selected volumes is outside. + const GLCanvas3D::Selection::IndicesList& list = selection.get_volume_idxs(); + for (const auto& idx : list) + if (selection.get_volume(idx)->is_outside) + return false; + + return true; +} + +bool GLGizmoSlaSupports::on_is_selectable() const +{ + return (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA); +} + +std::string GLGizmoSlaSupports::on_get_name() const +{ + return L("SLA Support Points [L]"); +} + +void GLGizmoSlaSupports::on_set_state() +{ + if (m_state == On && m_old_state != On) { // the gizmo was just turned on + if (is_mesh_update_necessary()) + update_mesh(); + + // we'll now reload support points: + if (m_model_object) + editing_mode_reload_cache(); + + m_parent.toggle_model_objects_visibility(false); + if (m_model_object) + m_parent.toggle_model_objects_visibility(true, m_model_object, m_active_instance); + + // Set default head diameter from config. + const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config; + m_new_point_head_diameter = static_cast(cfg.option("support_head_front_diameter"))->value; + } + if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off + if (m_model_object) { + if (m_unsaved_changes) { + wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L("Do you want to save your manually edited support points ?\n")), + _(L("Save changes?")), wxICON_QUESTION | wxYES | wxNO); + if (dlg.ShowModal() == wxID_YES) + editing_mode_apply_changes(); + else + editing_mode_discard_changes(); + } + } + + m_parent.toggle_model_objects_visibility(true); + m_editing_mode = false; // so it is not active next time the gizmo opens + m_editing_mode_cache.clear(); + } + m_old_state = m_state; +} + + + +void GLGizmoSlaSupports::on_start_dragging(const GLCanvas3D::Selection& selection) +{ + if (m_hover_id != -1) { + select_point(NoPoints); + select_point(m_hover_id); + } +} + + + +void GLGizmoSlaSupports::select_point(int i) +{ + if (i == AllPoints || i == NoPoints) { + for (auto& point_and_selection : m_editing_mode_cache) + point_and_selection.selected = ( i == AllPoints ); + m_selection_empty = (i == NoPoints); + + if (i == AllPoints) + m_new_point_head_diameter = m_editing_mode_cache[0].support_point.head_front_radius * 2.f; + } + else { + m_editing_mode_cache[i].selected = true; + m_selection_empty = false; + m_new_point_head_diameter = m_editing_mode_cache[i].support_point.head_front_radius * 2.f; + } +} + + + +void GLGizmoSlaSupports::editing_mode_discard_changes() +{ + m_editing_mode_cache.clear(); + for (const sla::SupportPoint& point : m_model_object->sla_support_points) + m_editing_mode_cache.emplace_back(point, false); + m_editing_mode = false; + m_unsaved_changes = false; +} + + + +void GLGizmoSlaSupports::editing_mode_apply_changes() +{ + // If there are no changes, don't touch the front-end. The data in the cache could have been + // taken from the backend and copying them to ModelObject would needlessly invalidate them. + if (m_unsaved_changes) { + m_model_object->sla_points_status = sla::PointsStatus::UserModified; + m_model_object->sla_support_points.clear(); + for (const CacheEntry& cache_entry : m_editing_mode_cache) + m_model_object->sla_support_points.push_back(cache_entry.support_point); + + // Recalculate support structures once the editing mode is left. + // m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); + // m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); + wxGetApp().plater()->reslice_SLA_supports(*m_model_object); + } + m_editing_mode = false; + m_unsaved_changes = false; +} + + + +void GLGizmoSlaSupports::editing_mode_reload_cache() +{ + m_editing_mode_cache.clear(); + for (const sla::SupportPoint& point : m_model_object->sla_support_points) + m_editing_mode_cache.emplace_back(point, false); + + m_unsaved_changes = false; +} + + + +void GLGizmoSlaSupports::get_data_from_backend() +{ + for (const SLAPrintObject* po : m_parent.sla_print()->objects()) { + if (po->model_object()->id() == m_model_object->id() && po->is_step_done(slaposSupportPoints)) { + m_editing_mode_cache.clear(); + const std::vector& points = po->get_support_points(); + auto mat = po->trafo().inverse().cast(); + for (unsigned int i=0; isla_points_status != sla::PointsStatus::UserModified) + m_model_object->sla_points_status = sla::PointsStatus::AutoGenerated; + + break; + } + } + m_unsaved_changes = false; + + // We don't copy the data into ModelObject, as this would stop the background processing. +} + + + +void GLGizmoSlaSupports::auto_generate() +{ + wxMessageDialog dlg(GUI::wxGetApp().plater(), _(L( + "Autogeneration will erase all manually edited points.\n\n" + "Are you sure you want to do it?\n" + )), _(L("Warning")), wxICON_WARNING | wxYES | wxNO); + + if (m_model_object->sla_points_status != sla::PointsStatus::UserModified || m_editing_mode_cache.empty() || dlg.ShowModal() == wxID_YES) { + m_model_object->sla_support_points.clear(); + m_model_object->sla_points_status = sla::PointsStatus::Generating; + m_editing_mode_cache.clear(); + wxGetApp().plater()->reslice_SLA_supports(*m_model_object); + } +} + + + +void GLGizmoSlaSupports::switch_to_editing_mode() +{ + if (m_model_object->sla_points_status != sla::PointsStatus::AutoGenerated) + editing_mode_reload_cache(); + m_unsaved_changes = false; + m_editing_mode = true; +} + +} // namespace GUI +} // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp new file mode 100644 index 000000000..44842e5c5 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -0,0 +1,137 @@ +#ifndef slic3r_GLGizmoSlaSupports_hpp_ +#define slic3r_GLGizmoSlaSupports_hpp_ + +#include "GLGizmoBase.hpp" + +// There is an L function in igl that would be overridden by our localization macro - let's undefine it... +#undef L +#include +#include "slic3r/GUI/I18N.hpp" // ...and redefine again when we are done with the igl code + +#include "libslic3r/SLA/SLACommon.hpp" +#include "libslic3r/SLAPrint.hpp" + + +namespace Slic3r { +namespace GUI { + + +class GLGizmoSlaSupports : public GLGizmoBase +{ +private: + ModelObject* m_model_object = nullptr; + ModelObject* m_old_model_object = nullptr; + int m_active_instance = -1; + int m_old_instance_id = -1; + std::pair unproject_on_mesh(const Vec2d& mouse_pos); + + const float RenderPointScale = 1.f; + + GLUquadricObj* m_quadric; + Eigen::MatrixXf m_V; // vertices + Eigen::MatrixXi m_F; // facets indices + igl::AABB m_AABB; + + struct SourceDataSummary { + Geometry::Transformation transformation; + }; + + class CacheEntry { + public: + CacheEntry(const sla::SupportPoint& point, bool sel, const Vec3f& norm = Vec3f::Zero()) : + support_point(point), selected(sel), normal(norm) {} + + sla::SupportPoint support_point; + bool selected; // whether the point is selected + Vec3f normal; + }; + + // This holds information to decide whether recalculation is necessary: + SourceDataSummary m_source_data; + + mutable Vec3d m_starting_center; + +public: +#if ENABLE_SVG_ICONS + GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); +#else + GLGizmoSlaSupports(GLCanvas3D& parent, unsigned int sprite_id); +#endif // ENABLE_SVG_ICONS + virtual ~GLGizmoSlaSupports(); + void set_sla_support_data(ModelObject* model_object, const GLCanvas3D::Selection& selection); + bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down); + void delete_selected_points(bool force = false); + std::pair get_sla_clipping_plane() const; + +private: + bool on_init(); + void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); + virtual void on_render(const GLCanvas3D::Selection& selection) const; + virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; + + void render_selection_rectangle() const; + void render_points(const GLCanvas3D::Selection& selection, bool picking = false) const; + bool is_mesh_update_necessary() const; + void update_mesh(); + void update_cache_entry_normal(unsigned int i) const; + +#if !ENABLE_IMGUI + void render_tooltip_texture() const; + mutable GLTexture m_tooltip_texture; + mutable GLTexture m_reset_texture; +#endif // not ENABLE_IMGUI + + bool m_lock_unique_islands = false; + bool m_editing_mode = false; // Is editing mode active? + bool m_old_editing_state = false; // To keep track of whether the user toggled between the modes (needed for imgui refreshes). + float m_new_point_head_diameter; // Size of a new point. + float m_minimal_point_distance = 20.f; + float m_density = 100.f; + mutable std::vector m_editing_mode_cache; // a support point and whether it is currently selected + float m_clipping_plane_distance = 0.f; + + bool m_selection_rectangle_active = false; + Vec2d m_selection_rectangle_start_corner; + Vec2d m_selection_rectangle_end_corner; + bool m_ignore_up_event = false; + bool m_combo_box_open = false; // To ensure proper rendering of the imgui combobox. + bool m_unsaved_changes = false; // Are there unsaved changes in manual mode? + bool m_selection_empty = true; + EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state) + int m_canvas_width; + int m_canvas_height; + + std::vector get_config_options(const std::vector& keys) const; + + // Methods that do the model_object and editing cache synchronization, + // editing mode selection, etc: + enum { + AllPoints = -2, + NoPoints, + }; + void select_point(int i); + void editing_mode_apply_changes(); + void editing_mode_discard_changes(); + void editing_mode_reload_cache(); + void get_data_from_backend(); + void auto_generate(); + void switch_to_editing_mode(); + +protected: + void on_set_state() override; + void on_start_dragging(const GLCanvas3D::Selection& selection) override; + +#if ENABLE_IMGUI + virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) override; +#endif // ENABLE_IMGUI + + virtual std::string on_get_name() const; + virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const; + virtual bool on_is_selectable() const; +}; + + +} // namespace GUI +} // namespace Slic3r + +#endif // slic3r_GLGizmoSlaSupports_hpp_ diff --git a/src/slic3r/GUI/Gizmos/GLGizmos.hpp b/src/slic3r/GUI/Gizmos/GLGizmos.hpp new file mode 100644 index 000000000..8c5e25669 --- /dev/null +++ b/src/slic3r/GUI/Gizmos/GLGizmos.hpp @@ -0,0 +1,11 @@ +#ifndef slic3r_GLGizmos_hpp_ +#define slic3r_GLGizmos_hpp_ + +#include "slic3r/GUI/Gizmos/GLGizmoMove.hpp" +#include "slic3r/GUI/Gizmos/GLGizmoScale.hpp" +#include "slic3r/GUI/Gizmos/GLGizmoRotate.hpp" +#include "slic3r/GUI/Gizmos/GLGizmoFlatten.hpp" +#include "slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp" +#include "slic3r/GUI/Gizmos/GLGizmoCut.hpp" + +#endif //slic3r_GLGizmos_hpp_ From e813a562a1108b678f0b5b1de38e3f3ebb60433d Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 15 Mar 2019 16:31:54 +0100 Subject: [PATCH 22/23] Removed technology ENABLE_IMGUI --- src/libslic3r/Technologies.hpp | 5 +- src/slic3r/GUI/GLCanvas3D.cpp | 61 -------------------- src/slic3r/GUI/GLCanvas3D.hpp | 17 ------ src/slic3r/GUI/GUI_App.cpp | 5 -- src/slic3r/GUI/GUI_App.hpp | 7 --- src/slic3r/GUI/GUI_Preview.cpp | 12 ---- src/slic3r/GUI/GUI_Preview.hpp | 4 -- src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 5 -- src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 14 ----- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 31 ---------- src/slic3r/GUI/Gizmos/GLGizmoCut.hpp | 17 +----- src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 2 - src/slic3r/GUI/Gizmos/GLGizmoMove.hpp | 3 - src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 2 - src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp | 2 - src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 2 - src/slic3r/GUI/Gizmos/GLGizmoScale.hpp | 3 - src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 38 ------------ src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp | 9 --- 19 files changed, 3 insertions(+), 236 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index e978b5838..307527fcb 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -20,9 +20,8 @@ // Disable synchronization of unselected instances #define DISABLE_INSTANCES_SYNCH (0 && ENABLE_1_42_0_ALPHA1) -// Scene's GUI made using imgui library -#define ENABLE_IMGUI (1 && ENABLE_1_42_0_ALPHA1) -#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_IMGUI) +// Disable imgui dialog for move, rotate and scale gizmos +#define DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI (1 && ENABLE_1_42_0_ALPHA1) // Use wxDataViewRender instead of wxDataViewCustomRenderer #define ENABLE_NONCUSTOM_DATA_VIEW_RENDERING (0 && ENABLE_1_42_0_ALPHA1) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 902c68b59..f38e257ac 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3005,14 +3005,6 @@ void GLCanvas3D::Gizmos::render_overlay(const GLCanvas3D& canvas, const GLCanvas ::glPopMatrix(); } -#if !ENABLE_IMGUI -void GLCanvas3D::Gizmos::create_external_gizmo_widgets(wxWindow *parent) -{ - for (auto &entry : m_gizmos) { - entry.second->create_external_gizmo_widgets(parent); - } -} -#endif // not ENABLE_IMGUI void GLCanvas3D::Gizmos::reset() { @@ -3031,9 +3023,7 @@ void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCan return; float cnv_w = (float)canvas.get_canvas_size().get_width(); -#if ENABLE_IMGUI float cnv_h = (float)canvas.get_canvas_size().get_height(); -#endif // ENABLE_IMGUI float zoom = canvas.get_camera_zoom(); float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; @@ -3171,7 +3161,6 @@ void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCan #endif // ENABLE_SVG_ICONS GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } }); -#if ENABLE_IMGUI if (it->second->get_state() == GLGizmoBase::On) { float toolbar_top = (float)cnv_h - canvas.m_view_toolbar.get_height(); #if ENABLE_SVG_ICONS @@ -3180,7 +3169,6 @@ void GLCanvas3D::Gizmos::do_render_overlay(const GLCanvas3D& canvas, const GLCan it->second->render_input_window(2.0f * m_overlay_border + icon_size * zoom, 0.5f * cnv_h - top_y * zoom, toolbar_top, selection); #endif // ENABLE_SVG_ICONS } -#endif // ENABLE_IMGUI #if ENABLE_SVG_ICONS top_y -= scaled_stride_y; #else @@ -3739,9 +3727,6 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar , m_color_by("volume") , m_reload_delayed(false) , m_render_sla_auxiliaries(true) -#if !ENABLE_IMGUI - , m_external_gizmo_widgets_parent(nullptr) -#endif // not ENABLE_IMGUI { if (m_canvas != nullptr) { m_timer.SetOwner(m_canvas); @@ -3834,13 +3819,6 @@ bool GLCanvas3D::init(bool useVBOs, bool use_legacy_opengl) std::cout << "Unable to initialize gizmos: please, check that all the required textures are available" << std::endl; return false; } - -#if !ENABLE_IMGUI - if (m_external_gizmo_widgets_parent != nullptr) { - m_gizmos.create_external_gizmo_widgets(m_external_gizmo_widgets_parent); - m_canvas->GetParent()->Layout(); - } -#endif // not ENABLE_IMGUI } if (!_init_toolbar()) @@ -4115,27 +4093,6 @@ void GLCanvas3D::update_toolbar_items_visibility() m_dirty = true; } -// Returns a Rect object denoting size and position of the Reset button used by a gizmo. -// Returns in either screen or viewport coords. -#if !ENABLE_IMGUI -Rect GLCanvas3D::get_gizmo_reset_rect(const GLCanvas3D& canvas, bool viewport) const -{ - const Size& cnv_size = canvas.get_canvas_size(); - float w = (viewport ? -0.5f : 0.f) * (float)cnv_size.get_width(); - float h = (viewport ? 0.5f : 1.f) * (float)cnv_size.get_height(); - float zoom = canvas.get_camera_zoom(); - float inv_zoom = viewport ? ((zoom != 0.0f) ? 1.0f / zoom : 0.0f) : 1.f; - const float gap = 30.f; - return Rect((w + gap + 80.f) * inv_zoom, (viewport ? -1.f : 1.f) * (h - GIZMO_RESET_BUTTON_HEIGHT) * inv_zoom, - (w + gap + 80.f + GIZMO_RESET_BUTTON_WIDTH) * inv_zoom, (viewport ? -1.f : 1.f) * (h * inv_zoom)); -} - -bool GLCanvas3D::gizmo_reset_rect_contains(const GLCanvas3D& canvas, float x, float y) const -{ - const Rect& rect = get_gizmo_reset_rect(canvas, false); - return (rect.get_left() <= x) && (x <= rect.get_right()) && (rect.get_top() <= y) && (y <= rect.get_bottom()); -} -#endif // not ENABLE_IMGUI void GLCanvas3D::render() { @@ -4184,9 +4141,7 @@ void GLCanvas3D::render() // absolute value of the rotation theta = 360.f - theta; -#if ENABLE_IMGUI wxGetApp().imgui()->new_frame(); -#endif // ENABLE_IMGUI // picking pass _picking_pass(); @@ -4237,9 +4192,7 @@ void GLCanvas3D::render() if (m_layers_editing.last_object_id >= 0) m_layers_editing.render_overlay(*this); -#if ENABLE_IMGUI wxGetApp().imgui()->render(); -#endif // ENABLE_IMGUI m_canvas->SwapBuffers(); } @@ -4805,13 +4758,11 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) int keyCode = evt.GetKeyCode(); int ctrlMask = wxMOD_CONTROL; -#if ENABLE_IMGUI auto imgui = wxGetApp().imgui(); if (imgui->update_key_data(evt)) { render(); return; } -#endif // ENABLE_IMGUI //#ifdef __APPLE__ // ctrlMask |= wxMOD_RAW_CONTROL; @@ -4919,12 +4870,10 @@ void GLCanvas3D::on_key(wxKeyEvent& evt) { const int keyCode = evt.GetKeyCode(); -#if ENABLE_IMGUI auto imgui = wxGetApp().imgui(); if (imgui->update_key_data(evt)) { render(); } else -#endif // ENABLE_IMGUI if (evt.GetEventType() == wxEVT_KEY_UP) { if (m_tab_down && keyCode == WXK_TAB && !evt.HasAnyModifiers()) { // Enable switching between 3D and Preview with Tab @@ -5047,7 +4996,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) Point pos(evt.GetX(), evt.GetY()); -#if ENABLE_IMGUI ImGuiWrapper *imgui = wxGetApp().imgui(); if (imgui->update_mouse_data(evt)) { m_mouse.position = evt.Leaving() ? Vec2d(-1.0, -1.0) : pos.cast(); @@ -5057,7 +5005,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) #endif /* SLIC3R_DEBUG_MOUSE_EVENTS */ return; } -#endif // ENABLE_IMGUI #ifdef __WXMSW__ bool on_enter_workaround = false; @@ -5628,12 +5575,6 @@ void GLCanvas3D::set_tooltip(const std::string& tooltip) const } } -#if !ENABLE_IMGUI -void GLCanvas3D::set_external_gizmo_widgets_parent(wxWindow *parent) -{ - m_external_gizmo_widgets_parent = parent; -} -#endif // not ENABLE_IMGUI void GLCanvas3D::do_move() { @@ -6066,14 +6007,12 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h) if ((m_canvas == nullptr) && (m_context == nullptr)) return; -#if ENABLE_IMGUI wxGetApp().imgui()->set_display_size((float)w, (float)h); #if ENABLE_RETINA_GL wxGetApp().imgui()->set_style_scaling(m_retina_helper->get_scale_factor()); #else wxGetApp().imgui()->set_style_scaling(m_canvas->GetContentScaleFactor()); #endif -#endif // ENABLE_IMGUI // ensures that this canvas is current _set_current(); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 07b3907a3..4ec0f076b 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -750,10 +750,6 @@ private: void render_overlay(const GLCanvas3D& canvas, const Selection& selection) const; -#if !ENABLE_IMGUI - void create_external_gizmo_widgets(wxWindow *parent); -#endif // not ENABLE_IMGUI - private: void reset(); @@ -894,10 +890,6 @@ private: GCodePreviewVolumeIndex m_gcode_preview_volume_index; -#if !ENABLE_IMGUI - wxWindow *m_external_gizmo_widgets_parent; -#endif // not ENABLE_IMGUI - public: GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar); ~GLCanvas3D(); @@ -971,11 +963,6 @@ public: void update_toolbar_items_visibility(); -#if !ENABLE_IMGUI - Rect get_gizmo_reset_rect(const GLCanvas3D& canvas, bool viewport) const; - bool gizmo_reset_rect_contains(const GLCanvas3D& canvas, float x, float y) const; -#endif // not ENABLE_IMGUI - bool is_dragging() const { return m_gizmos.is_dragging() || m_moving; } void render(); @@ -1016,10 +1003,6 @@ public: void set_tooltip(const std::string& tooltip) const; -#if !ENABLE_IMGUI - void set_external_gizmo_widgets_parent(wxWindow *parent); -#endif // not ENABLE_IMGUI - void do_move(); void do_rotate(); void do_scale(); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 1cf2ca17c..89f5d00c9 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -79,9 +79,7 @@ IMPLEMENT_APP(GUI_App) GUI_App::GUI_App() : wxApp() , m_em_unit(10) -#if ENABLE_IMGUI , m_imgui(new ImGuiWrapper()) -#endif // ENABLE_IMGUI {} bool GUI_App::OnInit() @@ -90,10 +88,7 @@ bool GUI_App::OnInit() const wxString resources_dir = from_u8(Slic3r::resources_dir()); wxCHECK_MSG(wxDirExists(resources_dir), false, wxString::Format("Resources path does not exist or is not a directory: %s", resources_dir)); - -#if ENABLE_IMGUI wxCHECK_MSG(m_imgui->init(), false, "Failed to initialize ImGui"); -#endif // ENABLE_IMGUI SetAppName("Slic3rPE-beta"); SetAppDisplayName("Slic3r Prusa Edition"); diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 4c23e3eb7..8f332b855 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -5,9 +5,7 @@ #include #include "libslic3r/PrintConfig.hpp" #include "MainFrame.hpp" -#if ENABLE_IMGUI #include "ImGuiWrapper.hpp" -#endif // ENABLE_IMGUI #include #include @@ -86,10 +84,7 @@ class GUI_App : public wxApp wxLocale* m_wxLocale{ nullptr }; -#if ENABLE_IMGUI std::unique_ptr m_imgui; -#endif // ENABLE_IMGUI - std::unique_ptr m_printhost_job_queue; public: @@ -166,9 +161,7 @@ public: std::vector tabs_list; -#if ENABLE_IMGUI ImGuiWrapper* imgui() { return m_imgui.get(); } -#endif // ENABLE_IMGUI PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); } diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index e2539473b..2211e8d7d 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -30,9 +30,6 @@ namespace GUI { View3D::View3D(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process) : m_canvas_widget(nullptr) , m_canvas(nullptr) -#if !ENABLE_IMGUI - , m_gizmo_widget(nullptr) -#endif // !ENABLE_IMGUI { init(parent, bed, camera, view_toolbar, model, config, process); } @@ -67,17 +64,8 @@ bool View3D::init(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_ m_canvas->enable_gizmos(true); m_canvas->enable_toolbar(true); -#if !ENABLE_IMGUI - m_gizmo_widget = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize); - m_gizmo_widget->SetSizer(new wxBoxSizer(wxVERTICAL)); - m_canvas->set_external_gizmo_widgets_parent(m_gizmo_widget); -#endif // !ENABLE_IMGUI - wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); main_sizer->Add(m_canvas_widget, 1, wxALL | wxEXPAND, 0); -#if !ENABLE_IMGUI - main_sizer->Add(m_gizmo_widget, 0, wxALL | wxEXPAND, 0); -#endif // !ENABLE_IMGUI SetSizer(main_sizer); SetMinSize(GetSize()); diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index c15aad3b3..bfb604c40 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -35,10 +35,6 @@ class View3D : public wxPanel wxGLCanvas* m_canvas_widget; GLCanvas3D* m_canvas; -#if !ENABLE_IMGUI - wxPanel* m_gizmo_widget; -#endif // !ENABLE_IMGUI - public: View3D(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_toolbar, Model* model, DynamicPrintConfig* config, BackgroundSlicingProcess* process); virtual ~View3D(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 3c3f68371..290541a18 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -146,9 +146,7 @@ GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, unsigned int sprite_id) , m_sprite_id(sprite_id) , m_hover_id(-1) , m_dragging(false) -#if ENABLE_IMGUI , m_imgui(wxGetApp().imgui()) -#endif // ENABLE_IMGUI { ::memcpy((void*)m_base_color, (const void*)DEFAULT_BASE_COLOR, 3 * sizeof(float)); ::memcpy((void*)m_drag_color, (const void*)DEFAULT_DRAG_COLOR, 3 * sizeof(float)); @@ -268,9 +266,6 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const } } -#if !ENABLE_IMGUI -void GLGizmoBase::create_external_gizmo_widgets(wxWindow *parent) {} -#endif // not ENABLE_IMGUI void GLGizmoBase::set_tooltip(const std::string& tooltip) const { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 3abd2e607..e8328bcd4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -27,9 +27,7 @@ static const float AXES_COLOR[3][3] = { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f -#if ENABLE_IMGUI class ImGuiWrapper; -#endif // ENABLE_IMGUI class GLGizmoBase @@ -101,9 +99,7 @@ protected: float m_drag_color[3]; float m_highlight_color[3]; mutable std::vector m_grabbers; -#if ENABLE_IMGUI ImGuiWrapper* m_imgui; -#endif // ENABLE_IMGUI public: #if ENABLE_SVG_ICONS @@ -151,14 +147,7 @@ public: void render(const GLCanvas3D::Selection& selection) const { on_render(selection); } void render_for_picking(const GLCanvas3D::Selection& selection) const { on_render_for_picking(selection); } - -#if !ENABLE_IMGUI - virtual void create_external_gizmo_widgets(wxWindow *parent); -#endif // not ENABLE_IMGUI - -#if ENABLE_IMGUI void render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { on_render_input_window(x, y, bottom_limit, selection); } -#endif // ENABLE_IMGUI protected: virtual bool on_init() = 0; @@ -174,10 +163,7 @@ protected: virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection) = 0; virtual void on_render(const GLCanvas3D::Selection& selection) const = 0; virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const = 0; - -#if ENABLE_IMGUI virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) {} -#endif // ENABLE_IMGUI // Returns the picking color for the given id, based on the BASE_ID constant // No check is made for clashing with other picking color (i.e. GLVolumes) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index bd29b1288..54a39c6d5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -75,33 +75,11 @@ GLGizmoCut::GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id) #endif // ENABLE_SVG_ICONS , m_cut_z(0.0) , m_max_z(0.0) -#if !ENABLE_IMGUI - , m_panel(nullptr) -#endif // not ENABLE_IMGUI , m_keep_upper(true) , m_keep_lower(true) , m_rotate_lower(false) {} -#if !ENABLE_IMGUI -void GLGizmoCut::create_external_gizmo_widgets(wxWindow *parent) -{ - wxASSERT(m_panel == nullptr); - - m_panel = new GLGizmoCutPanel(parent); - parent->GetSizer()->Add(m_panel, 0, wxEXPAND); - - parent->Layout(); - parent->Fit(); - auto prev_heigh = parent->GetMinSize().GetHeight(); - parent->SetMinSize(wxSize(-1, std::max(prev_heigh, m_panel->GetSize().GetHeight()))); - - m_panel->Hide(); - m_panel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { - perform_cut(m_parent.get_selection()); - }, wxID_OK); -} -#endif // not ENABLE_IMGUI bool GLGizmoCut::on_init() { @@ -121,13 +99,6 @@ void GLGizmoCut::on_set_state() if (get_state() == On) { m_cut_z = m_parent.get_selection().get_bounding_box().size()(2) / 2.0; } - -#if !ENABLE_IMGUI - // Display or hide the extra panel - if (m_panel != nullptr) { - m_panel->display(get_state() == On); - } -#endif // not ENABLE_IMGUI } bool GLGizmoCut::on_is_activable(const GLCanvas3D::Selection& selection) const @@ -212,7 +183,6 @@ void GLGizmoCut::on_render_for_picking(const GLCanvas3D::Selection& selection) c render_grabbers_for_picking(selection.get_bounding_box()); } -#if ENABLE_IMGUI void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { m_imgui->set_next_window_pos(x, y, ImGuiCond_Always); @@ -236,7 +206,6 @@ void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit, co perform_cut(selection); } } -#endif // ENABLE_IMGUI void GLGizmoCut::update_max_z(const GLCanvas3D::Selection& selection) const { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp index 200e1c0df..beec6d1da 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.hpp @@ -7,10 +7,6 @@ namespace Slic3r { namespace GUI { -#if !ENABLE_IMGUI -class GLGizmoCutPanel; -#endif // not ENABLE_IMGUI - class GLGizmoCut : public GLGizmoBase { static const double Offset; @@ -25,9 +21,6 @@ class GLGizmoCut : public GLGizmoBase bool m_keep_upper; bool m_keep_lower; bool m_rotate_lower; -#if !ENABLE_IMGUI - GLGizmoCutPanel *m_panel; -#endif // not ENABLE_IMGUI public: #if ENABLE_SVG_ICONS @@ -36,12 +29,6 @@ public: GLGizmoCut(GLCanvas3D& parent, unsigned int sprite_id); #endif // ENABLE_SVG_ICONS -#if !ENABLE_IMGUI - virtual void create_external_gizmo_widgets(wxWindow *parent); -#endif // not ENABLE_IMGUI -#if !ENABLE_IMGUI -#endif // not ENABLE_IMGUI - protected: virtual bool on_init(); virtual std::string on_get_name() const; @@ -51,10 +38,8 @@ protected: virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); virtual void on_render(const GLCanvas3D::Selection& selection) const; virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; - -#if ENABLE_IMGUI virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); -#endif // ENABLE_IMGUI + private: void update_max_z(const GLCanvas3D::Selection& selection) const; void set_cut_z(double cut_z) const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 38b0ce23b..d18d71c83 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -166,7 +166,6 @@ void GLGizmoMove3D::on_render_for_picking(const GLCanvas3D::Selection& selection render_grabber_extension(Z, box, true); } -#if ENABLE_IMGUI void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI @@ -184,7 +183,6 @@ void GLGizmoMove3D::on_render_input_window(float x, float y, float bottom_limit, m_imgui->end(); #endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI } -#endif // ENABLE_IMGUI double GLGizmoMove3D::calc_projection(const UpdateData& data) const { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp index 72b067ba9..d4d97de7f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.hpp @@ -42,10 +42,7 @@ protected: virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); virtual void on_render(const GLCanvas3D::Selection& selection) const; virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; - -#if ENABLE_IMGUI virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); -#endif // ENABLE_IMGUI private: double calc_projection(const UpdateData& data) const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index 89ca426e4..4c6f66f4c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -483,7 +483,6 @@ void GLGizmoRotate3D::on_render(const GLCanvas3D::Selection& selection) const m_gizmos[Z].render(selection); } -#if ENABLE_IMGUI void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI @@ -497,7 +496,6 @@ void GLGizmoRotate3D::on_render_input_window(float x, float y, float bottom_limi m_imgui->end(); #endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI } -#endif // ENABLE_IMGUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp index 6281f98cb..aca64c94e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp @@ -131,9 +131,7 @@ protected: } } -#if ENABLE_IMGUI virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); -#endif // ENABLE_IMGUI }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index bb0663e36..acc44e00d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -274,7 +274,6 @@ void GLGizmoScale3D::on_render_for_picking(const GLCanvas3D::Selection& selectio render_grabbers_for_picking(selection.get_bounding_box()); } -#if ENABLE_IMGUI void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { #if !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI @@ -288,7 +287,6 @@ void GLGizmoScale3D::on_render_input_window(float x, float y, float bottom_limit m_imgui->end(); #endif // !DISABLE_MOVE_ROTATE_SCALE_GIZMOS_IMGUI } -#endif // ENABLE_IMGUI void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2) const { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp index a6ee40c1a..8554e57a7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.hpp @@ -42,10 +42,7 @@ protected: virtual void on_update(const UpdateData& data, const GLCanvas3D::Selection& selection); virtual void on_render(const GLCanvas3D::Selection& selection) const; virtual void on_render_for_picking(const GLCanvas3D::Selection& selection) const; - -#if ENABLE_IMGUI virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection); -#endif // ENABLE_IMGUI private: void render_grabbers_connection(unsigned int id_1, unsigned int id_2) const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index c43f80de2..695564971 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -80,10 +80,6 @@ void GLGizmoSlaSupports::on_render(const GLCanvas3D::Selection& selection) const render_points(selection, false); render_selection_rectangle(); -#if !ENABLE_IMGUI - render_tooltip_texture(); -#endif // not ENABLE_IMGUI - ::glDisable(GL_BLEND); } @@ -505,38 +501,6 @@ void GLGizmoSlaSupports::on_update(const UpdateData& data, const GLCanvas3D::Sel } } -#if !ENABLE_IMGUI -void GLGizmoSlaSupports::render_tooltip_texture() const { - if (m_tooltip_texture.get_id() == 0) - if (!m_tooltip_texture.load_from_file(resources_dir() + "/icons/sla_support_points_tooltip.png", false)) - return; - if (m_reset_texture.get_id() == 0) - if (!m_reset_texture.load_from_file(resources_dir() + "/icons/sla_support_points_reset.png", false)) - return; - - float zoom = m_parent.get_camera_zoom(); - float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; - float gap = 30.0f * inv_zoom; - - const Size& cnv_size = m_parent.get_canvas_size(); - float l = gap - cnv_size.get_width()/2.f * inv_zoom; - float r = l + (float)m_tooltip_texture.get_width() * inv_zoom; - float b = gap - cnv_size.get_height()/2.f * inv_zoom; - float t = b + (float)m_tooltip_texture.get_height() * inv_zoom; - - Rect reset_rect = m_parent.get_gizmo_reset_rect(m_parent, true); - - ::glDisable(GL_DEPTH_TEST); - ::glPushMatrix(); - ::glLoadIdentity(); - GLTexture::render_texture(m_tooltip_texture.get_id(), l, r, b, t); - GLTexture::render_texture(m_reset_texture.get_id(), reset_rect.get_left(), reset_rect.get_right(), reset_rect.get_bottom(), reset_rect.get_top()); - ::glPopMatrix(); - ::glEnable(GL_DEPTH_TEST); -} -#endif // not ENABLE_IMGUI - - std::vector GLGizmoSlaSupports::get_config_options(const std::vector& keys) const { std::vector out; @@ -578,7 +542,6 @@ void GLGizmoSlaSupports::update_cache_entry_normal(unsigned int i) const -#if ENABLE_IMGUI void GLGizmoSlaSupports::on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) { if (!m_model_object) @@ -722,7 +685,6 @@ RENDER_AGAIN: if (force_refresh) m_parent.set_as_dirty(); } -#endif // ENABLE_IMGUI bool GLGizmoSlaSupports::on_is_activable(const GLCanvas3D::Selection& selection) const { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index 44842e5c5..492bb85ca 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -75,12 +75,6 @@ private: void update_mesh(); void update_cache_entry_normal(unsigned int i) const; -#if !ENABLE_IMGUI - void render_tooltip_texture() const; - mutable GLTexture m_tooltip_texture; - mutable GLTexture m_reset_texture; -#endif // not ENABLE_IMGUI - bool m_lock_unique_islands = false; bool m_editing_mode = false; // Is editing mode active? bool m_old_editing_state = false; // To keep track of whether the user toggled between the modes (needed for imgui refreshes). @@ -120,10 +114,7 @@ private: protected: void on_set_state() override; void on_start_dragging(const GLCanvas3D::Selection& selection) override; - -#if ENABLE_IMGUI virtual void on_render_input_window(float x, float y, float bottom_limit, const GLCanvas3D::Selection& selection) override; -#endif // ENABLE_IMGUI virtual std::string on_get_name() const; virtual bool on_is_activable(const GLCanvas3D::Selection& selection) const; From 96fb6dff29e20742d1053c21a87047b76b660d3e Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 18 Mar 2019 12:37:14 +0100 Subject: [PATCH 23/23] Fixed GLVolume::get_volume_scaling_factor() declaration --- src/slic3r/GUI/3DScene.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 5daf4b941..15ac6a3a1 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -364,7 +364,7 @@ public: void set_volume_rotation(const Vec3d& rotation) { m_volume_transformation.set_rotation(rotation); set_bounding_boxes_as_dirty(); } void set_volume_rotation(Axis axis, double rotation) { m_volume_transformation.set_rotation(axis, rotation); set_bounding_boxes_as_dirty(); } - Vec3d get_volume_scaling_factor() const { return m_volume_transformation.get_scaling_factor(); } + const Vec3d& get_volume_scaling_factor() const { return m_volume_transformation.get_scaling_factor(); } double get_volume_scaling_factor(Axis axis) const { return m_volume_transformation.get_scaling_factor(axis); } void set_volume_scaling_factor(const Vec3d& scaling_factor) { m_volume_transformation.set_scaling_factor(scaling_factor); set_bounding_boxes_as_dirty(); }