diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index e0aa67074..ffaa2d20c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3488,7 +3488,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = _utf8(L("Copy")) + " [" + GUI::shortkey_ctrl_prefix() + "C]"; item.sprite_id = 4; item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_COPY)); }; - item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_copy(); }; + item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_copy_to_clipboard(); }; if (!m_toolbar.add_item(item)) return false; @@ -3499,7 +3499,7 @@ bool GLCanvas3D::_init_toolbar() item.tooltip = _utf8(L("Paste")) + " [" + GUI::shortkey_ctrl_prefix() + "V]"; item.sprite_id = 5; item.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLTOOLBAR_PASTE)); }; - item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_paste(); }; + item.enabled_state_callback = []()->bool { return wxGetApp().plater()->can_paste_from_clipboard(); }; if (!m_toolbar.add_item(item)) return false; diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 667dcd899..d800f6f38 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -505,10 +505,10 @@ void MainFrame::init_menubar() editMenu->AppendSeparator(); append_menu_item(editMenu, wxID_ANY, _(L("&Copy")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + "C", _(L("Copy selection to clipboard")), [this](wxCommandEvent&) { m_plater->copy_selection_to_clipboard(); }, - menu_icon("copy_menu"), nullptr, [this](){return m_plater->can_copy(); }, this); + menu_icon("copy_menu"), nullptr, [this](){return m_plater->can_copy_to_clipboard(); }, this); append_menu_item(editMenu, wxID_ANY, _(L("&Paste")) + sep + GUI::shortkey_ctrl_prefix() + sep_space + "V", _(L("Paste clipboard")), [this](wxCommandEvent&) { m_plater->paste_from_clipboard(); }, - menu_icon("paste_menu"), nullptr, [this](){return m_plater->can_paste(); }, this); + menu_icon("paste_menu"), nullptr, [this](){return m_plater->can_paste_from_clipboard(); }, this); } // Window menu diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index c2456db80..f68267cef 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -4187,30 +4187,14 @@ void Plater::update_object_menu() { p->update_object_menu(); } void Plater::copy_selection_to_clipboard() { - p->view3D->get_canvas3d()->get_selection().copy_to_clipboard(); + if (can_copy_to_clipboard()) + p->view3D->get_canvas3d()->get_selection().copy_to_clipboard(); } void Plater::paste_from_clipboard() { - p->view3D->get_canvas3d()->get_selection().paste_from_clipboard(); -} - -bool Plater::can_paste_from_clipboard() const -{ - const Selection& selection = p->view3D->get_canvas3d()->get_selection(); - const Selection::Clipboard& clipboard = selection.get_clipboard(); - Selection::EMode mode = clipboard.get_mode(); - - if (clipboard.is_empty()) - return false; - - if ((mode == Selection::Volume) && !selection.is_from_single_instance()) - return false; - - if ((mode == Selection::Instance) && (selection.get_mode() != Selection::Instance)) - return false; - - return true; + if (can_paste_from_clipboard()) + p->view3D->get_canvas3d()->get_selection().paste_from_clipboard(); } void Plater::msw_rescale() @@ -4237,7 +4221,37 @@ bool Plater::can_split_to_objects() const { return p->can_split_to_objects(); } bool Plater::can_split_to_volumes() const { return p->can_split_to_volumes(); } bool Plater::can_arrange() const { return p->can_arrange(); } bool Plater::can_layers_editing() const { return p->can_layers_editing(); } -bool Plater::can_copy() const { return !is_selection_empty(); } -bool Plater::can_paste() const { return can_paste_from_clipboard(); } +bool Plater::can_paste_from_clipboard() const +{ + const Selection& selection = p->view3D->get_canvas3d()->get_selection(); + const Selection::Clipboard& clipboard = selection.get_clipboard(); + + if (clipboard.is_empty()) + return false; + + if ((wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA) && !clipboard.is_sla_compliant()) + return false; + + Selection::EMode mode = clipboard.get_mode(); + if ((mode == Selection::Volume) && !selection.is_from_single_instance()) + return false; + + if ((mode == Selection::Instance) && (selection.get_mode() != Selection::Instance)) + return false; + + return true; +} + +bool Plater::can_copy_to_clipboard() const +{ + if (is_selection_empty()) + return false; + + const Selection& selection = p->view3D->get_canvas3d()->get_selection(); + if ((wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptSLA) && !selection.is_sla_compliant()) + return false; + + return true; +} }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 761bf7a05..2851af654 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -200,7 +200,6 @@ public: void copy_selection_to_clipboard(); void paste_from_clipboard(); - bool can_paste_from_clipboard() const; bool can_delete() const; bool can_delete_all() const; @@ -212,8 +211,8 @@ public: bool can_split_to_volumes() const; bool can_arrange() const; bool can_layers_editing() const; - bool can_copy() const; - bool can_paste() const; + bool can_paste_from_clipboard() const; + bool can_copy_to_clipboard() const; void msw_rescale(); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index 6e80783cc..97168ee04 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -47,6 +47,26 @@ Selection::VolumeCache::VolumeCache(const Geometry::Transformation& volume_trans { } +bool Selection::Clipboard::is_sla_compliant() const +{ + if (m_mode == Selection::Volume) + return false; + + for (const ModelObject* o : m_model.objects) + { + if (o->is_multiparts()) + return false; + + for (const ModelVolume* v : o->volumes) + { + if (v->is_modifier()) + return false; + } + } + + return true; +} + Selection::Selection() : m_volumes(nullptr) , m_model(nullptr) @@ -385,6 +405,20 @@ bool Selection::is_from_single_object() const return (0 <= idx) && (idx < 1000); } +bool Selection::is_sla_compliant() const +{ + if (m_mode == Volume) + return false; + + for (unsigned int i : m_list) + { + if ((*m_volumes)[i]->is_modifier) + return false; + } + + return true; +} + bool Selection::requires_uniform_scale() const { if (is_single_full_instance() || is_single_modifier() || is_single_volume()) diff --git a/src/slic3r/GUI/Selection.hpp b/src/slic3r/GUI/Selection.hpp index 5da1e477b..802f8d284 100644 --- a/src/slic3r/GUI/Selection.hpp +++ b/src/slic3r/GUI/Selection.hpp @@ -152,6 +152,8 @@ public: void reset() { m_model.clear_objects(); } bool is_empty() const { return m_model.objects.empty(); } + bool is_sla_compliant() const; + ModelObject* add_object() { return m_model.add_object(); } ModelObject* get_object(unsigned int id) { return (id < (unsigned int)m_model.objects.size()) ? m_model.objects[id] : nullptr; } const ModelObjectPtrs& get_objects() const { return m_model.objects; } @@ -257,6 +259,7 @@ public: bool is_mixed() const { return m_type == Mixed; } bool is_from_single_instance() const { return get_instance_idx() != -1; } bool is_from_single_object() const; + bool is_sla_compliant() const; bool contains_volume(unsigned int volume_idx) const { return m_list.find(volume_idx) != m_list.end(); } bool requires_uniform_scale() const;