This commit is contained in:
bubnikv 2019-03-21 10:07:42 +01:00
commit a5b27a7540
12 changed files with 142 additions and 91 deletions

View file

@ -58,11 +58,20 @@ Note that Slic3r PE is tested with wxWidgets 3.0 somewhat sporadically and so th
### Build variant ### Build variant
By default Scli3r builds the release variant. By default Slic3r builds the release variant.
To create a debug build, use the following CMake flag: To create a debug build, use the following CMake flag:
-DCMAKE_BUILD_TYPE=Debug -DCMAKE_BUILD_TYPE=Debug
### Enabling address sanitizer
If you're using GCC/Clang compiler, it is possible to build Slic3r with the built-in address sanitizer enabled to help detect memory-corruption issues.
To enable it, simply use the following CMake flag:
-DSLIC3R_ASAN=1
This requires GCC>4.8 or Clang>3.1.
### Installation ### Installation
At runtime, Slic3r needs a way to access its resource files. By default, it looks for a `resources` directory relative to its binary. At runtime, Slic3r needs a way to access its resource files. By default, it looks for a `resources` directory relative to its binary.

View file

@ -249,6 +249,7 @@ GLVolume::GLVolume(float r, float g, float b, float a)
, is_wipe_tower(false) , is_wipe_tower(false)
, is_extrusion_path(false) , is_extrusion_path(false)
, force_transparent(false) , force_transparent(false)
, force_native_color(false)
, tverts_range(0, size_t(-1)) , tverts_range(0, size_t(-1))
, qverts_range(0, size_t(-1)) , qverts_range(0, size_t(-1))
{ {
@ -280,16 +281,20 @@ void GLVolume::set_render_color(const float* rgba, unsigned int size)
void GLVolume::set_render_color() void GLVolume::set_render_color()
{ {
if (selected) if (force_native_color)
set_render_color(is_outside ? SELECTED_OUTSIDE_COLOR : SELECTED_COLOR, 4);
else if (hover)
set_render_color(HOVER_COLOR, 4);
else if (disabled)
set_render_color(DISABLED_COLOR, 4);
else if (is_outside && shader_outside_printer_detection_enabled)
set_render_color(OUTSIDE_COLOR, 4);
else
set_render_color(color, 4); set_render_color(color, 4);
else {
if (selected)
set_render_color(is_outside ? SELECTED_OUTSIDE_COLOR : SELECTED_COLOR, 4);
else if (hover)
set_render_color(HOVER_COLOR, 4);
else if (disabled)
set_render_color(DISABLED_COLOR, 4);
else if (is_outside && shader_outside_printer_detection_enabled)
set_render_color(OUTSIDE_COLOR, 4);
else
set_render_color(color, 4);
}
if (force_transparent) if (force_transparent)
render_color[3] = color[3]; render_color[3] = color[3];

View file

@ -302,6 +302,8 @@ public:
bool is_extrusion_path; bool is_extrusion_path;
// Wheter or not to always render this volume using its own alpha // Wheter or not to always render this volume using its own alpha
bool force_transparent; bool force_transparent;
// Whether or not always use the volume's own color (not using SELECTED/HOVER/DISABLED/OUTSIDE)
bool force_native_color;
// Interleaved triangles & normals with indexed triangles & quads. // Interleaved triangles & normals with indexed triangles & quads.
GLIndexedVertexArray indexed_vertex_array; GLIndexedVertexArray indexed_vertex_array;

View file

@ -1304,14 +1304,14 @@ void GLCanvas3D::Gizmos::set_sla_support_data(ModelObject* model_object, const S
// Returns true if the gizmo used the event to do something, false otherwise. // Returns true if the gizmo used the event to do something, false otherwise.
bool GLCanvas3D::Gizmos::mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down) bool GLCanvas3D::Gizmos::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down)
{ {
if (!m_enabled) if (!m_enabled)
return false; return false;
GizmosMap::const_iterator it = m_gizmos.find(SlaSupports); GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
if (it != m_gizmos.end()) if (it != m_gizmos.end())
return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->mouse_event(action, mouse_position, shift_down); return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->gizmo_event(action, mouse_position, shift_down);
return false; return false;
} }
@ -2231,8 +2231,10 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject
{ {
for (GLVolume* vol : m_volumes.volumes) { for (GLVolume* vol : m_volumes.volumes) {
if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo) if ((mo == nullptr || m_model->objects[vol->composite_id.object_id] == mo)
&& (instance_idx == -1 || vol->composite_id.instance_id == instance_idx)) && (instance_idx == -1 || vol->composite_id.instance_id == instance_idx)) {
vol->is_active = visible; vol->is_active = visible;
vol->force_native_color = (instance_idx != -1);
}
} }
if (visible && !mo) if (visible && !mo)
toggle_sla_auxiliaries_visibility(true); toggle_sla_auxiliaries_visibility(true);
@ -3100,7 +3102,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
case 'a': case 'a':
case 'A': case 'A':
case WXK_CONTROL_A: case WXK_CONTROL_A:
if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::SelectAll)) // Sla gizmo selects all support points if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::SelectAll)) // Sla gizmo selects all support points
m_dirty = true; m_dirty = true;
else else
post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL)); post_event(SimpleEvent(EVT_GLCANVAS_SELECT_ALL));
@ -3120,14 +3122,14 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
{ {
// key ESC // key ESC
case WXK_ESCAPE: { case WXK_ESCAPE: {
if (m_gizmos.get_current_type() != Gizmos::SlaSupports || !m_gizmos.mouse_event(SLAGizmoEventType::DiscardChanges)) if (m_gizmos.get_current_type() != Gizmos::SlaSupports || !m_gizmos.gizmo_event(SLAGizmoEventType::DiscardChanges))
m_gizmos.reset_all_states(); m_gizmos.reset_all_states();
m_dirty = true; m_dirty = true;
break; break;
} }
case WXK_RETURN: { case WXK_RETURN: {
if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::ApplyChanges)) if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::ApplyChanges))
m_dirty = true; m_dirty = true;
break; break;
} }
@ -3137,7 +3139,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#else /* __APPLE__ */ #else /* __APPLE__ */
case WXK_DELETE: case WXK_DELETE:
#endif /* __APPLE__ */ #endif /* __APPLE__ */
if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::Delete)) if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::Delete))
m_dirty = true; m_dirty = true;
else else
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE)); post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE));
@ -3156,7 +3158,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
case 'A': case 'A':
case 'a': { case 'a': {
if (m_gizmos.get_current_type() == Gizmos::SlaSupports) { if (m_gizmos.get_current_type() == Gizmos::SlaSupports) {
if (m_gizmos.mouse_event(SLAGizmoEventType::AutomaticGeneration)) if (m_gizmos.gizmo_event(SLAGizmoEventType::AutomaticGeneration))
m_dirty = true; m_dirty = true;
} }
else else
@ -3173,7 +3175,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
case 'z': { m_selection.is_empty() ? zoom_to_volumes() : zoom_to_selection(); break; } case 'z': { m_selection.is_empty() ? zoom_to_volumes() : zoom_to_selection(); break; }
case 'M': case 'M':
case 'm': { case 'm': {
if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::ManualEditing)) { if (m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::ManualEditing)) {
m_dirty = true; m_dirty = true;
break; break;
} }
@ -3207,7 +3209,7 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
// Enable switching between 3D and Preview with Tab // Enable switching between 3D and Preview with Tab
// m_canvas->HandleAsNavigationKey(evt); // XXX: Doesn't work in some cases / on Linux // m_canvas->HandleAsNavigationKey(evt); // XXX: Doesn't work in some cases / on Linux
post_event(SimpleEvent(EVT_GLCANVAS_TAB)); post_event(SimpleEvent(EVT_GLCANVAS_TAB));
} else if (m_gizmos.get_current_type() == Gizmos::SlaSupports && keyCode == WXK_SHIFT && m_gizmos.mouse_event(SLAGizmoEventType::ShiftUp)) { } else if (m_gizmos.get_current_type() == Gizmos::SlaSupports && keyCode == WXK_SHIFT && m_gizmos.gizmo_event(SLAGizmoEventType::ShiftUp)) {
// shift has been just released - SLA gizmo might want to close rectangular selection. // shift has been just released - SLA gizmo might want to close rectangular selection.
m_dirty = true; m_dirty = true;
} }
@ -3443,10 +3445,6 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
_update_gizmos_data(); _update_gizmos_data();
m_dirty = true; m_dirty = true;
} }
else if (evt.LeftDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && evt.ShiftDown() && m_gizmos.mouse_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 (evt.LeftDown() && !m_selection.is_empty() && m_gizmos.grabber_contains_mouse()) else if (evt.LeftDown() && !m_selection.is_empty() && m_gizmos.grabber_contains_mouse())
{ {
_update_gizmos_data(); _update_gizmos_data();
@ -3462,7 +3460,11 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true; m_dirty = true;
} }
else if ((selected_object_idx != -1) && evt.RightDown() && m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.mouse_event(SLAGizmoEventType::RightDown)) else if (evt.LeftDown() && m_gizmos.get_current_type() == Gizmos::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() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::RightDown))
{ {
// event was taken care of by the SlaSupports gizmo // event was taken care of by the SlaSupports gizmo
} }
@ -3619,7 +3621,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_dirty = true; m_dirty = true;
} }
else if (evt.Dragging() && m_gizmos.get_current_type() == Gizmos::SlaSupports && evt.ShiftDown() && m_gizmos.mouse_event(SLAGizmoEventType::Dragging, Vec2d(pos(0), pos(1)), evt.ShiftDown())) else if (evt.Dragging() && m_gizmos.get_current_type() == Gizmos::SlaSupports && m_gizmos.gizmo_event(SLAGizmoEventType::Dragging, Vec2d(pos(0), pos(1)), evt.ShiftDown()))
{ {
// the gizmo got the event and took some action, no need to do anything more here // the gizmo got the event and took some action, no need to do anything more here
m_dirty = true; m_dirty = true;
@ -3672,11 +3674,13 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
m_layers_editing.accept_changes(*this); m_layers_editing.accept_changes(*this);
} }
else if (evt.LeftUp() && m_gizmos.get_current_type() == Gizmos::SlaSupports && !m_gizmos.is_dragging() else if (evt.LeftUp() && m_gizmos.get_current_type() == Gizmos::SlaSupports && !m_gizmos.is_dragging()
&& !m_mouse.dragging && m_gizmos.mouse_event(SLAGizmoEventType::LeftUp, Vec2d(pos(0), pos(1)), evt.ShiftDown())) && !m_mouse.dragging)
{ {
// the gizmo got the event and took some action, no need to do anything more // in case SLA gizmo is selected, we just pass the LeftUp event and stop processing - neither
// object moving or selecting is suppressed in that case
m_gizmos.gizmo_event(SLAGizmoEventType::LeftUp, Vec2d(pos(0), pos(1)), evt.ShiftDown());
} }
else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging && m_gizmos.get_current_type() != Gizmos::SlaSupports) else if ((m_mouse.drag.move_volume_idx != -1) && m_mouse.dragging)
{ {
m_regenerate_volumes = false; m_regenerate_volumes = false;
do_move(); do_move();
@ -3686,11 +3690,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
post_event(SimpleEvent(EVT_GLCANVAS_MOUSE_DRAGGING_FINISHED)); 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() else if (evt.LeftUp() && !m_mouse.dragging && (m_hover_volume_id == -1) && !gizmos_overlay_contains_mouse && !m_gizmos.is_dragging()
&& !is_layers_editing_enabled() && (m_gizmos.get_current_type() != Gizmos::SlaSupports || !m_gizmos.mouse_event(SLAGizmoEventType::LeftUp, Vec2d(pos(0), pos(1)), evt.ShiftDown()))) && !is_layers_editing_enabled())
{ {
// SLA gizmo cannot be deselected by clicking in canvas area to avoid inadvertent unselection and losing manual changes
// that's why the mouse_event function was called so that the gizmo can refuse the deselection in manual editing mode
// deselect and propagate event through callback // deselect and propagate event through callback
if (!evt.ShiftDown() && m_picking_enabled && !m_mouse.ignore_up_event) if (!evt.ShiftDown() && m_picking_enabled && !m_mouse.ignore_up_event)
{ {

View file

@ -446,8 +446,7 @@ private:
void set_flattening_data(const ModelObject* model_object); void set_flattening_data(const ModelObject* model_object);
void set_sla_support_data(ModelObject* model_object, const Selection& selection); void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false); bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false);
void delete_current_grabber(bool delete_all = false);
void render_current_gizmo(const Selection& selection) const; void render_current_gizmo(const Selection& selection) const;
void render_current_gizmo_for_picking_pass(const Selection& selection) const; void render_current_gizmo_for_picking_pass(const Selection& selection) const;

View file

@ -157,7 +157,7 @@ GLToolbar::GLToolbar(GLToolbar::EType type)
#if ENABLE_SVG_ICONS #if ENABLE_SVG_ICONS
, m_icons_texture_dirty(true) , m_icons_texture_dirty(true)
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
, m_mouse_capture({false, false, false}) , m_mouse_capture({ false, false, false, nullptr })
, m_tooltip("") , m_tooltip("")
{ {
} }
@ -418,8 +418,17 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
m_mouse_capture.middle = false; m_mouse_capture.middle = false;
else if (evt.RightUp()) else if (evt.RightUp())
m_mouse_capture.right = false; m_mouse_capture.right = false;
else if (m_mouse_capture.any() && evt.Dragging()) else if (m_mouse_capture.any())
processed = true; {
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();
}
int item_id = contains_mouse(mouse_pos, parent); int item_id = contains_mouse(mouse_pos, parent);
if (item_id == -1) if (item_id == -1)
@ -429,10 +438,11 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
} }
else else
{ {
// mouse inside toolbar only // mouse inside toolbar
if (evt.LeftDown() || evt.LeftDClick()) if (evt.LeftDown() || evt.LeftDClick())
{ {
m_mouse_capture.left = true; m_mouse_capture.left = true;
m_mouse_capture.parent = &parent;
if ((item_id != -2) && !m_items[item_id]->is_separator()) if ((item_id != -2) && !m_items[item_id]->is_separator())
{ {
// mouse is inside an icon // mouse is inside an icon
@ -441,9 +451,15 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
} }
} }
else if (evt.MiddleDown()) else if (evt.MiddleDown())
{
m_mouse_capture.middle = true; m_mouse_capture.middle = true;
m_mouse_capture.parent = &parent;
}
else if (evt.RightDown()) else if (evt.RightDown())
{
m_mouse_capture.right = true; m_mouse_capture.right = true;
m_mouse_capture.parent = &parent;
}
else if (evt.LeftUp()) else if (evt.LeftUp())
processed = true; processed = true;
} }

View file

@ -236,8 +236,10 @@ private:
bool left; bool left;
bool middle; bool middle;
bool right; bool right;
GLCanvas3D* parent;
bool any() const { return left || middle || right; } bool any() const { return left || middle || right; }
void reset() { left = middle = right = false; parent = nullptr; }
}; };
MouseCapture m_mouse_capture; MouseCapture m_mouse_capture;

View file

@ -95,7 +95,7 @@ ObjectList::ObjectList(wxWindow* parent) :
#endif //__WXMSW__ #endif //__WXMSW__
}); });
// Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { key_event(event); }); // doesn't work on OSX Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { key_event(event); }); // doesn't work on OSX
#ifdef __WXMSW__ #ifdef __WXMSW__
GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) { GetMainWindow()->Bind(wxEVT_MOTION, [this](wxMouseEvent& event) {
@ -442,8 +442,6 @@ void ObjectList::OnContextMenu(wxDataViewEvent&)
if (is_windows10()) if (is_windows10())
fix_through_netfabb(); fix_through_netfabb();
} }
else if (title == _("Extruder"))
show_extruder_selection_menu();
#ifndef __WXMSW__ #ifndef __WXMSW__
GetMainWindow()->SetToolTip(""); // hide tooltip GetMainWindow()->SetToolTip(""); // hide tooltip
@ -457,7 +455,7 @@ void ObjectList::show_context_menu()
if (selected_instances_of_same_object()) if (selected_instances_of_same_object())
wxGetApp().plater()->PopupMenu(&m_menu_instance); wxGetApp().plater()->PopupMenu(&m_menu_instance);
else else
show_extruder_selection_menu(); show_multi_selection_menu();
return; return;
} }
@ -989,10 +987,14 @@ wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu)
[this](wxCommandEvent&) { split_instances(); }, "", menu); [this](wxCommandEvent&) { split_instances(); }, "", menu);
} }
void ObjectList::append_menu_item_rename(wxMenu* menu) void ObjectList::append_menu_items_osx(wxMenu* menu)
{ {
append_menu_item(menu, wxID_ANY, _(L("Delete item")), "",
[this](wxCommandEvent&) { remove(); }, "", menu);
append_menu_item(menu, wxID_ANY, _(L("Rename")), "", append_menu_item(menu, wxID_ANY, _(L("Rename")), "",
[this](wxCommandEvent&) { rename_item(); }, "", menu); [this](wxCommandEvent&) { rename_item(); }, "", menu);
menu->AppendSeparator(); menu->AppendSeparator();
} }
@ -1015,7 +1017,7 @@ void ObjectList::append_menu_item_export_stl(wxMenu* menu) const
void ObjectList::create_object_popupmenu(wxMenu *menu) void ObjectList::create_object_popupmenu(wxMenu *menu)
{ {
#ifdef __WXOSX__ #ifdef __WXOSX__
append_menu_item_rename(menu); append_menu_items_osx(menu);
#endif // __WXOSX__ #endif // __WXOSX__
append_menu_item_export_stl(menu); append_menu_item_export_stl(menu);
@ -1036,7 +1038,7 @@ void ObjectList::create_object_popupmenu(wxMenu *menu)
void ObjectList::create_sla_object_popupmenu(wxMenu *menu) void ObjectList::create_sla_object_popupmenu(wxMenu *menu)
{ {
#ifdef __WXOSX__ #ifdef __WXOSX__
append_menu_item_rename(menu); append_menu_items_osx(menu);
#endif // __WXOSX__ #endif // __WXOSX__
append_menu_item_export_stl(menu); append_menu_item_export_stl(menu);
@ -1048,7 +1050,7 @@ void ObjectList::create_sla_object_popupmenu(wxMenu *menu)
void ObjectList::create_part_popupmenu(wxMenu *menu) void ObjectList::create_part_popupmenu(wxMenu *menu)
{ {
#ifdef __WXOSX__ #ifdef __WXOSX__
append_menu_item_rename(menu); append_menu_items_osx(menu);
#endif // __WXOSX__ #endif // __WXOSX__
append_menu_item_fix_through_netfabb(menu); append_menu_item_fix_through_netfabb(menu);
@ -1856,8 +1858,11 @@ void ObjectList::remove()
{ {
if (m_objects_model->GetParent(item) == wxDataViewItem(0)) if (m_objects_model->GetParent(item) == wxDataViewItem(0))
delete_from_model_and_list(itObject, m_objects_model->GetIdByItem(item), -1); delete_from_model_and_list(itObject, m_objects_model->GetIdByItem(item), -1);
else else {
if (sels.size() == 1)
select_item(m_objects_model->GetParent(item));
del_subobject_item(item); del_subobject_item(item);
}
} }
} }
@ -2357,7 +2362,7 @@ void ObjectList::OnEditingDone(wxDataViewEvent &event)
_(L("the following characters are not allowed:")) + " <>:/\\|?*\""); _(L("the following characters are not allowed:")) + " <>:/\\|?*\"");
} }
void ObjectList::show_extruder_selection_menu() void ObjectList::show_multi_selection_menu()
{ {
wxDataViewItemArray sels; wxDataViewItemArray sels;
GetSelections(sels); GetSelections(sels);
@ -2368,9 +2373,17 @@ void ObjectList::show_extruder_selection_menu()
return; return;
wxMenu* menu = new wxMenu(); wxMenu* menu = new wxMenu();
append_menu_item(menu, wxID_ANY, _(L("Set extruder for selected items")),
_(L("Select extruder number for selected objects and/or parts")), #ifdef __WXOSX__
[this](wxCommandEvent&) { extruder_selection(); }, "", menu); append_menu_item(menu, wxID_ANY, _(L("Delete items")), "",
[this](wxCommandEvent&) { remove(); }, "", menu);
#endif //__WXOSX__
if (extruders_count() > 1)
append_menu_item(menu, wxID_ANY, _(L("Set extruder for selected items")),
_(L("Select extruder number for selected objects and/or parts")),
[this](wxCommandEvent&) { extruder_selection(); }, "", menu);
PopupMenu(menu); PopupMenu(menu);
} }

View file

@ -184,7 +184,7 @@ public:
wxMenuItem* append_menu_item_settings(wxMenu* menu); wxMenuItem* append_menu_item_settings(wxMenu* menu);
wxMenuItem* append_menu_item_change_type(wxMenu* menu); wxMenuItem* append_menu_item_change_type(wxMenu* menu);
wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu); wxMenuItem* append_menu_item_instance_to_object(wxMenu* menu);
void append_menu_item_rename(wxMenu* menu); void append_menu_items_osx(wxMenu* menu);
void append_menu_item_fix_through_netfabb(wxMenu* menu); void append_menu_item_fix_through_netfabb(wxMenu* menu);
void append_menu_item_export_stl(wxMenu* menu) const ; void append_menu_item_export_stl(wxMenu* menu) const ;
void create_object_popupmenu(wxMenu *menu); void create_object_popupmenu(wxMenu *menu);
@ -283,7 +283,7 @@ private:
void ItemValueChanged(wxDataViewEvent &event); void ItemValueChanged(wxDataViewEvent &event);
void OnEditingDone(wxDataViewEvent &event); void OnEditingDone(wxDataViewEvent &event);
void show_extruder_selection_menu(); void show_multi_selection_menu();
void extruder_selection(); void extruder_selection();
void set_extruder_for_selected_items(const int extruder) const ; void set_extruder_for_selected_items(const int extruder) const ;

View file

@ -307,7 +307,7 @@ std::pair<Vec3f, Vec3f> GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse
// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is // The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is
// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo // aware that the event was reacted to and stops trying to make different sense of it. If the gizmo
// concludes that the event was not intended for it, it should return false. // concludes that the event was not intended for it, it should return false.
bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down) bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down)
{ {
if (m_editing_mode) { if (m_editing_mode) {
@ -326,39 +326,19 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
return true; return true;
} }
// dragging the selection rectangle: // left down without selection rectangle - place point on the mesh:
if (action == SLAGizmoEventType::Dragging && m_selection_rectangle_active) { if (action == SLAGizmoEventType::LeftDown && !m_selection_rectangle_active && !shift_down) {
m_selection_rectangle_end_corner = mouse_position;
return true;
}
// mouse up without selection rectangle - place point on the mesh:
if (action == SLAGizmoEventType::LeftUp && !m_selection_rectangle_active && !shift_down) {
if (m_ignore_up_event) {
m_ignore_up_event = false;
return false;
}
int instance_id = m_parent.get_selection().get_instance_idx();
if (m_old_instance_id != instance_id)
{
bool something_selected = (m_old_instance_id != -1);
m_old_instance_id = instance_id;
if (something_selected)
return false;
}
if (instance_id == -1)
return false;
// If there is some selection, don't add new point and deselect everything instead. // If there is some selection, don't add new point and deselect everything instead.
if (m_selection_empty) { if (m_selection_empty) {
try { try {
std::pair<Vec3f, Vec3f> pos_and_normal = unproject_on_mesh(mouse_position); // don't create anything if this throws std::pair<Vec3f, Vec3f> pos_and_normal = unproject_on_mesh(mouse_position); // don't create anything if this throws
m_editing_mode_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second); m_editing_mode_cache.emplace_back(sla::SupportPoint(pos_and_normal.first, m_new_point_head_diameter/2.f, false), false, pos_and_normal.second);
m_unsaved_changes = true; m_unsaved_changes = true;
m_parent.set_as_dirty();
m_wait_for_up_event = true;
} }
catch (...) { // not clicked on object catch (...) { // not clicked on object
return true; // prevents deselection of the gizmo by GLCanvas3D return false;
} }
} }
else else
@ -368,10 +348,7 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
} }
// left up with selection rectangle - select points inside the rectangle: // left up with selection rectangle - select points inside the rectangle:
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp) if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::ShiftUp) && m_selection_rectangle_active) {
&& m_selection_rectangle_active) {
if (action == SLAGizmoEventType::ShiftUp)
m_ignore_up_event = true;
const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix(); const Transform3d& instance_matrix = m_model_object->instances[m_active_instance]->get_transformation().get_matrix();
GLint viewport[4]; GLint viewport[4];
::glGetIntegerv(GL_VIEWPORT, viewport); ::glGetIntegerv(GL_VIEWPORT, viewport);
@ -421,6 +398,28 @@ bool GLGizmoSlaSupports::mouse_event(SLAGizmoEventType action, const Vec2d& mous
return true; return true;
} }
// left up with no selection rectangle
if (action == SLAGizmoEventType::LeftUp) {
if (m_wait_for_up_event) {
m_wait_for_up_event = false;
return true;
}
}
// dragging the selection rectangle:
if (action == SLAGizmoEventType::Dragging) {
if (m_wait_for_up_event)
return true; // point has been placed and the button not released yet
// this prevents GLCanvas from starting scene rotation
if (m_selection_rectangle_active) {
m_selection_rectangle_end_corner = mouse_position;
return true;
}
return false;
}
if (action == SLAGizmoEventType::Delete) { if (action == SLAGizmoEventType::Delete) {
// delete key pressed // delete key pressed
delete_selected_points(); delete_selected_points();
@ -692,10 +691,10 @@ bool GLGizmoSlaSupports::on_is_activable(const Selection& selection) const
|| !selection.is_from_single_instance()) || !selection.is_from_single_instance())
return false; return false;
// Check that none of the selected volumes is outside. // Check that none of the selected volumes is outside. Only SLA auxiliaries (supports) are allowed outside.
const Selection::IndicesList& list = selection.get_volume_idxs(); const Selection::IndicesList& list = selection.get_volume_idxs();
for (const auto& idx : list) for (const auto& idx : list)
if (selection.get_volume(idx)->is_outside) if (selection.get_volume(idx)->is_outside && selection.get_volume(idx)->composite_id.volume_id >= 0)
return false; return false;
return true; return true;

View file

@ -59,7 +59,7 @@ public:
#endif // ENABLE_SVG_ICONS #endif // ENABLE_SVG_ICONS
virtual ~GLGizmoSlaSupports(); virtual ~GLGizmoSlaSupports();
void set_sla_support_data(ModelObject* model_object, const Selection& selection); void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool mouse_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down); bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down);
void delete_selected_points(bool force = false); void delete_selected_points(bool force = false);
std::pair<float, float> get_sla_clipping_plane() const; std::pair<float, float> get_sla_clipping_plane() const;
@ -87,8 +87,7 @@ private:
bool m_selection_rectangle_active = false; bool m_selection_rectangle_active = false;
Vec2d m_selection_rectangle_start_corner; Vec2d m_selection_rectangle_start_corner;
Vec2d m_selection_rectangle_end_corner; Vec2d m_selection_rectangle_end_corner;
bool m_ignore_up_event = false; bool m_wait_for_up_event = false;
bool m_combo_box_open = false; // To ensure proper rendering of the imgui combobox.
bool m_unsaved_changes = false; // Are there unsaved changes in manual mode? bool m_unsaved_changes = false; // Are there unsaved changes in manual mode?
bool m_selection_empty = true; bool m_selection_empty = true;
EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state) EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state)

View file

@ -5,8 +5,11 @@
#include <wx/button.h> #include <wx/button.h>
#include <wx/statusbr.h> #include <wx/statusbr.h>
#include <wx/frame.h> #include <wx/frame.h>
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "I18N.hpp"
#include <iostream> #include <iostream>
namespace Slic3r { namespace Slic3r {
@ -22,7 +25,7 @@ ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id):
wxDefaultSize)), wxDefaultSize)),
m_cancelbutton(new wxButton(self, m_cancelbutton(new wxButton(self,
-1, -1,
"Cancel", _(L("Cancel")),
wxDefaultPosition, wxDefaultPosition,
wxDefaultSize)) wxDefaultSize))
{ {
@ -33,6 +36,9 @@ ProgressStatusBar::ProgressStatusBar(wxWindow *parent, int id):
int w[] = {-1, 150, 155}; int w[] = {-1, 150, 155};
self->SetStatusWidths(3, w); self->SetStatusWidths(3, w);
wxSize s = m_cancelbutton->GetTextExtent(m_cancelbutton->GetLabel());
self->SetMinHeight(int(2 * self->GetBorderY() + 1.2 * s.GetHeight()));
self->Bind(wxEVT_TIMER, [this](const wxTimerEvent&) { self->Bind(wxEVT_TIMER, [this](const wxTimerEvent&) {
if (m_prog->IsShown()) m_timer->Stop(); if (m_prog->IsShown()) m_timer->Stop();
if(is_busy()) m_prog->Pulse(); if(is_busy()) m_prog->Pulse();