Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnrico Turri <enricoturri@seznam.cz>2019-03-26 11:01:04 +0300
committerEnrico Turri <enricoturri@seznam.cz>2019-03-26 11:01:04 +0300
commit3818bfa19ac19d1790f514c8604b30c0b9926e70 (patch)
tree4df1ff528ba6700ac38963bc48fd408b01db3bb1 /src/slic3r
parenta8cf701520ab9755105c1cd958ecee2247152f41 (diff)
parent3e0ec8098bce46673c4b0325b85825008ead9d03 (diff)
1st installment of gizmos refactoring
1) GLCanvas3D::Gizmos moved into a standalone class GLGizmosManager 2) GLGizmosManager handles mouse events by calling its on_mouse method (wip)
Diffstat (limited to 'src/slic3r')
-rw-r--r--src/slic3r/GUI/Field.cpp5
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp446
-rw-r--r--src/slic3r/GUI/GLCanvas3D.hpp13
-rw-r--r--src/slic3r/GUI/GLToolbar.cpp32
-rw-r--r--src/slic3r/GUI/GLToolbar.hpp2
-rw-r--r--src/slic3r/GUI/GUI_ObjectManipulation.cpp4
-rw-r--r--src/slic3r/GUI/GUI_ObjectSettings.cpp7
-rw-r--r--src/slic3r/GUI/GUI_Preview.cpp47
-rw-r--r--src/slic3r/GUI/GUI_Preview.hpp4
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp6
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmosManager.cpp340
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmosManager.hpp37
-rw-r--r--src/slic3r/GUI/Plater.cpp23
-rw-r--r--src/slic3r/GUI/Plater.hpp8
-rw-r--r--src/slic3r/GUI/Preset.cpp86
-rw-r--r--src/slic3r/GUI/Preset.hpp22
-rw-r--r--src/slic3r/GUI/PresetBundle.cpp10
-rw-r--r--src/slic3r/GUI/Tab.cpp101
-rw-r--r--src/slic3r/GUI/Tab.hpp3
19 files changed, 859 insertions, 337 deletions
diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp
index 026b62ab5..9cd933160 100644
--- a/src/slic3r/GUI/Field.cpp
+++ b/src/slic3r/GUI/Field.cpp
@@ -540,7 +540,10 @@ void Choice::BUILD() {
else{
for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels) {
const wxString& str = _(el);//m_opt_id == "support" ? _(el) : el;
- temp->Append(str, create_scaled_bitmap("empty_icon.png"));
+ //FIXME Vojtech: Why is the single column empty icon necessary? It is a workaround of some kind, but what for?
+ // Please document such workarounds by comments!
+ // temp->Append(str, create_scaled_bitmap("empty_icon.png"));
+ temp->Append(str, wxNullBitmap);
}
set_selection();
}
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index bf0e1785a..e4f0f461e 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -34,6 +34,7 @@
#include <wx/settings.h>
#include <wx/tooltip.h>
#include <wx/debug.h>
+#include <wx/fontutil.h>
// Print now includes tbb, and tbb includes Windows. This breaks compilation of wxWidgets if included before wx.
#include "libslic3r/Print.hpp"
@@ -728,13 +729,69 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool
_generate(text, canvas, red_colored); // GUI::GLTexture::reset() is called at the beginning of generate(...)
}
-bool GLCanvas3D::WarningTexture::_generate(const std::string& msg, const GLCanvas3D& canvas, const bool red_colored/* = false*/)
+
+#ifdef __WXMSW__
+static bool is_font_cleartype(const wxFont &font)
+{
+ // Native font description: on MSW, it is a version number plus the content of LOGFONT, separated by semicolon.
+ wxString font_desc = font.GetNativeFontInfoDesc();
+ // Find the quality field.
+ wxString sep(";");
+ size_t startpos = 0;
+ for (size_t i = 0; i < 12; ++ i)
+ startpos = font_desc.find(sep, startpos + 1);
+ ++ startpos;
+ size_t endpos = font_desc.find(sep, startpos);
+ int quality = wxAtoi(font_desc(startpos, endpos - startpos));
+ return quality == CLEARTYPE_QUALITY;
+}
+
+// ClearType produces renders, which are difficult to convert into an alpha blended OpenGL texture.
+// Therefore it is better to disable it, though Vojtech found out, that the font returned with ClearType
+// disabled is signifcantly thicker than the default ClearType font.
+// This function modifies the font provided.
+static void msw_disable_cleartype(wxFont &font)
+{
+ // Native font description: on MSW, it is a version number plus the content of LOGFONT, separated by semicolon.
+ wxString font_desc = font.GetNativeFontInfoDesc();
+ // Find the quality field.
+ wxString sep(";");
+ size_t startpos_weight = 0;
+ for (size_t i = 0; i < 5; ++ i)
+ startpos_weight = font_desc.find(sep, startpos_weight + 1);
+ ++ startpos_weight;
+ size_t endpos_weight = font_desc.find(sep, startpos_weight);
+ // Parse the weight field.
+ unsigned int weight = atoi(font_desc(startpos_weight, endpos_weight - startpos_weight));
+ size_t startpos = endpos_weight;
+ for (size_t i = 0; i < 6; ++ i)
+ startpos = font_desc.find(sep, startpos + 1);
+ ++ startpos;
+ size_t endpos = font_desc.find(sep, startpos);
+ int quality = wxAtoi(font_desc(startpos, endpos - startpos));
+ if (quality == CLEARTYPE_QUALITY) {
+ // Replace the weight with a smaller value to compensate the weight of non ClearType font.
+ wxString sweight = std::to_string(weight * 2 / 4);
+ size_t len_weight = endpos_weight - startpos_weight;
+ wxString squality = std::to_string(ANTIALIASED_QUALITY);
+ font_desc.replace(startpos_weight, len_weight, sweight);
+ font_desc.replace(startpos + sweight.size() - len_weight, endpos - startpos, squality);
+ font.SetNativeFontInfo(font_desc);
+ wxString font_desc2 = font.GetNativeFontInfoDesc();
+ }
+ wxString font_desc2 = font.GetNativeFontInfoDesc();
+}
+#endif /* __WXMSW__ */
+
+bool GLCanvas3D::WarningTexture::_generate(const std::string& msg_utf8, const GLCanvas3D& canvas, const bool red_colored/* = false*/)
{
reset();
- if (msg.empty())
+ if (msg_utf8.empty())
return false;
+ wxString msg = GUI::from_u8(msg_utf8);
+
wxMemoryDC memDC;
// select default font
const float scale = canvas.get_canvas_size().get_scale_factor();
@@ -745,46 +802,47 @@ bool GLCanvas3D::WarningTexture::_generate(const std::string& msg, const GLCanva
// calculates texture size
wxCoord w, h;
-// memDC.GetTextExtent(msg, &w, &h);
memDC.GetMultiLineTextExtent(msg, &w, &h);
- int pow_of_two_size = next_highest_power_of_2(std::max<unsigned int>(w, h));
-
m_original_width = (int)w;
m_original_height = (int)h;
- m_width = pow_of_two_size;
- m_height = pow_of_two_size;
+ m_width = (int)next_highest_power_of_2((uint32_t)w);
+ m_height = (int)next_highest_power_of_2((uint32_t)h);
// generates bitmap
wxBitmap bitmap(m_width, m_height);
memDC.SelectObject(bitmap);
- memDC.SetBackground(wxBrush(wxColour(Background_Color[0], Background_Color[1], Background_Color[2])));
+ memDC.SetBackground(wxBrush(*wxBLACK));
memDC.Clear();
// draw message
- memDC.SetTextForeground(red_colored ? wxColour(255,72,65/*204,204*/) : *wxWHITE);
-// memDC.DrawText(msg, 0, 0);
- memDC.DrawLabel(msg, wxRect(0,0, m_original_width, m_original_height), wxALIGN_CENTER);
+ memDC.SetTextForeground(*wxRED);
+ memDC.DrawLabel(msg, wxRect(0,0, m_original_width, m_original_height), wxALIGN_CENTER);
memDC.SelectObject(wxNullBitmap);
// Convert the bitmap into a linear data ready to be loaded into the GPU.
wxImage image = bitmap.ConvertToImage();
- image.SetMaskColour(Background_Color[0], Background_Color[1], Background_Color[2]);
// prepare buffer
std::vector<unsigned char> data(4 * m_width * m_height, 0);
+ const unsigned char *src = image.GetData();
for (int h = 0; h < m_height; ++h)
{
- int hh = h * m_width;
- unsigned char* px_ptr = data.data() + 4 * hh;
+ unsigned char* dst = data.data() + 4 * h * m_width;
for (int w = 0; w < m_width; ++w)
{
- *px_ptr++ = image.GetRed(w, h);
- *px_ptr++ = image.GetGreen(w, h);
- *px_ptr++ = image.GetBlue(w, h);
- *px_ptr++ = image.IsTransparent(w, h) ? 0 : Opacity;
+ *dst++ = 255;
+ if (red_colored) {
+ *dst++ = 72; // 204
+ *dst++ = 65; // 204
+ } else {
+ *dst++ = 255;
+ *dst++ = 255;
+ }
+ *dst++ = (unsigned char)std::min<int>(255, *src);
+ src += 3;
}
}
@@ -908,7 +966,15 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
const int scaled_border = Px_Border * scale;
// select default font
- const wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale_gl);
+ wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale_gl);
+#ifdef __WXMSW__
+ // Disabling ClearType works, but the font returned is very different (much thicker) from the default.
+// msw_disable_cleartype(font);
+ bool cleartype = is_font_cleartype(font);
+#else
+ bool cleartype = false;
+#endif /* __WXMSW__ */
+
memDC.SetFont(font);
mask_memDC.SetFont(font);
@@ -932,10 +998,8 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
if (items_count > 1)
m_original_height += (items_count - 1) * scaled_square_contour;
- int pow_of_two_size = (int)next_highest_power_of_2(std::max<uint32_t>(m_original_width, m_original_height));
-
- m_width = pow_of_two_size;
- m_height = pow_of_two_size;
+ m_width = (int)next_highest_power_of_2((uint32_t)m_original_width);
+ m_height = (int)next_highest_power_of_2((uint32_t)m_original_height);
// generates bitmap
wxBitmap bitmap(m_width, m_height);
@@ -952,16 +1016,13 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
// draw title
memDC.SetTextForeground(*wxWHITE);
- mask_memDC.SetTextForeground(*wxWHITE);
+ mask_memDC.SetTextForeground(*wxRED);
int title_x = scaled_border;
int title_y = scaled_border;
memDC.DrawText(title, title_x, title_y);
mask_memDC.DrawText(title, title_x, title_y);
- mask_memDC.SetPen(wxPen(*wxWHITE));
- mask_memDC.SetBrush(wxBrush(*wxWHITE));
-
// draw icons contours as background
int squares_contour_x = scaled_border;
int squares_contour_y = scaled_border + title_height + scaled_title_offset;
@@ -976,7 +1037,6 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
memDC.SetPen(pen);
memDC.SetBrush(brush);
memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height));
- mask_memDC.DrawRectangle(wxRect(squares_contour_x, squares_contour_y, squares_contour_width, squares_contour_height));
// draw items (colored icon + text)
int icon_x = squares_contour_x + scaled_square_contour;
@@ -1012,7 +1072,6 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
memDC.DrawRectangle(wxRect(icon_x_inner, icon_y + 1, px_inner_square, px_inner_square));
// draw text
- memDC.DrawText(GUI::from_u8(item.text), text_x, icon_y + text_y_offset);
mask_memDC.DrawText(GUI::from_u8(item.text), text_x, icon_y + text_y_offset);
// update y
@@ -1028,17 +1087,34 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
// prepare buffer
std::vector<unsigned char> data(4 * m_width * m_height, 0);
- for (int h = 0; h < m_height; ++h)
+ const unsigned char *src_image = image.GetData();
+ const unsigned char *src_mask = mask_image.GetData();
+ for (int h = 0; h < m_height; ++h)
{
int hh = h * m_width;
unsigned char* px_ptr = data.data() + 4 * hh;
for (int w = 0; w < m_width; ++w)
{
- unsigned char alpha = (mask_image.GetRed(w, h) + mask_image.GetGreen(w, h) + mask_image.GetBlue(w, h)) / 3;
- *px_ptr++ = image.GetRed(w, h);
- *px_ptr++ = image.GetGreen(w, h);
- *px_ptr++ = image.GetBlue(w, h);
- *px_ptr++ = (alpha == 0) ? 128 : 255;
+ if (w >= squares_contour_x && w < squares_contour_x + squares_contour_width &&
+ h >= squares_contour_y && h < squares_contour_y + squares_contour_height) {
+ // Color palette, use the color verbatim.
+ *px_ptr++ = *src_image++;
+ *px_ptr++ = *src_image++;
+ *px_ptr++ = *src_image++;
+ *px_ptr++ = 255;
+ } else {
+ // Text or background
+ unsigned char alpha = *src_mask;
+ // Compensate the white color for the 50% opacity reduction at the character edges.
+ //unsigned char color = (unsigned char)floor(alpha * 255.f / (128.f + 0.5f * alpha));
+ unsigned char color = alpha;
+ *px_ptr++ = color;
+ *px_ptr++ = color; // *src_mask ++;
+ *px_ptr++ = color; // *src_mask ++;
+ *px_ptr++ = 128 + (alpha / 2); // (alpha > 0) ? 255 : 128;
+ src_image += 3;
+ }
+ src_mask += 3;
}
}
@@ -1286,11 +1362,13 @@ int GLCanvas3D::check_volumes_outside_state() const
return (int)state;
}
-void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible)
+void GLCanvas3D::toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo, int instance_idx)
{
for (GLVolume* vol : m_volumes.volumes) {
- if (vol->composite_id.volume_id < 0)
- vol->is_active = visible;
+ if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo)
+ && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx)
+ && vol->composite_id.volume_id < 0)
+ vol->is_active = visible;
}
m_render_sla_auxiliaries = visible;
@@ -1306,7 +1384,7 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject
}
}
if (visible && !mo)
- toggle_sla_auxiliaries_visibility(true);
+ toggle_sla_auxiliaries_visibility(true, mo, instance_idx);
if (!mo && !visible && !m_model->objects.empty() && (m_model->objects.size() > 1 || m_model->objects.front()->instances.size() > 1))
_set_warning_texture(WarningTexture::SomethingNotShown, true);
@@ -1938,7 +2016,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
m_selection.volumes_changed(map_glvolume_old_to_new);
}
- _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ update_gizmos_data();
+// _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Update the toolbar
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
@@ -2253,7 +2334,10 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
{
if (m_gizmos.handle_shortcut(keyCode, m_selection))
{
- _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ update_gizmos_data();
+// _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
m_dirty = true;
}
else
@@ -2432,13 +2516,25 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
return;
}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ std::cout << to_string(m_mouse.position) << std::endl;
+
+ if (m_gizmos.on_mouse(evt, *this))
+ {
+ m_mouse.set_start_position_3D_as_invalid();
+ return;
+ }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
if (m_picking_enabled)
_set_current();
int selected_object_idx = m_selection.get_object_idx();
int layer_editing_object_idx = is_layers_editing_enabled() ? selected_object_idx : -1;
m_layers_editing.select_object(*m_model, layer_editing_object_idx);
- bool gizmos_overlay_contains_mouse = m_gizmos.overlay_contains_mouse(*this, m_mouse.position);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+// bool gizmos_overlay_contains_mouse = m_gizmos.overlay_contains_mouse(*this, m_mouse.position);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
if (m_mouse.drag.move_requires_threshold && m_mouse.is_move_start_threshold_position_2D_defined() && m_mouse.is_move_threshold_met(pos))
{
@@ -2508,15 +2604,27 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true;
}
}
- else if (!m_selection.is_empty() && gizmos_overlay_contains_mouse)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+// else if (!m_selection.is_empty() && gizmos_overlay_contains_mouse)
+// {
+// m_gizmos.update_on_off_state(*this, m_mouse.position, m_selection);
+// _update_gizmos_data();
+// m_dirty = true;
+// }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ else if (evt.LeftDown() && m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::LeftDown, Vec2d(pos(0), pos(1)), evt.ShiftDown()))
+// else if (evt.LeftDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::LeftDown, Vec2d(pos(0), pos(1)), evt.ShiftDown()))
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
{
- m_gizmos.update_on_off_state(*this, m_mouse.position, m_selection);
- _update_gizmos_data();
- m_dirty = true;
+ // the gizmo got the event and took some action, there is no need to do anything more
}
else if (evt.LeftDown() && !m_selection.is_empty() && m_gizmos.grabber_contains_mouse())
{
- _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ update_gizmos_data();
+// _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
m_selection.start_dragging();
m_gizmos.start_dragging(m_selection);
@@ -2529,11 +2637,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true;
}
- else if (evt.LeftDown() && m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::LeftDown, Vec2d(pos(0), pos(1)), evt.ShiftDown()))
- {
- // the gizmo got the event and took some action, there is no need to do anything more
- }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
else if ((selected_object_idx != -1) && evt.RightDown() && m_gizmos.get_current_type() == GLGizmosManager::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::RightDown))
+// else if ((selected_object_idx != -1) && evt.RightDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::RightDown))
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
{
// event was taken care of by the SlaSupports gizmo
}
@@ -2569,7 +2676,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
{
m_gizmos.update_on_off_state(m_selection);
- _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ update_gizmos_data();
+// _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
m_dirty = true;
}
@@ -2596,7 +2706,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
}
- else if (evt.Dragging() && evt.LeftIsDown() && !gizmos_overlay_contains_mouse && (m_layers_editing.state == LayersEditing::Unknown)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ else if (evt.Dragging() && evt.LeftIsDown() && (m_layers_editing.state == LayersEditing::Unknown)
+// else if (evt.Dragging() && evt.LeftIsDown() && !gizmos_overlay_contains_mouse && (m_layers_editing.state == LayersEditing::Unknown)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
&& (m_mouse.drag.move_volume_idx != -1) && m_gizmos.get_current_type() != GLGizmosManager::SlaSupports /* don't allow dragging objects with the Sla gizmo on */)
{
if (!m_mouse.drag.move_requires_threshold)
@@ -2695,8 +2808,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// the gizmo got the event and took some action, no need to do anything more here
m_dirty = true;
}
- // do not process dragging if the mouse is into any of the HUD elements
- else if (evt.Dragging() && !gizmos_overlay_contains_mouse)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ else if (evt.Dragging())
+// // do not process dragging if the mouse is into any of the HUD elements
+// else if (evt.Dragging() && !gizmos_overlay_contains_mouse)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
{
m_mouse.dragging = true;
@@ -2758,8 +2874,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
// of the scene with the background processing data should be performed.
post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED));
}
- else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging()
- && !is_layers_editing_enabled())
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !m_gizmos.is_dragging()
+// else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging()
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ && !is_layers_editing_enabled())
{
// deselect and propagate event through callback
if (!evt.ShiftDown() && m_picking_enabled && !m_mouse.ignore_up_event)
@@ -2768,7 +2887,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_selection.set_mode(Selection::Instance);
wxGetApp().obj_manipul()->update_settings_value(m_selection);
m_gizmos.reset_all_states();
- _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ update_gizmos_data();
+// _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
post_event(SimpleEvent(EVT_GLCANVAS_OBJECT_SELECT));
}
m_mouse.ignore_up_event = false;
@@ -2797,7 +2919,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
break;
}
m_gizmos.stop_dragging();
- _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ update_gizmos_data();
+// _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
wxGetApp().obj_manipul()->update_settings_value(m_selection);
// Let the platter know that the dragging finished, so a delayed refresh
@@ -2822,7 +2947,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
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();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ update_gizmos_data();
+// _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();
@@ -2853,9 +2981,14 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
std::string tooltip = "";
// updates gizmos overlay
- tooltip = m_gizmos.update_hover_state(*this, m_mouse.position, m_selection);
- if (m_selection.is_empty())
- m_gizmos.reset_all_states();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ if (tooltip.empty())
+ tooltip = m_gizmos.get_tooltip();
+
+// tooltip = m_gizmos.update_hover_state(*this, m_mouse.position, m_selection);
+// if (m_selection.is_empty())
+// m_gizmos.reset_all_states();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
if (tooltip.empty())
tooltip = m_toolbar.get_tooltip();
@@ -2865,6 +2998,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
set_tooltip(tooltip);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ if (m_selection.is_empty())
+ m_gizmos.reset_all_states();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
// Only refresh if picking is enabled, in that case the objects may get highlighted if the mouse cursor hovers over.
if (m_picking_enabled)
m_dirty = true;
@@ -3172,7 +3310,10 @@ void GLCanvas3D::set_camera_zoom(float zoom)
void GLCanvas3D::update_gizmos_on_off_state()
{
set_as_dirty();
- _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ update_gizmos_data();
+// _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
m_gizmos.update_on_off_state(get_selection());
}
@@ -3207,6 +3348,48 @@ void GLCanvas3D::update_ui_from_settings()
#endif
}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+void GLCanvas3D::update_gizmos_data()
+{
+ if (!m_gizmos.is_enabled())
+ return;
+
+ bool enable_move_z = !m_selection.is_wipe_tower();
+ m_gizmos.enable_grabber(GLGizmosManager::Move, 2, enable_move_z);
+ bool enable_scale_xyz = m_selection.is_single_full_instance() || m_selection.is_single_volume() || m_selection.is_single_modifier();
+ for (int i = 0; i < 6; ++i)
+ {
+ m_gizmos.enable_grabber(GLGizmosManager::Scale, i, enable_scale_xyz);
+ }
+
+ if (m_selection.is_single_full_instance())
+ {
+ // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first
+ const GLVolume* volume = m_volumes.volumes[*m_selection.get_volume_idxs().begin()];
+ m_gizmos.set_scale(volume->get_instance_scaling_factor());
+ m_gizmos.set_rotation(Vec3d::Zero());
+ ModelObject* model_object = m_model->objects[m_selection.get_object_idx()];
+ m_gizmos.set_flattening_data(model_object);
+ m_gizmos.set_sla_support_data(model_object, m_selection);
+ }
+ else if (m_selection.is_single_volume() || m_selection.is_single_modifier())
+ {
+ const GLVolume* volume = m_volumes.volumes[*m_selection.get_volume_idxs().begin()];
+ m_gizmos.set_scale(volume->get_volume_scaling_factor());
+ m_gizmos.set_rotation(Vec3d::Zero());
+ m_gizmos.set_flattening_data(nullptr);
+ m_gizmos.set_sla_support_data(nullptr, m_selection);
+ }
+ else
+ {
+ m_gizmos.set_scale(Vec3d::Ones());
+ m_gizmos.set_rotation(Vec3d::Zero());
+ m_gizmos.set_flattening_data(m_selection.is_from_single_object() ? m_model->objects[m_selection.get_object_idx()] : nullptr);
+ m_gizmos.set_sla_support_data(nullptr, m_selection);
+ }
+}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
bool GLCanvas3D::_is_shown_on_screen() const
{
return (m_canvas != nullptr) ? m_canvas->IsShownOnScreen() : false;
@@ -3964,24 +4147,20 @@ void GLCanvas3D::_render_sla_slices() const
{
const SLAPrintObject* obj = print_objects[i];
- double shift_z = obj->get_current_elevation();
- double min_z = clip_min_z - shift_z;
- double max_z = clip_max_z - shift_z;
-
SlaCap::ObjectIdToTrianglesMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i);
SlaCap::ObjectIdToTrianglesMap::iterator it_caps_top = m_sla_caps[1].triangles.find(i);
{
if (it_caps_bottom == m_sla_caps[0].triangles.end())
it_caps_bottom = m_sla_caps[0].triangles.emplace(i, SlaCap::Triangles()).first;
- if (! m_sla_caps[0].matches(min_z)) {
- m_sla_caps[0].z = min_z;
+ if (! m_sla_caps[0].matches(clip_min_z)) {
+ m_sla_caps[0].z = clip_min_z;
it_caps_bottom->second.object.clear();
it_caps_bottom->second.supports.clear();
}
if (it_caps_top == m_sla_caps[1].triangles.end())
it_caps_top = m_sla_caps[1].triangles.emplace(i, SlaCap::Triangles()).first;
- if (! m_sla_caps[1].matches(max_z)) {
- m_sla_caps[1].z = max_z;
+ if (! m_sla_caps[1].matches(clip_max_z)) {
+ m_sla_caps[1].z = clip_max_z;
it_caps_top->second.object.clear();
it_caps_top->second.supports.clear();
}
@@ -4001,36 +4180,39 @@ void GLCanvas3D::_render_sla_slices() const
std::vector<InstanceTransform> instance_transforms;
for (const SLAPrintObject::Instance& inst : instances)
{
- instance_transforms.push_back({ to_3d(unscale(inst.shift), shift_z), Geometry::rad2deg(inst.rotation) });
+ instance_transforms.push_back({ to_3d(unscale(inst.shift), 0.), Geometry::rad2deg(inst.rotation) });
}
if ((bottom_obj_triangles.empty() || bottom_sup_triangles.empty() || top_obj_triangles.empty() || top_sup_triangles.empty()) && obj->is_step_done(slaposIndexSlices))
{
- const std::vector<ExPolygons>& model_slices = obj->get_model_slices();
- const std::vector<ExPolygons>& support_slices = obj->get_support_slices();
-
- const SLAPrintObject::SliceIndex& index = obj->get_slice_index();
- SLAPrintObject::SliceIndex::const_iterator it_min_z = std::find_if(index.begin(), index.end(), [min_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(min_z - id.first) < EPSILON; });
- SLAPrintObject::SliceIndex::const_iterator it_max_z = std::find_if(index.begin(), index.end(), [max_z](const SLAPrintObject::SliceIndex::value_type& id) -> bool { return std::abs(max_z - id.first) < EPSILON; });
-
- if (it_min_z != index.end())
- {
+ double initial_layer_height = print->material_config().initial_layer_height.value;
+ LevelID key_zero = obj->get_slice_records().begin()->key();
+ LevelID key_low = LevelID((clip_min_z - initial_layer_height) / SCALING_FACTOR) + key_zero;
+ LevelID key_high = LevelID((clip_max_z - initial_layer_height) / SCALING_FACTOR) + key_zero;
+ auto slice_range = obj->get_slice_records(key_low - LevelID(SCALED_EPSILON), key_high - LevelID(SCALED_EPSILON));
+ auto it_low = slice_range.begin();
+ auto it_high = std::prev(slice_range.end());
+
+ if (! it_low.is_end() && it_low->key() < key_low + LevelID(SCALED_EPSILON)) {
+ const ExPolygons& obj_bottom = obj->get_slices_from_record(it_low, soModel);
+ const ExPolygons& sup_bottom = obj->get_slices_from_record(it_low, soSupport);
// calculate model bottom cap
- if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size()))
- bottom_obj_triangles = triangulate_expolygons_3d(model_slices[it_min_z->second.model_slices_idx], min_z, true);
+ if (bottom_obj_triangles.empty() && !obj_bottom.empty())
+ bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, clip_min_z, true);
// calculate support bottom cap
- if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size()))
- bottom_sup_triangles = triangulate_expolygons_3d(support_slices[it_min_z->second.support_slices_idx], min_z, true);
+ if (bottom_sup_triangles.empty() && !sup_bottom.empty())
+ bottom_sup_triangles = triangulate_expolygons_3d(sup_bottom, clip_min_z, true);
}
- if (it_max_z != index.end())
- {
+ if (! it_high.is_end() && it_high->key() < key_high + LevelID(SCALED_EPSILON)) {
+ const ExPolygons& obj_top = obj->get_slices_from_record(it_high, soModel);
+ const ExPolygons& sup_top = obj->get_slices_from_record(it_high, soSupport);
// calculate model top cap
- if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size()))
- top_obj_triangles = triangulate_expolygons_3d(model_slices[it_max_z->second.model_slices_idx], max_z, false);
+ if (top_obj_triangles.empty() && !obj_top.empty())
+ top_obj_triangles = triangulate_expolygons_3d(obj_top, clip_max_z, false);
// calculate support top cap
- if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size()))
- top_sup_triangles = triangulate_expolygons_3d(support_slices[it_max_z->second.support_slices_idx], max_z, false);
+ if (top_sup_triangles.empty() && !sup_top.empty())
+ top_sup_triangles = triangulate_expolygons_3d(sup_top, clip_max_z, false);
}
}
@@ -4122,45 +4304,47 @@ void GLCanvas3D::_update_volumes_hover_state() const
}
}
-void GLCanvas3D::_update_gizmos_data()
-{
- if (!m_gizmos.is_enabled())
- return;
-
- bool enable_move_z = !m_selection.is_wipe_tower();
- m_gizmos.enable_grabber(GLGizmosManager::Move, 2, enable_move_z);
- bool enable_scale_xyz = m_selection.is_single_full_instance() || m_selection.is_single_volume() || m_selection.is_single_modifier();
- for (int i = 0; i < 6; ++i)
- {
- m_gizmos.enable_grabber(GLGizmosManager::Scale, i, enable_scale_xyz);
- }
-
- if (m_selection.is_single_full_instance())
- {
- // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first
- const GLVolume* volume = m_volumes.volumes[*m_selection.get_volume_idxs().begin()];
- m_gizmos.set_scale(volume->get_instance_scaling_factor());
- m_gizmos.set_rotation(Vec3d::Zero());
- ModelObject* model_object = m_model->objects[m_selection.get_object_idx()];
- m_gizmos.set_flattening_data(model_object);
- m_gizmos.set_sla_support_data(model_object, m_selection);
- }
- else if (m_selection.is_single_volume() || m_selection.is_single_modifier())
- {
- const GLVolume* volume = m_volumes.volumes[*m_selection.get_volume_idxs().begin()];
- m_gizmos.set_scale(volume->get_volume_scaling_factor());
- m_gizmos.set_rotation(Vec3d::Zero());
- m_gizmos.set_flattening_data(nullptr);
- m_gizmos.set_sla_support_data(nullptr, m_selection);
- }
- else
- {
- m_gizmos.set_scale(Vec3d::Ones());
- m_gizmos.set_rotation(Vec3d::Zero());
- m_gizmos.set_flattening_data(m_selection.is_from_single_object() ? m_model->objects[m_selection.get_object_idx()] : nullptr);
- m_gizmos.set_sla_support_data(nullptr, m_selection);
- }
-}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+//void GLCanvas3D::_update_gizmos_data()
+//{
+// if (!m_gizmos.is_enabled())
+// return;
+//
+// bool enable_move_z = !m_selection.is_wipe_tower();
+// m_gizmos.enable_grabber(GLGizmosManager::Move, 2, enable_move_z);
+// bool enable_scale_xyz = m_selection.is_single_full_instance() || m_selection.is_single_volume() || m_selection.is_single_modifier();
+// for (int i = 0; i < 6; ++i)
+// {
+// m_gizmos.enable_grabber(GLGizmosManager::Scale, i, enable_scale_xyz);
+// }
+//
+// if (m_selection.is_single_full_instance())
+// {
+// // all volumes in the selection belongs to the same instance, any of them contains the needed data, so we take the first
+// const GLVolume* volume = m_volumes.volumes[*m_selection.get_volume_idxs().begin()];
+// m_gizmos.set_scale(volume->get_instance_scaling_factor());
+// m_gizmos.set_rotation(Vec3d::Zero());
+// ModelObject* model_object = m_model->objects[m_selection.get_object_idx()];
+// m_gizmos.set_flattening_data(model_object);
+// m_gizmos.set_sla_support_data(model_object, m_selection);
+// }
+// else if (m_selection.is_single_volume() || m_selection.is_single_modifier())
+// {
+// const GLVolume* volume = m_volumes.volumes[*m_selection.get_volume_idxs().begin()];
+// m_gizmos.set_scale(volume->get_volume_scaling_factor());
+// m_gizmos.set_rotation(Vec3d::Zero());
+// m_gizmos.set_flattening_data(nullptr);
+// m_gizmos.set_sla_support_data(nullptr, m_selection);
+// }
+// else
+// {
+// m_gizmos.set_scale(Vec3d::Ones());
+// m_gizmos.set_rotation(Vec3d::Zero());
+// m_gizmos.set_flattening_data(m_selection.is_from_single_object() ? m_model->objects[m_selection.get_object_idx()] : nullptr);
+// m_gizmos.set_sla_support_data(nullptr, m_selection);
+// }
+//}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void GLCanvas3D::_perform_layer_editing_action(wxMouseEvent* evt)
{
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index bc9932e75..f18c4a4f1 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -430,6 +430,9 @@ private:
bool m_regenerate_volumes;
bool m_moving;
bool m_tab_down;
+
+ // Following variable is obsolete and it should be safe to remove it.
+ // I just don't want to do it now before a release (Lukas Matena 24.3.2019)
bool m_render_sla_auxiliaries;
std::string m_color_by;
@@ -456,7 +459,7 @@ public:
void reset_volumes();
int check_volumes_outside_state() const;
- void toggle_sla_auxiliaries_visibility(bool visible);
+ void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1);
void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1);
void set_config(const DynamicPrintConfig* config);
@@ -562,6 +565,10 @@ public:
float get_view_toolbar_height() const { return m_view_toolbar.get_height(); }
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ void update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
private:
bool _is_shown_on_screen() const;
@@ -601,7 +608,9 @@ private:
void _render_selection_sidebar_hints() const;
void _update_volumes_hover_state() const;
- void _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+// void _update_gizmos_data();
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void _perform_layer_editing_action(wxMouseEvent* evt = nullptr);
diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp
index ac79784ad..de3236fc8 100644
--- a/src/slic3r/GUI/GLToolbar.cpp
+++ b/src/slic3r/GUI/GLToolbar.cpp
@@ -157,7 +157,6 @@ GLToolbar::GLToolbar(GLToolbar::EType type)
#if ENABLE_SVG_ICONS
, m_icons_texture_dirty(true)
#endif // ENABLE_SVG_ICONS
- , m_mouse_capture({ false, false, false, nullptr })
, m_tooltip("")
{
}
@@ -410,6 +409,16 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
bool processed = false;
// mouse anywhere
+ if (!evt.Dragging() && !evt.Leaving() && !evt.Entering() && (m_mouse_capture.parent != nullptr))
+ {
+ if (m_mouse_capture.any() && (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()))
+ // prevents loosing selection into the scene if mouse down was done inside the toolbar and mouse up was down outside it,
+ // as when switching between views
+ processed = true;
+
+ m_mouse_capture.reset();
+ }
+
if (evt.Moving())
m_tooltip = update_hover_state(mouse_pos, parent);
else if (evt.LeftUp())
@@ -418,17 +427,9 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
m_mouse_capture.middle = false;
else if (evt.RightUp())
m_mouse_capture.right = false;
- else if (m_mouse_capture.any())
- {
- if (evt.Dragging())
- processed = true;
- else if (evt.Entering() && (m_mouse_capture.parent == &parent))
- // Resets the mouse capture state to avoid setting the dragging event as processed when, for example,
- // the item action opens a modal dialog
- // Keeps the mouse capture state if the entering event happens on different parent from the one
- // who received the button down event, to prevent, for example, dragging when switching between scene views
- m_mouse_capture.reset();
- }
+ else if (evt.Dragging() && m_mouse_capture.any())
+ // if the button down was done on this toolbar, prevent from dragging into the scene
+ processed = true;
int item_id = contains_mouse(mouse_pos, parent);
if (item_id == -1)
@@ -443,11 +444,16 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
{
m_mouse_capture.left = true;
m_mouse_capture.parent = &parent;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ processed = true;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
if ((item_id != -2) && !m_items[item_id]->is_separator())
{
// mouse is inside an icon
do_action((unsigned int)item_id, parent);
- processed = true;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+// processed = true;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
}
}
else if (evt.MiddleDown())
diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp
index 5fe96df5f..0f8b17e04 100644
--- a/src/slic3r/GUI/GLToolbar.hpp
+++ b/src/slic3r/GUI/GLToolbar.hpp
@@ -239,6 +239,8 @@ private:
bool right;
GLCanvas3D* parent;
+ MouseCapture() { reset(); }
+
bool any() const { return left || middle || right; }
void reset() { left = middle = right = false; parent = nullptr; }
};
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
index f759250b3..6c8fdcab7 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
@@ -209,8 +209,8 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_position = volume->get_volume_offset();
m_new_rotation = volume->get_volume_rotation();
m_new_scale = volume->get_volume_scaling_factor();
- m_new_size = volume->get_instance_transformation().get_matrix(true, true) * volume->get_volume_transformation().get_matrix(true, true) * volume->bounding_box.size();
- m_new_enabled = true;
+ m_new_size = volume->get_volume_transformation().get_matrix(true, true) * volume->bounding_box.size();
+ m_new_enabled = true;
}
else if (wxGetApp().obj_list()->multiple_selection())
{
diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp
index 3781cbf45..dbfdb8e6c 100644
--- a/src/slic3r/GUI/GUI_ObjectSettings.cpp
+++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp
@@ -10,6 +10,8 @@
#include "I18N.hpp"
+#include <wx/wupdlock.h>
+
namespace Slic3r
{
namespace GUI
@@ -40,7 +42,7 @@ void OG_Settings::Hide()
void OG_Settings::UpdateAndShow(const bool show)
{
Show(show);
-// m_parent->Layout();
+// m_parent->Layout();
}
wxSizer* OG_Settings::get_sizer()
@@ -84,6 +86,7 @@ void ObjectSettings::update_settings_list()
btn->Bind(wxEVT_BUTTON, [opt_key, config, this](wxEvent &event) {
config->erase(opt_key);
wxTheApp->CallAfter([this]() {
+ wxWindowUpdateLocker noUpdates(m_parent);
update_settings_list();
m_parent->Layout();
});
@@ -119,7 +122,7 @@ void ObjectSettings::update_settings_list()
if (cat.second.size() == 1 && cat.second[0] == "extruder")
continue;
- auto optgroup = std::make_shared<ConfigOptionsGroup>(m_parent, cat.first, config, false, extra_column);
+ auto optgroup = std::make_shared<ConfigOptionsGroup>(m_og->ctrl_parent(), cat.first, config, false, extra_column);
optgroup->label_width = 15 * wxGetApp().em_unit();//150;
optgroup->sidetext_width = 7 * wxGetApp().em_unit();//70;
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index be3fad9ec..2361ff6d3 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -174,7 +174,9 @@ Preview::Preview(wxWindow* parent, Bed3D& bed, Camera& camera, GLToolbar& view_t
, m_loaded(false)
, m_enabled(false)
, m_schedule_background_process(schedule_background_process_func)
+#ifdef __linux__
, m_volumes_cleanup_required(false)
+#endif // __linux__
{
if (init(parent, bed, camera, view_toolbar))
{
@@ -354,31 +356,28 @@ void Preview::load_print(bool keep_z_range)
void Preview::reload_print(bool keep_volumes)
{
-#ifndef __linux__
- if (m_volumes_cleanup_required || !keep_volumes)
- {
- m_canvas->reset_volumes();
- m_canvas->reset_legend_texture();
- m_loaded = false;
- m_volumes_cleanup_required = false;
- }
-#endif // __linux__
-
+#ifdef __linux__
+ // We are getting mysterious crashes on Linux in gtk due to OpenGL context activation GH #1874 #1955.
+ // So we are applying a workaround here: a delayed release of OpenGL vertex buffers.
if (!IsShown())
{
m_volumes_cleanup_required = !keep_volumes;
return;
}
-
+#endif /* __linux __ */
+ if (
#ifdef __linux__
- if (m_volumes_cleanup_required || !keep_volumes)
+ m_volumes_cleanup_required ||
+#endif /* __linux__ */
+ !keep_volumes)
{
m_canvas->reset_volumes();
m_canvas->reset_legend_texture();
m_loaded = false;
+#ifdef __linux__
m_volumes_cleanup_required = false;
+#endif /* __linux__ */
}
-#endif // __linux__
load_print();
}
@@ -770,19 +769,17 @@ void Preview::load_print_as_sla()
unsigned int n_layers = 0;
const SLAPrint* print = m_process->sla_print();
- std::set<double> zs;
+ std::vector<double> zs;
+ double initial_layer_height = print->material_config().initial_layer_height.value;
for (const SLAPrintObject* obj : print->objects())
- {
- double shift_z = obj->get_current_elevation();
if (obj->is_step_done(slaposIndexSlices))
{
- const SLAPrintObject::SliceIndex& index = obj->get_slice_index();
- for (const SLAPrintObject::SliceIndex::value_type& id : index)
- {
- zs.insert(shift_z + id.first);
- }
+ auto slicerecords = obj->get_slice_records();
+ auto low_coord = slicerecords.begin()->key();
+ for (auto& rec : slicerecords)
+ zs.emplace_back(initial_layer_height + (rec.key() - low_coord) * SCALING_FACTOR);
}
- }
+ sort_remove_duplicates(zs);
n_layers = (unsigned int)zs.size();
if (n_layers == 0)
@@ -797,11 +794,7 @@ void Preview::load_print_as_sla()
show_hide_ui_elements("none");
if (n_layers > 0)
- {
- std::vector<double> layer_zs;
- std::copy(zs.begin(), zs.end(), std::back_inserter(layer_zs));
- update_sliders(layer_zs);
- }
+ update_sliders(zs);
m_loaded = true;
}
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index 182eaa952..96c49e54f 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -84,7 +84,11 @@ class Preview : public wxPanel
BackgroundSlicingProcess* m_process;
GCodePreviewData* m_gcode_preview_data;
+#ifdef __linux__
+ // We are getting mysterious crashes on Linux in gtk due to OpenGL context activation GH #1874 #1955.
+ // So we are applying a workaround here.
bool m_volumes_cleanup_required;
+#endif /* __linux__ */
// Calling this function object forces Plater::schedule_background_process.
std::function<void()> m_schedule_background_process;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index e62a116a7..0f6713e0d 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -329,6 +329,10 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
// left down without selection rectangle - place point on the mesh:
if (action == SLAGizmoEventType::LeftDown && !m_selection_rectangle_active && !shift_down) {
+ // If any point is in hover state, this should initiate its move - return control back to GLCanvas:
+ if (m_hover_id != -1)
+ return false;
+
// If there is some selection, don't add new point and deselect everything instead.
if (m_selection_empty) {
try {
@@ -663,7 +667,7 @@ RENDER_AGAIN:
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);
+ m_parent.toggle_sla_auxiliaries_visibility(!m_editing_mode, m_model_object, m_active_instance);
force_refresh = true;
}
m_old_editing_state = m_editing_mode;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
index 89668162e..9ac7af516 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
@@ -23,6 +23,9 @@ GLGizmosManager::GLGizmosManager()
, m_overlay_scale(1.0f)
, m_overlay_border(5.0f)
, m_overlay_gap_y(5.0f)
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ , m_tooltip("")
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
{
}
#else
@@ -186,51 +189,53 @@ void GLGizmosManager::set_overlay_scale(float scale)
#endif // ENABLE_SVG_ICONS
}
-std::string GLGizmosManager::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection)
-{
- std::string name = "";
-
- if (!m_enabled)
- return name;
-
- float cnv_h = (float)canvas.get_canvas_size().get_height();
- float height = get_total_overlay_height();
-#if ENABLE_SVG_ICONS
- float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
- float scaled_border = m_overlay_border * m_overlay_scale;
- float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
- float scaled_stride_y = scaled_icons_size + scaled_gap_y;
- float top_y = 0.5f * (cnv_h - height) + scaled_border;
-#else
- float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
- float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale;
-#endif // ENABLE_SVG_ICONS
-
- for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
- {
- if ((it->second == nullptr) || !it->second->is_selectable())
- continue;
-
-#if ENABLE_SVG_ICONS
- bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
-#else
- bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
-#endif // ENABLE_SVG_ICONS
- if (inside)
- name = it->second->get_name();
-
- if (it->second->is_activable(selection) && (it->second->get_state() != GLGizmoBase::On))
- it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off);
-
-#if ENABLE_SVG_ICONS
- top_y += scaled_stride_y;
-#else
- top_y += (scaled_icons_size + m_overlay_gap_y);
-#endif // ENABLE_SVG_ICONS
- }
-
- return name;
-}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+//std::string GLGizmosManager::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection)
+//{
+// std::string name = "";
+//
+// if (!m_enabled)
+// return name;
+//
+// float cnv_h = (float)canvas.get_canvas_size().get_height();
+// float height = get_total_overlay_height();
+//#if ENABLE_SVG_ICONS
+// float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
+// float scaled_border = m_overlay_border * m_overlay_scale;
+// float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
+// float scaled_stride_y = scaled_icons_size + scaled_gap_y;
+// float top_y = 0.5f * (cnv_h - height) + scaled_border;
+//#else
+// float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
+// float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale;
+//#endif // ENABLE_SVG_ICONS
+//
+// for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
+// {
+// if ((it->second == nullptr) || !it->second->is_selectable())
+// continue;
+//
+//#if ENABLE_SVG_ICONS
+// bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
+//#else
+// bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
+//#endif // ENABLE_SVG_ICONS
+// if (inside)
+// name = it->second->get_name();
+//
+// if (it->second->is_activable(selection) && (it->second->get_state() != GLGizmoBase::On))
+// it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off);
+//
+//#if ENABLE_SVG_ICONS
+// top_y += scaled_stride_y;
+//#else
+// top_y += (scaled_icons_size + m_overlay_gap_y);
+//#endif // ENABLE_SVG_ICONS
+// }
+//
+// return name;
+//}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void GLGizmosManager::update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection)
{
@@ -346,46 +351,48 @@ void GLGizmosManager::enable_grabber(EType type, unsigned int id, bool enable)
}
}
-bool GLGizmosManager::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const
-{
- if (!m_enabled)
- return false;
-
- float cnv_h = (float)canvas.get_canvas_size().get_height();
- float height = get_total_overlay_height();
-
-#if ENABLE_SVG_ICONS
- float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
- float scaled_border = m_overlay_border * m_overlay_scale;
- float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
- float scaled_stride_y = scaled_icons_size + scaled_gap_y;
- float top_y = 0.5f * (cnv_h - height) + scaled_border;
-#else
- float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
- float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale;
-#endif // ENABLE_SVG_ICONS
-
- for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
- {
- if ((it->second == nullptr) || !it->second->is_selectable())
- continue;
-
-#if ENABLE_SVG_ICONS
- if ((scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size))
-#else
- if ((m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size))
-#endif // ENABLE_SVG_ICONS
- return true;
-
-#if ENABLE_SVG_ICONS
- top_y += scaled_stride_y;
-#else
- top_y += (scaled_icons_size + m_overlay_gap_y);
-#endif // ENABLE_SVG_ICONS
- }
-
- return false;
-}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+//bool GLGizmosManager::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const
+//{
+// if (!m_enabled)
+// return false;
+//
+// float cnv_h = (float)canvas.get_canvas_size().get_height();
+// float height = get_total_overlay_height();
+//
+//#if ENABLE_SVG_ICONS
+// float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
+// float scaled_border = m_overlay_border * m_overlay_scale;
+// float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
+// float scaled_stride_y = scaled_icons_size + scaled_gap_y;
+// float top_y = 0.5f * (cnv_h - height) + scaled_border;
+//#else
+// float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
+// float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale;
+//#endif // ENABLE_SVG_ICONS
+//
+// for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
+// {
+// if ((it->second == nullptr) || !it->second->is_selectable())
+// continue;
+//
+//#if ENABLE_SVG_ICONS
+// if ((scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size))
+//#else
+// if ((m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size))
+//#endif // ENABLE_SVG_ICONS
+// return true;
+//
+//#if ENABLE_SVG_ICONS
+// top_y += scaled_stride_y;
+//#else
+// top_y += (scaled_icons_size + m_overlay_gap_y);
+//#endif // ENABLE_SVG_ICONS
+// }
+//
+// return false;
+//}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
bool GLGizmosManager::grabber_contains_mouse() const
{
@@ -614,6 +621,78 @@ void GLGizmosManager::render_overlay(const GLCanvas3D& canvas, const Selection&
glsafe(::glPopMatrix());
}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+bool GLGizmosManager::on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas)
+{
+ Vec2d mouse_pos((double)evt.GetX(), (double)evt.GetY());
+
+ std::cout << to_string(mouse_pos) << std::endl;
+
+
+ const Selection& selection = canvas.get_selection();
+ bool processed = false;
+
+ // mouse anywhere
+ if (!evt.Dragging() && !evt.Leaving() && !evt.Entering() && (m_mouse_capture.parent != nullptr))
+ {
+ if (m_mouse_capture.any() && (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()))
+ // prevents loosing selection into the scene if mouse down was done inside the toolbar and mouse up was down outside it
+ processed = true;
+
+ m_mouse_capture.reset();
+ }
+
+ // mouse anywhere
+ if (evt.Moving())
+ m_tooltip = update_hover_state(canvas, mouse_pos);
+ else if (evt.LeftUp())
+ m_mouse_capture.left = false;
+ else if (evt.MiddleUp())
+ m_mouse_capture.middle = false;
+ else if (evt.RightUp())
+ m_mouse_capture.right = false;
+ else if (evt.Dragging() && m_mouse_capture.any())
+ // if the button down was done on this toolbar, prevent from dragging into the scene
+ processed = true;
+
+ if (!overlay_contains_mouse(canvas, mouse_pos))
+ {
+ // mouse is outside the toolbar
+ m_tooltip = "";
+ }
+ else
+ {
+ // mouse inside toolbar
+ if (evt.LeftDown() || evt.LeftDClick())
+ {
+ m_mouse_capture.left = true;
+ m_mouse_capture.parent = &canvas;
+ processed = true;
+ if (!selection.is_empty())
+ {
+ update_on_off_state(canvas, mouse_pos, selection);
+ canvas.update_gizmos_data();
+ canvas.set_as_dirty();
+ }
+ }
+ else if (evt.MiddleDown())
+ {
+ m_mouse_capture.middle = true;
+ m_mouse_capture.parent = &canvas;
+ }
+ else if (evt.RightDown())
+ {
+ m_mouse_capture.right = true;
+ m_mouse_capture.parent = &canvas;
+ }
+ else if (evt.LeftUp())
+ processed = true;
+ }
+
+ return processed;
+}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
void GLGizmosManager::reset()
{
for (GizmosMap::value_type& gizmo : m_gizmos)
@@ -861,5 +940,96 @@ bool GLGizmosManager::generate_icons_texture() const
}
#endif // ENABLE_SVG_ICONS
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+std::string GLGizmosManager::update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos)
+{
+ std::string name = "";
+
+ if (!m_enabled)
+ return name;
+
+ const Selection& selection = canvas.get_selection();
+
+ float cnv_h = (float)canvas.get_canvas_size().get_height();
+ float height = get_total_overlay_height();
+#if ENABLE_SVG_ICONS
+ float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
+ float scaled_border = m_overlay_border * m_overlay_scale;
+ float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
+ float scaled_stride_y = scaled_icons_size + scaled_gap_y;
+ float top_y = 0.5f * (cnv_h - height) + scaled_border;
+#else
+ float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
+ float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale;
+#endif // ENABLE_SVG_ICONS
+
+ for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
+ {
+ if ((it->second == nullptr) || !it->second->is_selectable())
+ continue;
+
+#if ENABLE_SVG_ICONS
+ bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
+#else
+ bool inside = (m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
+#endif // ENABLE_SVG_ICONS
+ if (inside)
+ name = it->second->get_name();
+
+ if (it->second->is_activable(selection) && (it->second->get_state() != GLGizmoBase::On))
+ it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off);
+
+#if ENABLE_SVG_ICONS
+ top_y += scaled_stride_y;
+#else
+ top_y += (scaled_icons_size + m_overlay_gap_y);
+#endif // ENABLE_SVG_ICONS
+ }
+
+ return name;
+}
+
+bool GLGizmosManager::overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const
+{
+ if (!m_enabled)
+ return false;
+
+ float cnv_h = (float)canvas.get_canvas_size().get_height();
+ float height = get_total_overlay_height();
+
+#if ENABLE_SVG_ICONS
+ float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
+ float scaled_border = m_overlay_border * m_overlay_scale;
+ float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
+ float scaled_stride_y = scaled_icons_size + scaled_gap_y;
+ float top_y = 0.5f * (cnv_h - height) + scaled_border;
+#else
+ float top_y = 0.5f * (cnv_h - height) + m_overlay_border;
+ float scaled_icons_size = (float)m_icons_texture.metadata.icon_size * m_overlay_icons_scale;
+#endif // ENABLE_SVG_ICONS
+
+ for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
+ {
+ if ((it->second == nullptr) || !it->second->is_selectable())
+ continue;
+
+#if ENABLE_SVG_ICONS
+ if ((scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size))
+#else
+ if ((m_overlay_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= m_overlay_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size))
+#endif // ENABLE_SVG_ICONS
+ return true;
+
+#if ENABLE_SVG_ICONS
+ top_y += scaled_stride_y;
+#else
+ top_y += (scaled_icons_size + m_overlay_gap_y);
+#endif // ENABLE_SVG_ICONS
+ }
+
+ return false;
+}
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
} // namespace GUI
} // namespace Slic3r
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
index cb121352a..c280eda50 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
@@ -83,6 +83,24 @@ private:
float m_overlay_border;
float m_overlay_gap_y;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ struct MouseCapture
+ {
+ bool left;
+ bool middle;
+ bool right;
+ GLCanvas3D* parent;
+
+ MouseCapture() { reset(); }
+
+ bool any() const { return left || middle || right; }
+ void reset() { left = middle = right = false; parent = nullptr; }
+ };
+
+ MouseCapture m_mouse_capture;
+ std::string m_tooltip;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
public:
GLGizmosManager();
~GLGizmosManager();
@@ -97,7 +115,9 @@ public:
#endif // ENABLE_SVG_ICONS
void set_overlay_scale(float scale);
- std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+// std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
void update_on_off_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos, const Selection& selection);
void update_on_off_state(const Selection& selection);
void reset_all_states();
@@ -105,7 +125,9 @@ public:
void set_hover_id(int id);
void enable_grabber(EType type, unsigned int id, bool enable);
- bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+// bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
bool grabber_contains_mouse() const;
void update(const Linef3& mouse_ray, const Selection& selection, bool shift_down, const Point* mouse_pos = nullptr);
Rect get_reset_rect_viewport(const GLCanvas3D& canvas) const;
@@ -138,6 +160,12 @@ public:
void render_overlay(const GLCanvas3D& canvas, const Selection& selection) const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ const std::string& get_tooltip() const { return m_tooltip; }
+
+ bool on_mouse(wxMouseEvent& evt, GLCanvas3D& canvas);
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
private:
void reset();
@@ -151,6 +179,11 @@ private:
#if ENABLE_SVG_ICONS
bool generate_icons_texture() const;
#endif // ENABLE_SVG_ICONS
+
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ std::string update_hover_state(const GLCanvas3D& canvas, const Vec2d& mouse_pos);
+ bool overlay_contains_mouse(const GLCanvas3D& canvas, const Vec2d& mouse_pos) const;
+//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
};
} // namespace GUI
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index 2acc2cec4..e15882125 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -57,6 +57,7 @@
#include "BackgroundSlicingProcess.hpp"
#include "ProgressStatusBar.hpp"
#include "PrintHostDialogs.hpp"
+#include "ConfigWizard.hpp"
#include "../Utils/ASCIIFolding.hpp"
#include "../Utils/PrintHost.hpp"
#include "../Utils/FixModelByWin10.hpp"
@@ -233,9 +234,11 @@ wxBitmapComboBox(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(15 *
auto selected_item = this->GetSelection();
auto marker = reinterpret_cast<Marker>(this->GetClientData(selected_item));
- if (marker == LABEL_ITEM_MARKER) {
+ if (marker == LABEL_ITEM_MARKER || marker == LABEL_ITEM_CONFIG_WIZARD) {
this->SetSelection(this->last_selected);
evt.StopPropagation();
+ if (marker == LABEL_ITEM_CONFIG_WIZARD)
+ wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); });
} else if ( this->last_selected != selected_item ||
wxGetApp().get_tab(this->preset_type)->get_presets()->current_is_dirty() ) {
this->last_selected = selected_item;
@@ -317,15 +320,14 @@ PresetComboBox::~PresetComboBox()
}
-void PresetComboBox::set_label_marker(int item)
+void PresetComboBox::set_label_marker(int item, LabelItemType label_item_type)
{
- this->SetClientData(item, (void*)LABEL_ITEM_MARKER);
+ this->SetClientData(item, (void*)label_item_type);
}
void PresetComboBox::check_selection()
{
- if (this->last_selected != GetSelection())
- this->last_selected = GetSelection();
+ this->last_selected = GetSelection();
}
// Frequently changed parameters
@@ -826,10 +828,7 @@ void Sidebar::update_presets(Preset::Type preset_type)
preset_bundle.sla_materials.update_platter_ui(p->combo_sla_material);
}
// Update the printer choosers, update the dirty flags.
- auto prev_selection = p->combo_printer->GetSelection();
preset_bundle.printers.update_platter_ui(p->combo_printer);
- if (prev_selection != p->combo_printer->GetSelection())
- p->combo_printer->check_selection();
// Update the filament choosers to only contain the compatible presets, update the color preview,
// update the dirty flags.
if (print_tech == ptFFF) {
@@ -1617,7 +1616,11 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
if (type_3mf || type_any_amf) {
#endif // !ENABLE_VOLUMES_CENTERING_FIXES
for (ModelObject* model_object : model.objects) {
+#if ENABLE_VOLUMES_CENTERING_FIXES
+ model_object->center_around_origin(false);
+#else
model_object->center_around_origin();
+#endif // ENABLE_VOLUMES_CENTERING_FIXES
model_object->ensure_on_bed();
}
#if !ENABLE_VOLUMES_CENTERING_FIXES
@@ -1710,8 +1713,8 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode
object->center_around_origin();
new_instances.emplace_back(object->add_instance());
#else /* AUTOPLACEMENT_ON_LOAD */
- // if object has no defined position(s) we need to rearrange everything after loading object->center_around_origin();
- need_arrange = true;
+ // if object has no defined position(s) we need to rearrange everything after loading
+ need_arrange = true;
// add a default instance and center object around origin
object->center_around_origin(); // also aligns object to Z = 0
ModelInstance* instance = object->add_instance();
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index f3e195ad0..f830edce3 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -48,14 +48,18 @@ public:
wxButton* edit_btn { nullptr };
- void set_label_marker(int item);
+ enum LabelItemType {
+ LABEL_ITEM_MARKER = 0x4d,
+ LABEL_ITEM_CONFIG_WIZARD = 0x4e
+ };
+
+ void set_label_marker(int item, LabelItemType label_item_type = LABEL_ITEM_MARKER);
void set_extruder_idx(const int extr_idx) { extruder_idx = extr_idx; }
int get_extruder_idx() const { return extruder_idx; }
void check_selection();
private:
typedef std::size_t Marker;
- enum { LABEL_ITEM_MARKER = 0x4d };
Preset::Type preset_type;
int last_selected;
diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp
index 656658b0b..82223b15c 100644
--- a/src/slic3r/GUI/Preset.cpp
+++ b/src/slic3r/GUI/Preset.cpp
@@ -519,6 +519,7 @@ PresetCollection::PresetCollection(Preset::Type type, const std::vector<std::str
m_edited_preset(type, "", false),
m_idx_selected(0),
m_bitmap_main_frame(new wxBitmap),
+ m_bitmap_add(new wxBitmap),
m_bitmap_cache(new GUI::BitmapCache)
{
// Insert just the default preset.
@@ -530,6 +531,8 @@ PresetCollection::~PresetCollection()
{
delete m_bitmap_main_frame;
m_bitmap_main_frame = nullptr;
+ delete m_bitmap_add;
+ m_bitmap_add = nullptr;
delete m_bitmap_cache;
m_bitmap_cache = nullptr;
}
@@ -740,6 +743,8 @@ void PresetCollection::save_current_preset(const std::string &new_name)
return;
// Overwriting an existing preset.
preset.config = std::move(m_edited_preset.config);
+ // The newly saved preset will be activated -> make it visible.
+ preset.is_visible = true;
} else {
// Creating a new preset.
Preset &preset = *m_presets.insert(it, m_edited_preset);
@@ -761,18 +766,20 @@ void PresetCollection::save_current_preset(const std::string &new_name)
preset.is_default = false;
preset.is_system = false;
preset.is_external = false;
- }
+ // The newly saved preset will be activated -> make it visible.
+ preset.is_visible = true;
+ }
// 2) Activate the saved preset.
this->select_preset_by_name(new_name, true);
// 2) Store the active preset to disk.
this->get_selected_preset().save();
}
-void PresetCollection::delete_current_preset()
+bool PresetCollection::delete_current_preset()
{
const Preset &selected = this->get_selected_preset();
- if (selected.is_default)
- return;
+ if (selected.is_default)
+ return false;
if (! selected.is_external && ! selected.is_system) {
// Erase the preset file.
boost::nowide::remove(selected.file.c_str());
@@ -786,6 +793,7 @@ void PresetCollection::delete_current_preset()
if (new_selected_idx == m_presets.size())
for (--new_selected_idx; new_selected_idx > 0 && !m_presets[new_selected_idx].is_visible; --new_selected_idx);
this->select_preset(new_selected_idx);
+ return true;
}
bool PresetCollection::load_bitmap_default(const std::string &file_name)
@@ -793,6 +801,11 @@ bool PresetCollection::load_bitmap_default(const std::string &file_name)
return m_bitmap_main_frame->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
}
+bool PresetCollection::load_bitmap_add(const std::string &file_name)
+{
+ return m_bitmap_add->LoadFile(wxString::FromUTF8(Slic3r::var(file_name).c_str()), wxBITMAP_TYPE_PNG);
+}
+
const Preset* PresetCollection::get_selected_preset_parent() const
{
const std::string &inherits = this->get_edited_preset().inherits();
@@ -843,7 +856,9 @@ void PresetCollection::set_default_suppressed(bool default_suppressed)
{
if (m_default_suppressed != default_suppressed) {
m_default_suppressed = default_suppressed;
- m_presets.front().is_visible = ! default_suppressed || (m_presets.size() > m_num_default_presets && m_idx_selected > 0);
+ bool default_visible = ! default_suppressed || m_idx_selected < m_num_default_presets;
+ for (size_t i = 0; i < m_num_default_presets; ++ i)
+ m_presets[i].is_visible = default_visible;
}
}
@@ -895,8 +910,8 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui)
std::map<wxString, wxBitmap*> nonsys_presets;
wxString selected = "";
if (!this->m_presets.front().is_visible)
- ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap));
- for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) {
+ ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap));
+ for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++ i) {
const Preset &preset = this->m_presets[i];
if (! preset.is_visible || (! preset.is_compatible && i != m_idx_selected))
continue;
@@ -935,20 +950,45 @@ void PresetCollection::update_platter_ui(GUI::PresetComboBox *ui)
selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str());
}
if (i + 1 == m_num_default_presets)
- ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap));
+ ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap));
}
if (!nonsys_presets.empty())
{
- ui->set_label_marker(ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap));
+ ui->set_label_marker(ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap));
for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
ui->Append(it->first, *it->second);
if (it->first == selected)
selected_preset_item = ui->GetCount() - 1;
}
}
+ if (m_type == Preset::TYPE_PRINTER) {
+ std::string bitmap_key = "";
+ // If the filament preset is not compatible and there is a "red flag" icon loaded, show it left
+ // to the filament color image.
+ if (wide_icons)
+ bitmap_key += "wide,";
+ bitmap_key += "add_printer";
+ wxBitmap *bmp = m_bitmap_cache->find(bitmap_key);
+ if (bmp == nullptr) {
+ // Create the bitmap with color bars.
+ std::vector<wxBitmap> bmps;
+ if (wide_icons)
+ // Paint a red flag for incompatible presets.
+ bmps.emplace_back(m_bitmap_cache->mkclear(16, 16));
+ // Paint the color bars.
+ bmps.emplace_back(m_bitmap_cache->mkclear(4, 16));
+ bmps.emplace_back(*m_bitmap_main_frame);
+ // Paint a lock at the system presets.
+ bmps.emplace_back(m_bitmap_cache->mkclear(6, 16));
+ bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap);
+ bmp = m_bitmap_cache->insert(bitmap_key, bmps);
+ }
+ ui->set_label_marker(ui->Append(PresetCollection::separator(L("Add a new printer")), *bmp), GUI::PresetComboBox::LABEL_ITEM_CONFIG_WIZARD);
+ }
ui->SetSelection(selected_preset_item);
ui->SetToolTip(ui->GetString(selected_preset_item));
+ ui->check_selection();
ui->Thaw();
}
@@ -963,7 +1003,7 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati
std::map<wxString, wxBitmap*> nonsys_presets;
wxString selected = "";
if (!this->m_presets.front().is_visible)
- ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap);
+ ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap);
for (size_t i = this->m_presets.front().is_visible ? 0 : m_num_default_presets; i < this->m_presets.size(); ++i) {
const Preset &preset = this->m_presets[i];
if (! preset.is_visible || (! show_incompatible && ! preset.is_compatible && i != m_idx_selected))
@@ -994,18 +1034,29 @@ size_t PresetCollection::update_tab_ui(wxBitmapComboBox *ui, bool show_incompati
if (i == m_idx_selected)
selected = wxString::FromUTF8((preset.name + (preset.is_dirty ? g_suffix_modified : "")).c_str());
}
- if (i + 1 == m_num_default_presets)
- ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap);
+ if (i + 1 == m_num_default_presets)
+ ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap);
}
if (!nonsys_presets.empty())
{
- ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap);
+ ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap);
for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
ui->Append(it->first, *it->second);
if (it->first == selected)
selected_preset_item = ui->GetCount() - 1;
}
}
+ if (m_type == Preset::TYPE_PRINTER) {
+ wxBitmap *bmp = m_bitmap_cache->find("add_printer_tab");
+ if (bmp == nullptr) {
+ // Create the bitmap with color bars.
+ std::vector<wxBitmap> bmps;
+ bmps.emplace_back(*m_bitmap_main_frame);
+ bmps.emplace_back(m_bitmap_add ? *m_bitmap_add : wxNullBitmap);
+ bmp = m_bitmap_cache->insert("add_printer_tab", bmps);
+ }
+ ui->Append(PresetCollection::separator("Add a new printer"), *bmp);
+ }
ui->SetSelection(selected_preset_item);
ui->SetToolTip(ui->GetString(selected_preset_item));
ui->Thaw();
@@ -1114,7 +1165,9 @@ Preset& PresetCollection::select_preset(size_t idx)
idx = first_visible_idx();
m_idx_selected = idx;
m_edited_preset = m_presets[idx];
- m_presets.front().is_visible = ! m_default_suppressed || m_idx_selected == 0;
+ bool default_visible = ! m_default_suppressed || m_idx_selected < m_num_default_presets;
+ for (size_t i = 0; i < m_num_default_presets; ++i)
+ m_presets[i].is_visible = default_visible;
return m_presets[idx];
}
@@ -1232,6 +1285,11 @@ std::string PresetCollection::path_from_name(const std::string &new_name) const
return (boost::filesystem::path(m_dir_path) / file_name).make_preferred().string();
}
+wxString PresetCollection::separator(const std::string &label)
+{
+ return wxString::FromUTF8(PresetCollection::separator_head()) + _(label) + wxString::FromUTF8(PresetCollection::separator_tail());
+}
+
const Preset& PrinterPresetCollection::default_preset_for(const DynamicPrintConfig &config) const
{
const ConfigOptionEnumGeneric *opt_printer_technology = config.opt<ConfigOptionEnumGeneric>("printer_technology");
diff --git a/src/slic3r/GUI/Preset.hpp b/src/slic3r/GUI/Preset.hpp
index 511313715..ac1171e18 100644
--- a/src/slic3r/GUI/Preset.hpp
+++ b/src/slic3r/GUI/Preset.hpp
@@ -11,9 +11,10 @@
#include "slic3r/Utils/Semver.hpp"
class wxBitmap;
-class wxChoice;
class wxBitmapComboBox;
+class wxChoice;
class wxItemContainer;
+class wxString;
namespace Slic3r {
@@ -115,6 +116,8 @@ public:
// Is this preset compatible with the currently active printer?
bool is_compatible = true;
+ bool is_user() const { return ! this->is_default && ! this->is_system; }
+
// Name of the preset, usually derived form the file name.
std::string name;
// File name of the preset. This could be a Print / Filament / Printer preset,
@@ -269,11 +272,15 @@ public:
void save_current_preset(const std::string &new_name);
// Delete the current preset, activate the first visible preset.
- void delete_current_preset();
+ // returns true if the preset was deleted successfully.
+ bool delete_current_preset();
// Load default bitmap to be placed at the wxBitmapComboBox of a MainFrame.
bool load_bitmap_default(const std::string &file_name);
+ // Load "add new printer" bitmap to be placed at the wxBitmapComboBox of a MainFrame.
+ bool load_bitmap_add(const std::string &file_name);
+
// Compatible & incompatible marks, to be placed at the wxBitmapComboBox items.
void set_bitmap_compatible (const wxBitmap *bmp) { m_bitmap_compatible = bmp; }
void set_bitmap_incompatible(const wxBitmap *bmp) { m_bitmap_incompatible = bmp; }
@@ -404,6 +411,15 @@ public:
// Generate a file path from a profile name. Add the ".ini" suffix if it is missing.
std::string path_from_name(const std::string &new_name) const;
+#ifdef __linux__
+ static const char* separator_head() { return "------- "; }
+ static const char* separator_tail() { return " -------"; }
+#else /* __linux__ */
+ static const char* separator_head() { return "————— "; }
+ static const char* separator_tail() { return " —————"; }
+#endif /* __linux__ */
+ static wxString separator(const std::string &label);
+
protected:
// Select a preset, if it exists. If it does not exist, select an invalid (-1) index.
// This is a temporary state, which shall be fixed immediately by the following step.
@@ -464,6 +480,8 @@ private:
// Marks placed at the wxBitmapComboBox of a MainFrame.
// These bitmaps are owned by PresetCollection.
wxBitmap *m_bitmap_main_frame;
+ // "Add printer profile" icon, owned by PresetCollection.
+ wxBitmap *m_bitmap_add;
// Path to the directory to store the config files into.
std::string m_dir_path;
diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp
index b8c9fedac..f78a04126 100644
--- a/src/slic3r/GUI/PresetBundle.cpp
+++ b/src/slic3r/GUI/PresetBundle.cpp
@@ -107,6 +107,7 @@ PresetBundle::PresetBundle() :
this->filaments .load_bitmap_default("spool.png");
this->sla_materials.load_bitmap_default("package_green.png");
this->printers .load_bitmap_default("printer_empty.png");
+ this->printers .load_bitmap_add("add.png");
this->load_compatible_bitmaps();
// Re-activate the default presets, so their "edited" preset copies will be updated with the additional configuration values above.
@@ -1405,7 +1406,7 @@ void PresetBundle::export_configbundle(const std::string &path, bool export_syst
// an optional "(modified)" suffix will be removed from the filament name.
void PresetBundle::set_filament_preset(size_t idx, const std::string &name)
{
- if (name.find_first_of("-------") == 0)
+ if (name.find_first_of(PresetCollection::separator_head()) == 0)
return;
if (idx >= filament_presets.size())
@@ -1461,7 +1462,7 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr
std::map<wxString, wxBitmap*> nonsys_presets;
wxString selected_str = "";
if (!this->filaments().front().is_visible)
- ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap));
+ ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap));
for (int i = this->filaments().front().is_visible ? 0 : 1; i < int(this->filaments().size()); ++i) {
const Preset &preset = this->filaments.preset(i);
bool selected = this->filament_presets[idx_extruder] == preset.name;
@@ -1514,12 +1515,12 @@ void PresetBundle::update_platter_filament_ui(unsigned int idx_extruder, GUI::Pr
selected_str = wxString::FromUTF8((preset.name + (preset.is_dirty ? Preset::suffix_modified() : "")).c_str());
}
if (preset.is_default)
- ui->set_label_marker(ui->Append("------- " + _(L("System presets")) + " -------", wxNullBitmap));
+ ui->set_label_marker(ui->Append(PresetCollection::separator(L("System presets")), wxNullBitmap));
}
if (!nonsys_presets.empty())
{
- ui->set_label_marker(ui->Append("------- " + _(L("User presets")) + " -------", wxNullBitmap));
+ ui->set_label_marker(ui->Append(PresetCollection::separator(L("User presets")), wxNullBitmap));
for (std::map<wxString, wxBitmap*>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
ui->Append(it->first, *it->second);
if (it->first == selected_str)
@@ -1528,6 +1529,7 @@ 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->check_selection();
ui->Thaw();
}
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 46a6de6ab..48d9ece47 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -29,6 +29,7 @@
#include "GUI_App.hpp"
#include "GUI_ObjectList.hpp"
+#include "ConfigWizard.hpp"
namespace Slic3r {
namespace GUI {
@@ -248,10 +249,12 @@ void Tab::create_preset_tab()
return;
if (selected_item >= 0) {
std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data();
- if (selected_string.find("-------") == 0
+ if (selected_string.find(PresetCollection::separator_head()) == 0
/*selected_string == "------- System presets -------" ||
selected_string == "------- User presets -------"*/) {
m_presets_choice->SetSelection(m_selected_preset_item);
+ if (wxString::FromUTF8(selected_string.c_str()) == PresetCollection::separator(L("Add a new printer")))
+ wxTheApp->CallAfter([]() { Slic3r::GUI::config_wizard(Slic3r::GUI::ConfigWizard::RR_USER); });
return;
}
m_selected_preset_item = selected_item;
@@ -385,7 +388,7 @@ void Tab::update_changed_ui()
if (m_postpone_update_ui)
return;
- const bool deep_compare = (m_name == "printer" || m_name == "sla_material");
+ const bool deep_compare = (m_type == Slic3r::Preset::TYPE_PRINTER || m_type == Slic3r::Preset::TYPE_SLA_MATERIAL);
auto dirty_options = m_presets->current_dirty_options(deep_compare);
auto nonsys_options = m_presets->current_different_from_parent_options(deep_compare);
if (m_type == Slic3r::Preset::TYPE_PRINTER) {
@@ -2395,7 +2398,7 @@ void Tab::load_current_preset()
(preset.is_default || preset.is_system) ? m_btn_delete_preset->Disable() : m_btn_delete_preset->Enable(true);
update();
- if (m_name == "printer") {
+ if (m_type == Slic3r::Preset::TYPE_PRINTER) {
// For the printer profile, generate the extruder pages.
if (preset.printer_technology() == ptFFF)
on_preset_loaded();
@@ -2425,7 +2428,7 @@ void Tab::load_current_preset()
update_tab_ui();
// update show/hide tabs
- if (m_name == "printer") {
+ if (m_type == Slic3r::Preset::TYPE_PRINTER) {
const PrinterTechnology printer_technology = m_presets->get_edited_preset().printer_technology();
if (printer_technology != static_cast<TabPrinter*>(this)->m_printer_technology)
{
@@ -2458,7 +2461,7 @@ void Tab::load_current_preset()
}
else {
on_presets_changed();
- if (m_type == Preset::TYPE_SLA_PRINT || m_type == Preset::TYPE_PRINT)// if (m_name == "print")
+ if (m_type == Preset::TYPE_SLA_PRINT || m_type == Preset::TYPE_PRINT)
update_frequently_changed_parameters();
}
@@ -2526,20 +2529,35 @@ void Tab::update_page_tree_visibility()
}
-// Called by the UI combo box when the user switches profiles.
+// Called by the UI combo box when the user switches profiles, and also to delete the current profile.
// Select a preset by a name.If !defined(name), then the default preset is selected.
// If the current profile is modified, user is asked to save the changes.
-void Tab::select_preset(std::string preset_name)
-{
- // If no name is provided, select the "-- default --" preset.
- if (preset_name.empty())
- preset_name = m_presets->default_preset().name;
- bool current_dirty = m_presets->current_is_dirty();
+void Tab::select_preset(std::string preset_name, bool delete_current)
+{
+ if (preset_name.empty()) {
+ if (delete_current) {
+ // Find an alternate preset to be selected after the current preset is deleted.
+ const std::deque<Preset> &presets = this->m_presets->get_presets();
+ size_t idx_current = this->m_presets->get_idx_selected();
+ // Find the next visible preset.
+ size_t idx_new = idx_current + 1;
+ if (idx_new < presets.size())
+ for (; idx_new < presets.size() && ! presets[idx_new].is_visible; ++ idx_new) ;
+ if (idx_new == presets.size())
+ for (idx_new = idx_current - 1; idx_new > 0 && ! presets[idx_new].is_visible; -- idx_new);
+ preset_name = presets[idx_new].name;
+ } else {
+ // If no name is provided, select the "-- default --" preset.
+ preset_name = m_presets->default_preset().name;
+ }
+ }
+ assert(! delete_current || (m_presets->get_edited_preset().name != preset_name && m_presets->get_edited_preset().is_user()));
+ bool current_dirty = ! delete_current && m_presets->current_is_dirty();
bool print_tab = m_presets->type() == Preset::TYPE_PRINT || m_presets->type() == Preset::TYPE_SLA_PRINT;
bool printer_tab = m_presets->type() == Preset::TYPE_PRINTER;
bool canceled = false;
m_dependent_tabs = {};
- if (current_dirty && !may_discard_current_dirty_preset()) {
+ if (current_dirty && ! may_discard_current_dirty_preset()) {
canceled = true;
} else if (print_tab) {
// Before switching the print profile to a new one, verify, whether the currently active filament or SLA material
@@ -2602,6 +2620,19 @@ void Tab::select_preset(std::string preset_name)
}
}
}
+
+ if (! canceled && delete_current) {
+ // Delete the file and select some other reasonable preset.
+ // It does not matter which preset will be made active as the preset will be re-selected from the preset_name variable.
+ // The 'external' presets will only be removed from the preset list, their files will not be deleted.
+ try {
+ m_presets->delete_current_preset();
+ } catch (const std::exception & /* e */) {
+ //FIXME add some error reporting!
+ canceled = true;
+ }
+ }
+
if (canceled) {
update_tab_ui();
// Trigger the on_presets_changed event so that we also restore the previous value in the plater selector,
@@ -2610,17 +2641,19 @@ void Tab::select_preset(std::string preset_name)
} else {
if (current_dirty)
m_presets->discard_current_changes();
- const bool is_selected = m_presets->select_preset_by_name(preset_name, false);
+
+ const bool is_selected = m_presets->select_preset_by_name(preset_name, false) || delete_current;
+ assert(m_presets->get_edited_preset().name == preset_name || ! is_selected);
// 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.
- if (current_dirty || print_tab || printer_tab)
+ if (current_dirty || delete_current || print_tab || printer_tab)
m_preset_bundle->update_compatible(true);
// Initialize the UI from the current preset.
if (printer_tab)
static_cast<TabPrinter*>(this)->update_pages();
- if (!is_selected && printer_tab)
+ if (! is_selected && printer_tab)
{
/* There is a case, when :
* after Config Wizard applying we try to select previously selected preset, but
@@ -2631,15 +2664,10 @@ void Tab::select_preset(std::string preset_name)
* 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 };
- }
+ if (printer_technology == ptFFF && m_dependent_tabs.front() != Preset::Type::TYPE_PRINT)
+ m_dependent_tabs = { Preset::Type::TYPE_PRINT, Preset::Type::TYPE_FILAMENT };
+ else if (printer_technology == ptSLA && m_dependent_tabs.front() != Preset::Type::TYPE_SLA_PRINT)
+ m_dependent_tabs = { Preset::Type::TYPE_SLA_PRINT, Preset::Type::TYPE_SLA_MATERIAL };
}
load_current_preset();
}
@@ -2771,11 +2799,14 @@ void Tab::save_preset(std::string name /*= ""*/)
//! m_treectrl->OnSetFocus();
if (name.empty()) {
- auto preset = m_presets->get_selected_preset();
+ const Preset &preset = m_presets->get_selected_preset();
auto default_name = preset.is_default ? "Untitled" : preset.name;
+ if (preset.is_system) {
+ default_name += " - ";
+ default_name += _(L("Copy")).ToUTF8().data();
+ }
bool have_extention = boost::iends_with(default_name, ".ini");
- if (have_extention)
- {
+ if (have_extention) {
size_t len = default_name.length()-4;
default_name.resize(len);
}
@@ -2819,7 +2850,7 @@ void Tab::save_preset(std::string name /*= ""*/)
// If current profile is saved, "delete preset" button have to be enabled
m_btn_delete_preset->Enable(true);
- if (m_name == "printer")
+ if (m_type == Preset::TYPE_PRINTER)
static_cast<TabPrinter*>(this)->m_initial_extruders_count = static_cast<TabPrinter*>(this)->m_extruders_count;
update_changed_ui();
}
@@ -2836,15 +2867,9 @@ void Tab::delete_preset()
if (current_preset.is_default ||
wxID_YES != wxMessageDialog(parent(), msg, title, wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION).ShowModal())
return;
- // Delete the file and select some other reasonable preset.
- // The 'external' presets will only be removed from the preset list, their files will not be deleted.
- try{ m_presets->delete_current_preset(); }
- catch (const std::exception & /* e */)
- {
- return;
- }
- // Load the newly selected preset into the UI, update selection combo boxes with their dirty flags.
- load_current_preset();
+ // Select will handle of the preset dependencies, of saving & closing the depending profiles, and
+ // finally of deleting the preset.
+ this->select_preset("", true);
}
void Tab::toggle_show_hide_incompatible()
diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp
index 15ae0443c..58950990c 100644
--- a/src/slic3r/GUI/Tab.hpp
+++ b/src/slic3r/GUI/Tab.hpp
@@ -239,7 +239,8 @@ public:
void load_current_preset();
void rebuild_page_tree();
void update_page_tree_visibility();
- void select_preset(std::string preset_name = "");
+ // Select a new preset, possibly delete the current one.
+ void select_preset(std::string preset_name = "", bool delete_current = false);
bool may_discard_current_dirty_preset(PresetCollection* presets = nullptr, const std::string& new_printer_name = "");
bool may_switch_to_SLA_preset();