From 85219b8bc05e0dacd8a32519c3f46662f255a3df Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 21 Nov 2018 14:30:15 +0100 Subject: [PATCH 1/6] Fixed split object to objects --- src/libslic3r/Model.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 3801c5b12..3aa04f3b2 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1051,9 +1051,6 @@ void ModelObject::split(ModelObjectPtrs* new_objects) ModelVolume* volume = this->volumes.front(); TriangleMeshPtrs meshptrs = volume->mesh.split(); for (TriangleMesh *mesh : meshptrs) { - // Snap the mesh to Z=0. - float z0 = FLT_MAX; - mesh->repair(); // XXX: this seems to be the only real usage of m_model, maybe refactor this so that it's not needed? @@ -1063,7 +1060,20 @@ void ModelObject::split(ModelObjectPtrs* new_objects) new_object->instances.reserve(this->instances.size()); for (const ModelInstance *model_instance : this->instances) new_object->add_instance(*model_instance); +#if ENABLE_MODELVOLUME_TRANSFORM + ModelVolume* new_vol = new_object->add_volume(*volume, std::move(*mesh)); + new_vol->center_geometry(); + + for (ModelInstance* model_instance : new_object->instances) + { + Vec3d shift = model_instance->get_transformation().get_matrix(true) * new_vol->get_offset(); + model_instance->set_offset(model_instance->get_offset() + shift); + } + + new_vol->set_offset(Vec3d::Zero()); +#else new_object->add_volume(*volume, std::move(*mesh)); +#endif // ENABLE_MODELVOLUME_TRANSFORM new_objects->emplace_back(new_object); delete mesh; } From c6b597b8138f464265d26def3d3cba60f21fb140 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Wed, 21 Nov 2018 15:02:22 +0100 Subject: [PATCH 2/6] Fixed updating of the options values after the clearing of the TextCtrl --- src/slic3r/GUI/Field.cpp | 23 ++++++++++++++++++----- src/slic3r/GUI/Field.hpp | 3 ++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 68d3948bb..bc1a5c1e9 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -161,6 +161,13 @@ void Field::get_value_by_opt_type(wxString& str) } } +bool TextCtrl::is_defined_input_value() +{ + if (static_cast(window)->GetValue().empty() && m_opt.type != coString && m_opt.type != coStrings) + return false; + return true; +} + void TextCtrl::BUILD() { auto size = wxSize(wxDefaultSize); if (m_opt.height >= 0) size.SetHeight(m_opt.height); @@ -226,16 +233,21 @@ void TextCtrl::BUILD() { temp->GetToolTip()->Enable(flag); }), temp->GetId()); -#if !defined(__WXGTK__) temp->Bind(wxEVT_KILL_FOCUS, ([this, temp](wxEvent& e) { - e.Skip();// on_kill_focus(e); +#if !defined(__WXGTK__) + e.Skip(); temp->GetToolTip()->Enable(true); - }), temp->GetId()); #endif // __WXGTK__ + if (!is_defined_input_value()) + on_kill_focus(e); + }), temp->GetId()); if (m_process_enter) { - temp->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent& evt) { on_change_field(); }), temp->GetId()); + temp->Bind(wxEVT_TEXT_ENTER, ([this](wxCommandEvent& evt) { + if(is_defined_input_value()) + on_change_field(); + }), temp->GetId()); } else { temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent& evt) @@ -243,6 +255,7 @@ void TextCtrl::BUILD() { #ifdef __WXGTK__ if (bChangedValueEvent) #endif //__WXGTK__ + if(is_defined_input_value()) on_change_field(); }), temp->GetId()); @@ -357,7 +370,7 @@ void SpinCtrl::BUILD() { 0, min_val, max_val, default_value); // temp->Bind(wxEVT_SPINCTRL, ([this](wxCommandEvent e) { tmp_value = undef_spin_val; on_change_field(); }), temp->GetId()); -// temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { tmp_value = undef_spin_val; on_kill_focus(e); }), temp->GetId()); + temp->Bind(wxEVT_KILL_FOCUS, ([this](wxEvent& e) { on_kill_focus(e); }), temp->GetId()); temp->Bind(wxEVT_TEXT, ([this](wxCommandEvent e) { // # On OSX / Cocoa, wxSpinCtrl::GetValue() doesn't return the new value diff --git a/src/slic3r/GUI/Field.hpp b/src/slic3r/GUI/Field.hpp index 29ae6f9ce..87ec0c1da 100644 --- a/src/slic3r/GUI/Field.hpp +++ b/src/slic3r/GUI/Field.hpp @@ -265,7 +265,8 @@ public: } boost::any& get_value() override; - + bool is_defined_input_value(); + virtual void enable(); virtual void disable(); virtual wxWindow* getWindow() { return window; } From 3667fc7894d4b6b8472962707967e090dce6de58 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 21 Nov 2018 15:21:57 +0100 Subject: [PATCH 3/6] Change to return const references for TriangleMesh return values in SLAPrintObject's methods --- src/libslic3r/CMakeLists.txt | 1 + src/libslic3r/MTUtils.hpp | 63 ++++++++++++++++++++++++++++ src/libslic3r/SLA/SLASupportTree.cpp | 13 +++--- src/libslic3r/SLA/SLASupportTree.hpp | 2 +- src/libslic3r/SLAPrint.cpp | 55 ++++++++++++------------ src/libslic3r/SLAPrint.hpp | 20 +++++---- 6 files changed, 111 insertions(+), 43 deletions(-) create mode 100644 src/libslic3r/MTUtils.hpp diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 3c3459f9d..059d871ae 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -156,6 +156,7 @@ add_library(libslic3r STATIC TriangleMesh.hpp utils.cpp Utils.hpp + MTUtils.hpp SLA/SLABoilerPlate.hpp SLA/SLABasePool.hpp SLA/SLABasePool.cpp diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp new file mode 100644 index 000000000..f07e8832d --- /dev/null +++ b/src/libslic3r/MTUtils.hpp @@ -0,0 +1,63 @@ +#ifndef MTUTILS_HPP +#define MTUTILS_HPP + +#include // for std::atomic_flag +#include // for std::lock_guard +#include // for std::function +#include // for std::forward + +namespace Slic3r { + +// TODO: these classes are untested + +/// Handy little spin mutex for the cached meshes. +/// Implements the "Lockable" concept +class SpinMutex { + std::atomic_flag m_flg; + static const /*constexpr*/ auto MO_ACQ = std::memory_order_acquire; + static const /*constexpr*/ auto MO_REL = std::memory_order_release; +public: + inline SpinMutex() { m_flg.clear(MO_REL); } + inline void lock() { while(m_flg.test_and_set(MO_ACQ)); } + inline bool try_lock() { return !m_flg.test_and_set(MO_ACQ); } + inline void unlock() { m_flg.clear(MO_REL); } +}; + +/// A wrapper class around arbitrary object that needs thread safe caching. +template class CachedObject { +public: + // Method type which refreshes the object when it has been invalidated + using Setter = std::function; +private: + T m_obj; // the object itself + bool m_valid; // invalidation flag + SpinMutex m_lck; // to make the caching thread safe + + // the setter will be called just before the object's const value is about + // to be retrieved. + std::function m_setter; +public: + + // Forwarded constructor + template inline CachedObject(Setter fn, Args&&...args): + m_obj(std::forward(args)...), m_valid(false), m_setter(fn) {} + + // invalidate the value of the object. The object will be refreshed at the + // next retrieval (Setter will be called). The data that is used in + // the setter function should be guarded as well if it is modified so the + // modification has to take place in fn. + inline void invalidate(std::function fn) { + std::lock_guard lck(m_lck); fn(); m_valid = false; + } + + // Get the const object properly updated. + inline const T& get() { + std::lock_guard lck(m_lck); + if(!m_valid) { m_setter(m_obj); m_valid = true; } + return m_obj; + } +}; + +} + +#endif // MTUTILS_HPP diff --git a/src/libslic3r/SLA/SLASupportTree.cpp b/src/libslic3r/SLA/SLASupportTree.cpp index f42f3b4ac..46f4d27e8 100644 --- a/src/libslic3r/SLA/SLASupportTree.cpp +++ b/src/libslic3r/SLA/SLASupportTree.cpp @@ -730,6 +730,9 @@ public: meshcache.merge(mesh(bs.mesh)); } + // TODO: Is this necessary? + meshcache.repair(); + BoundingBoxf3&& bb = meshcache.bounding_box(); model_height = bb.max(Z) - bb.min(Z); @@ -1616,13 +1619,13 @@ bool SLASupportTree::generate(const PointSet &points, return pc == ABORT; } -void SLASupportTree::merged_mesh(TriangleMesh &outmesh) const +const TriangleMesh &SLASupportTree::merged_mesh() const { - outmesh.merge(get().merged_mesh()); + return get().merged_mesh(); } void SLASupportTree::merged_mesh_with_pad(TriangleMesh &outmesh) const { - merged_mesh(outmesh); + outmesh.merge(merged_mesh()); outmesh.merge(get_pad()); } @@ -1658,14 +1661,12 @@ const TriangleMesh &SLASupportTree::add_pad(const SliceLayer& baseplate, double max_merge_distance_mm, double edge_radius_mm) const { - TriangleMesh mm; - merged_mesh(mm); PoolConfig pcfg; pcfg.min_wall_thickness_mm = min_wall_thickness_mm; pcfg.min_wall_height_mm = min_wall_height_mm; pcfg.max_merge_distance_mm = max_merge_distance_mm; pcfg.edge_radius_mm = edge_radius_mm; - return m_impl->create_pad(mm, baseplate, pcfg).tmesh; + return m_impl->create_pad(merged_mesh(), baseplate, pcfg).tmesh; } const TriangleMesh &SLASupportTree::get_pad() const diff --git a/src/libslic3r/SLA/SLASupportTree.hpp b/src/libslic3r/SLA/SLASupportTree.hpp index ce562946c..163cacbde 100644 --- a/src/libslic3r/SLA/SLASupportTree.hpp +++ b/src/libslic3r/SLA/SLASupportTree.hpp @@ -144,7 +144,7 @@ public: /// Get the whole mesh united into the output TriangleMesh /// WITHOUT THE PAD - void merged_mesh(TriangleMesh& outmesh) const; + const TriangleMesh& merged_mesh() const; void merged_mesh_with_pad(TriangleMesh&) const; diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index c8f6c1409..92b5bff8b 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -500,7 +500,10 @@ void SLAPrint::process() SLAPrintObject::SLAPrintObject(SLAPrint *print, ModelObject *model_object): Inherited(print, model_object), - m_stepmask(slaposCount, true) + m_stepmask(slaposCount, true), + m_transformed_rmesh( [this](TriangleMesh& obj){ + obj = m_model_object->raw_mesh(); obj.transform(m_trafo); + }) { } @@ -526,28 +529,29 @@ double SLAPrintObject::get_elevation() const { return ret; } -//const std::vector &SLAPrintObject::get_support_slices() const -//{ -// // I don't want to return a copy but the points may not exist, so ... -// static const std::vector dummy_empty; +namespace { // dummy empty static containers for return values in some methods +const std::vector EMPTY_SLICES; +const TriangleMesh EMPTY_MESH; +} -// if(!m_supportdata) return dummy_empty; -// return m_supportdata->support_slices; -//} +const std::vector &SLAPrintObject::get_support_slices() const +{ + if(!is_step_done(slaposSliceSupports) || !m_supportdata) return EMPTY_SLICES; + return m_supportdata->support_slices; +} -//const std::vector &SLAPrintObject::get_model_slices() const -//{ -// return m_model_slices; -//} +const std::vector &SLAPrintObject::get_model_slices() const +{ + if(!is_step_done(slaposObjectSlice)) return EMPTY_SLICES; + return m_model_slices; +} bool SLAPrintObject::has_mesh(SLAPrintObjectStep step) const { switch (step) { case slaposSupportTree: -// return m_supportdata && m_supportdata->support_tree_ptr && ! m_supportdata->support_tree_ptr->get().merged_mesh().empty(); return ! this->support_mesh().empty(); case slaposBasePool: -// return m_supportdata && m_supportdata->support_tree_ptr && ! m_supportdata->support_tree_ptr->get_pad().empty(); return ! this->pad_mesh().empty(); default: return false; @@ -566,22 +570,19 @@ TriangleMesh SLAPrintObject::get_mesh(SLAPrintObjectStep step) const } } -TriangleMesh SLAPrintObject::support_mesh() const + + +const TriangleMesh& SLAPrintObject::support_mesh() const { - TriangleMesh trm; - if(m_supportdata && m_supportdata->support_tree_ptr) - m_supportdata->support_tree_ptr->merged_mesh(trm); + return m_supportdata->support_tree_ptr->merged_mesh(); - // TODO: is this necessary? - trm.repair(); - - return trm; + return EMPTY_MESH; } -TriangleMesh SLAPrintObject::pad_mesh() const +const TriangleMesh& SLAPrintObject::pad_mesh() const { - if(!m_supportdata || !m_supportdata->support_tree_ptr) return {}; + if(!m_supportdata || !m_supportdata->support_tree_ptr) return EMPTY_MESH; return m_supportdata->support_tree_ptr->get_pad(); } @@ -596,11 +597,7 @@ const TriangleMesh &SLAPrintObject::transformed_mesh() const { // or apply an inverse transformation on the support structure after it // has been created. - if(m_trmesh_valid) return m_transformed_rmesh; - m_transformed_rmesh = m_model_object->raw_mesh(); - m_transformed_rmesh.transform(m_trafo); - m_trmesh_valid = true; - return m_transformed_rmesh; + return m_transformed_rmesh.get(); } std::vector SLAPrintObject::transformed_support_points() const diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 67a1db21a..ae797e9fb 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -1,9 +1,12 @@ #ifndef slic3r_SLAPrint_hpp_ #define slic3r_SLAPrint_hpp_ +#include + #include "PrintBase.hpp" #include "PrintExport.hpp" #include "Point.hpp" +#include "MTUtils.hpp" namespace Slic3r { @@ -53,10 +56,10 @@ public: // Get a support mesh centered around origin in XY, and with zero rotation around Z applied. // Support mesh is only valid if this->is_step_done(slaposSupportTree) is true. - TriangleMesh support_mesh() const; + const TriangleMesh& support_mesh() const; // Get a pad mesh centered around origin in XY, and with zero rotation around Z applied. // Support mesh is only valid if this->is_step_done(slaposPad) is true. - TriangleMesh pad_mesh() const; + const TriangleMesh& pad_mesh() const; // This will return the transformed mesh which is cached const TriangleMesh& transformed_mesh() const; @@ -69,8 +72,9 @@ public: // as the pad height also needs to be considered. double get_elevation() const; -// const std::vector& get_support_slices() const; -// const std::vector& get_model_slices() const; + // Should be obvious + const std::vector& get_support_slices() const; + const std::vector& get_model_slices() const; // I refuse to grantee copying (Tamas) SLAPrintObject(const SLAPrintObject&) = delete; @@ -86,7 +90,10 @@ protected: void config_apply(const ConfigBase &other, bool ignore_nonexistent = false) { this->m_config.apply(other, ignore_nonexistent); } void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) { this->m_config.apply_only(other, keys, ignore_nonexistent); } - void set_trafo(const Transform3d& trafo) { m_trafo = trafo; m_trmesh_valid = false; } + + void set_trafo(const Transform3d& trafo) { + m_transformed_rmesh.invalidate([this, &trafo](){ m_trafo = trafo; }); + } bool set_instances(const std::vector &instances); // Invalidates the step, and its depending steps in SLAPrintObject and SLAPrint. @@ -105,8 +112,7 @@ private: std::vector m_model_slices; // Caching the transformed (m_trafo) raw mesh of the object - mutable TriangleMesh m_transformed_rmesh; - mutable bool m_trmesh_valid = false; + mutable CachedObject m_transformed_rmesh; class SupportData; std::unique_ptr m_supportdata; From 681beeadf61292ff938b32959dc0af98c73361e5 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 21 Nov 2018 15:28:35 +0100 Subject: [PATCH 4/6] Added menu Edit -> Select all --- src/slic3r/GUI/3DScene.cpp | 5 ++++ src/slic3r/GUI/3DScene.hpp | 1 + src/slic3r/GUI/GLCanvas3D.cpp | 21 ++++++++++++++++ src/slic3r/GUI/GLCanvas3D.hpp | 3 +++ src/slic3r/GUI/GLCanvas3DManager.cpp | 7 ++++++ src/slic3r/GUI/GLCanvas3DManager.hpp | 1 + src/slic3r/GUI/MainFrame.cpp | 37 ++++++++++++++++++++++------ src/slic3r/GUI/MainFrame.hpp | 1 + src/slic3r/GUI/Plater.cpp | 8 ++++++ src/slic3r/GUI/Plater.hpp | 1 + 10 files changed, 77 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index b6b5691a1..8635c2a57 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -2045,6 +2045,11 @@ void _3DScene::render(wxGLCanvas* canvas) s_canvas_mgr.render(canvas); } +void _3DScene::select_all(wxGLCanvas* canvas) +{ + s_canvas_mgr.select_all(canvas); +} + void _3DScene::delete_selected(wxGLCanvas* canvas) { s_canvas_mgr.delete_selected(canvas); diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 7fdb845cf..28541cea2 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -633,6 +633,7 @@ public: static void render(wxGLCanvas* canvas); + static void select_all(wxGLCanvas* canvas); static void delete_selected(wxGLCanvas* canvas); static void ensure_on_bed(wxGLCanvas* canvas, unsigned int object_idx); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index e378eb23d..17959af03 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1315,6 +1315,22 @@ void GLCanvas3D::Selection::remove_volume(unsigned int object_idx, unsigned int m_bounding_box_dirty = true; } +void GLCanvas3D::Selection::add_all() +{ + if (!m_valid) + return; + + m_mode = Instance; + + for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i) + { + _add_volume(i); + } + + _update_type(); + m_bounding_box_dirty = true; +} + void GLCanvas3D::Selection::clear() { if (!m_valid) @@ -3687,6 +3703,11 @@ void GLCanvas3D::render() m_canvas->SwapBuffers(); } +void GLCanvas3D::select_all() +{ + m_selection.add_all(); +} + void GLCanvas3D::delete_selected() { m_selection.erase(); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index a52b544cf..5404701f8 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -485,6 +485,8 @@ public: void add_volume(unsigned int object_idx, unsigned int volume_idx, int instance_idx, bool as_single_selection = true); void remove_volume(unsigned int object_idx, unsigned int volume_idx); + void add_all(); + // Update the selection based on the map from old indices to new indices after m_volumes changed. // If the current selection is by instance, this call may select newly added volumes, if they belong to already selected instances. void volumes_changed(const std::vector &map_volume_old_to_new); @@ -813,6 +815,7 @@ public: void render(); + void select_all(); void delete_selected(); void ensure_on_bed(unsigned int object_idx); diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index fb5b8addb..6038f0b62 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -454,6 +454,13 @@ void GLCanvas3DManager::render(wxGLCanvas* canvas) const it->second->render(); } +void GLCanvas3DManager::select_all(wxGLCanvas* canvas) +{ + CanvasesMap::const_iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->select_all(); +} + void GLCanvas3DManager::delete_selected(wxGLCanvas* canvas) { CanvasesMap::const_iterator it = _get_canvas(canvas); diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index 881befa1b..e03f780c8 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -130,6 +130,7 @@ public: void render(wxGLCanvas* canvas) const; + void select_all(wxGLCanvas* canvas); void delete_selected(wxGLCanvas* canvas); void ensure_on_bed(wxGLCanvas* canvas, unsigned int object_idx); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 0bbeae022..0c3b75e71 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -201,6 +201,11 @@ bool MainFrame::can_change_view() const int page_id = m_tabpanel->GetSelection(); return (page_id != wxNOT_FOUND) ? m_tabpanel->GetPageText((size_t)page_id).Lower() == "plater" : false; } + +bool MainFrame::can_select() const +{ + return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false; +} #endif // ENABLE_NEW_MENU_LAYOUT void MainFrame::init_menubar() @@ -301,6 +306,19 @@ void MainFrame::init_menubar() #endif // ENABLE_NEW_MENU_LAYOUT } +#if ENABLE_NEW_MENU_LAYOUT + // Edit menu + wxMenu* editMenu = nullptr; + if (m_plater != nullptr) + { + editMenu = new wxMenu(); + wxMenuItem* item_select_all = append_menu_item(editMenu, wxID_ANY, L("Select all\tCtrl+A"), L("Selects all objects"), + [this](wxCommandEvent&) { m_plater->select_all(); }, ""); + + Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId()); + } +#endif // ENABLE_NEW_MENU_LAYOUT + #if !ENABLE_NEW_MENU_LAYOUT // Plater menu if (m_plater) { @@ -321,18 +339,18 @@ void MainFrame::init_menubar() { size_t tab_offset = 0; if (m_plater) { - append_menu_item(windowMenu, wxID_ANY, L("Select &Plater Tab\tCtrl+1"), L("Show the plater"), + append_menu_item(windowMenu, wxID_ANY, L("Select Plater Tab\tCtrl+1"), L("Show the plater"), [this](wxCommandEvent&) { select_tab(0); }, "application_view_tile.png"); tab_offset += 1; } if (tab_offset > 0) { windowMenu->AppendSeparator(); } - append_menu_item(windowMenu, wxID_ANY, L("Select P&rint Settings Tab\tCtrl+2"), L("Show the print settings"), + append_menu_item(windowMenu, wxID_ANY, L("Select Print Settings Tab\tCtrl+2"), L("Show the print settings"), [this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 0); }, "cog.png"); - append_menu_item(windowMenu, wxID_ANY, L("Select &Filament Settings Tab\tCtrl+3"), L("Show the filament settings"), + append_menu_item(windowMenu, wxID_ANY, L("Select Filament Settings Tab\tCtrl+3"), L("Show the filament settings"), [this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 1); }, "spool.png"); - append_menu_item(windowMenu, wxID_ANY, L("Select Print&er Settings Tab\tCtrl+4"), L("Show the printer settings"), + append_menu_item(windowMenu, wxID_ANY, L("Select Printer Settings Tab\tCtrl+4"), L("Show the printer settings"), [this, tab_offset](wxCommandEvent&) { select_tab(tab_offset + 2); }, "printer_empty.png"); } @@ -389,18 +407,18 @@ void MainFrame::init_menubar() //# wxTheApp->check_version(1); //# }); //# $versioncheck->Enable(wxTheApp->have_version_check); - append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r &Website")), _(L("Open the Slic3r website in your browser")), + append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r Website")), _(L("Open the Slic3r website in your browser")), [this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://slic3r.org/"); }); - append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r &Manual")), _(L("Open the Slic3r manual in your browser")), + append_menu_item(helpMenu, wxID_ANY, _(L("Slic3r Manual")), _(L("Open the Slic3r manual in your browser")), [this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://manual.slic3r.org/"); }); helpMenu->AppendSeparator(); append_menu_item(helpMenu, wxID_ANY, _(L("System Info")), _(L("Show system information")), [this](wxCommandEvent&) { wxGetApp().system_info(); }); - append_menu_item(helpMenu, wxID_ANY, _(L("Show &Configuration Folder")), _(L("Show user configuration folder (datadir)")), + append_menu_item(helpMenu, wxID_ANY, _(L("Show Configuration Folder")), _(L("Show user configuration folder (datadir)")), [this](wxCommandEvent&) { Slic3r::GUI::desktop_open_datadir_folder(); }); append_menu_item(helpMenu, wxID_ANY, _(L("Report an Issue")), _(L("Report an issue on the Slic3r Prusa Edition")), [this](wxCommandEvent&) { wxLaunchDefaultBrowser("http://github.com/prusa3d/slic3r/issues/new"); }); - append_menu_item(helpMenu, wxID_ANY, _(L("&About Slic3r")), _(L("Show about dialog")), + append_menu_item(helpMenu, wxID_ANY, _(L("About Slic3r")), _(L("Show about dialog")), [this](wxCommandEvent&) { Slic3r::GUI::about(); }); } @@ -410,6 +428,9 @@ void MainFrame::init_menubar() { auto menubar = new wxMenuBar(); menubar->Append(fileMenu, L("&File")); +#if ENABLE_NEW_MENU_LAYOUT + if (editMenu) menubar->Append(editMenu, L("&Edit")); +#endif // ENABLE_NEW_MENU_LAYOUT #if !ENABLE_NEW_MENU_LAYOUT if (m_plater_menu) menubar->Append(m_plater_menu, L("&Plater")); #endif // !ENABLE_NEW_MENU_LAYOUT diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 8cac3e8e2..8b534e324 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -71,6 +71,7 @@ class MainFrame : public wxFrame bool can_export_model() const; bool can_export_gcode() const; bool can_change_view() const; + bool can_select() const; #endif // ENABLE_NEW_MENU_LAYOUT public: diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 99c6148c7..df15f8207 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -951,6 +951,7 @@ struct Plater::priv void selection_changed(); void object_list_changed(); + void select_all(); void remove(size_t obj_idx); void delete_object_from_model(size_t obj_idx); void reset(); @@ -1529,6 +1530,11 @@ void Plater::priv::object_list_changed() sidebar->enable_buttons(!model.objects.empty() && !export_in_progress && model_fits); } +void Plater::priv::select_all() +{ + _3DScene::select_all(canvas3D); +} + void Plater::priv::remove(size_t obj_idx) { // Prevent toolpaths preview from rendering while we modify the Print object @@ -2272,6 +2278,8 @@ void Plater::update() { p->update(); } void Plater::select_view(const std::string& direction) { p->select_view(direction); } +void Plater::select_all() { p->select_all(); } + void Plater::remove(size_t obj_idx) { p->remove(obj_idx); } void Plater::delete_object_from_model(size_t obj_idx) { p->delete_object_from_model(obj_idx); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index ddd5232f8..9214db4cb 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -128,6 +128,7 @@ public: void update(); void select_view(const std::string& direction); + void select_all(); void remove(size_t obj_idx); void delete_object_from_model(size_t obj_idx); void remove_selected(); From 3e939a7496d32723f756475389ca77e7b15a9410 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 21 Nov 2018 15:47:41 +0100 Subject: [PATCH 5/6] Added menu Edit -> Delete selected --- src/slic3r/GUI/MainFrame.cpp | 8 ++++++++ src/slic3r/GUI/MainFrame.hpp | 1 + src/slic3r/GUI/Plater.cpp | 5 +++++ src/slic3r/GUI/Plater.hpp | 1 + 4 files changed, 15 insertions(+) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 0c3b75e71..db5b8a650 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -206,6 +206,11 @@ bool MainFrame::can_select() const { return (m_plater != nullptr) ? !m_plater->model().objects.empty() : false; } + +bool MainFrame::can_delete() const +{ + return (m_plater != nullptr) ? !m_plater->is_selection_empty() : false; +} #endif // ENABLE_NEW_MENU_LAYOUT void MainFrame::init_menubar() @@ -314,8 +319,11 @@ void MainFrame::init_menubar() editMenu = new wxMenu(); wxMenuItem* item_select_all = append_menu_item(editMenu, wxID_ANY, L("Select all\tCtrl+A"), L("Selects all objects"), [this](wxCommandEvent&) { m_plater->select_all(); }, ""); + wxMenuItem* item_delete_sel = append_menu_item(editMenu, wxID_ANY, L("Delete selected\tCtrl+D"), L("Deletes the current selection"), + [this](wxCommandEvent&) { m_plater->remove_selected(); }, ""); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId()); + Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_delete()); }, item_delete_sel->GetId()); } #endif // ENABLE_NEW_MENU_LAYOUT diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 8b534e324..488d0bd04 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -72,6 +72,7 @@ class MainFrame : public wxFrame bool can_export_gcode() const; bool can_change_view() const; bool can_select() const; + bool can_delete() const; #endif // ENABLE_NEW_MENU_LAYOUT public: diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index df15f8207..f3b3318db 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2366,6 +2366,11 @@ void Plater::set_number_of_copies(/*size_t num*/) decrease_instances(-diff); } +bool Plater::is_selection_empty() const +{ + return p->get_selection().is_empty(); +} + void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z) { wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds"); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 9214db4cb..b9cc9d528 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -135,6 +135,7 @@ public: void increase_instances(size_t num = 1); void decrease_instances(size_t num = 1); void set_number_of_copies(/*size_t num*/); + bool is_selection_empty() const; void cut(size_t obj_idx, size_t instance_idx, coordf_t z); From a27e238ceda9cc063bbcdc4557a0218f64a47b07 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Wed, 21 Nov 2018 16:00:20 +0100 Subject: [PATCH 6/6] Use Del as shortcut for Edit/Delete selected --- src/slic3r/GUI/MainFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index db5b8a650..b0d0c178b 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -319,7 +319,7 @@ void MainFrame::init_menubar() editMenu = new wxMenu(); wxMenuItem* item_select_all = append_menu_item(editMenu, wxID_ANY, L("Select all\tCtrl+A"), L("Selects all objects"), [this](wxCommandEvent&) { m_plater->select_all(); }, ""); - wxMenuItem* item_delete_sel = append_menu_item(editMenu, wxID_ANY, L("Delete selected\tCtrl+D"), L("Deletes the current selection"), + wxMenuItem* item_delete_sel = append_menu_item(editMenu, wxID_ANY, L("Delete selected\tDel"), L("Deletes the current selection"), [this](wxCommandEvent&) { m_plater->remove_selected(); }, ""); Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) { evt.Enable(can_select()); }, item_select_all->GetId());