diff --git a/src/libslic3r/MTUtils.hpp b/src/libslic3r/MTUtils.hpp index f07e8832d..3001c27ff 100644 --- a/src/libslic3r/MTUtils.hpp +++ b/src/libslic3r/MTUtils.hpp @@ -1,7 +1,7 @@ #ifndef MTUTILS_HPP #define MTUTILS_HPP -#include // for std::atomic_flag +#include // for std::atomic_flag and memory orders #include // for std::lock_guard #include // for std::function #include // for std::forward @@ -44,7 +44,7 @@ public: // 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 + // the setter function should be guarded as well during modification 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; 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; } diff --git a/src/libslic3r/ModelArrange.hpp b/src/libslic3r/ModelArrange.hpp index 78a400667..d62e0df30 100644 --- a/src/libslic3r/ModelArrange.hpp +++ b/src/libslic3r/ModelArrange.hpp @@ -20,9 +20,6 @@ public: inline double radius() const { return radius_; } inline const Point& center() const { return center_; } inline operator bool() { return !std::isnan(radius_); } -// inline operator lnCircle() { -// return lnCircle({center_(0), center_(1)}, radius_); -// } }; enum class BedShapeType { diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 486f7286c..b6b5691a1 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -2050,6 +2050,11 @@ void _3DScene::delete_selected(wxGLCanvas* canvas) s_canvas_mgr.delete_selected(canvas); } +void _3DScene::ensure_on_bed(wxGLCanvas* canvas, unsigned int object_idx) +{ + s_canvas_mgr.ensure_on_bed(canvas, object_idx); +} + std::vector _3DScene::get_current_print_zs(wxGLCanvas* canvas, bool active_only) { return s_canvas_mgr.get_current_print_zs(canvas, active_only); @@ -2102,9 +2107,9 @@ void _3DScene::mirror_selection(wxGLCanvas* canvas, Axis axis) s_canvas_mgr.mirror_selection(canvas, axis); } -void _3DScene::reload_scene(wxGLCanvas* canvas, bool force) +void _3DScene::reload_scene(wxGLCanvas* canvas, bool refresh_immediately, bool force_full_scene_refresh) { - s_canvas_mgr.reload_scene(canvas, force); + s_canvas_mgr.reload_scene(canvas, refresh_immediately, force_full_scene_refresh); } void _3DScene::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors) diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 6ebb6def0..7fdb845cf 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -634,6 +634,7 @@ public: static void render(wxGLCanvas* canvas); static void delete_selected(wxGLCanvas* canvas); + static void ensure_on_bed(wxGLCanvas* canvas, unsigned int object_idx); static std::vector get_current_print_zs(wxGLCanvas* canvas, bool active_only); static void set_toolpaths_range(wxGLCanvas* canvas, double low, double high); @@ -643,7 +644,7 @@ public: static void mirror_selection(wxGLCanvas* canvas, Axis axis); - static void reload_scene(wxGLCanvas* canvas, bool force); + static void reload_scene(wxGLCanvas* canvas, bool refresh_immediately, bool force_full_scene_refresh = false); static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors); static void load_preview(wxGLCanvas* canvas, const std::vector& str_tool_colors); 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; } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 11f3d8e06..e378eb23d 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3692,6 +3692,34 @@ void GLCanvas3D::delete_selected() m_selection.erase(); } +void GLCanvas3D::ensure_on_bed(unsigned int object_idx) +{ + typedef std::map, double> InstancesToZMap; + InstancesToZMap instances_min_z; + + for (GLVolume* volume : m_volumes.volumes) + { + if ((volume->object_idx() == object_idx) && !volume->is_modifier) + { + double min_z = volume->transformed_convex_hull_bounding_box().min(2); + std::pair instance = std::make_pair(volume->object_idx(), volume->instance_idx()); + InstancesToZMap::iterator it = instances_min_z.find(instance); + if (it == instances_min_z.end()) + it = instances_min_z.insert(InstancesToZMap::value_type(instance, DBL_MAX)).first; + + it->second = std::min(it->second, min_z); + } + } + + for (GLVolume* volume : m_volumes.volumes) + { + std::pair instance = std::make_pair(volume->object_idx(), volume->instance_idx()); + InstancesToZMap::iterator it = instances_min_z.find(instance); + if (it != instances_min_z.end()) + volume->set_instance_offset(Z, volume->get_instance_offset(Z) - it->second); + } +} + std::vector GLCanvas3D::get_current_print_zs(bool active_only) const { return m_volumes.get_current_print_zs(active_only); @@ -3739,7 +3767,7 @@ void GLCanvas3D::mirror_selection(Axis axis) // 3) SLA support meshes for their respective ModelObjects / ModelInstances // 4) Wipe tower preview // 5) Out of bed collision status & message overlay (texture) -void GLCanvas3D::reload_scene(bool force) +void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_refresh) { if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr)) return; @@ -3781,7 +3809,7 @@ void GLCanvas3D::reload_scene(bool force) glvolumes_new.reserve(m_volumes.volumes.size()); auto model_volume_state_lower = [](const ModelVolumeState &m1, const ModelVolumeState &m2) { return m1.geometry_id < m2.geometry_id; }; - m_reload_delayed = ! m_canvas->IsShown() && ! force; + m_reload_delayed = ! m_canvas->IsShown() && ! refresh_immediately && ! force_full_scene_refresh; PrinterTechnology printer_technology = wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology(); @@ -3838,7 +3866,7 @@ void GLCanvas3D::reload_scene(bool force) if (it != model_volume_state.end() && it->geometry_id == key.geometry_id) mvs = &(*it); } - if (mvs == nullptr) { + if (mvs == nullptr || force_full_scene_refresh) { // This GLVolume will be released. volume->release_geometry(); if (! m_reload_delayed) diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d65f55df8..a52b544cf 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -814,6 +814,7 @@ public: void render(); void delete_selected(); + void ensure_on_bed(unsigned int object_idx); std::vector get_current_print_zs(bool active_only) const; void set_toolpaths_range(double low, double high); @@ -823,7 +824,7 @@ public: void mirror_selection(Axis axis); - void reload_scene(bool force); + void reload_scene(bool refresh_immediately, bool force_full_scene_refresh); void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector& str_tool_colors); void load_preview(const std::vector& str_tool_colors); diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp index abf783460..fb5b8addb 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -461,6 +461,13 @@ void GLCanvas3DManager::delete_selected(wxGLCanvas* canvas) it->second->delete_selected(); } +void GLCanvas3DManager::ensure_on_bed(wxGLCanvas* canvas, unsigned int object_idx) +{ + CanvasesMap::const_iterator it = _get_canvas(canvas); + if (it != m_canvases.end()) + it->second->ensure_on_bed(object_idx); +} + std::vector GLCanvas3DManager::get_current_print_zs(wxGLCanvas* canvas, bool active_only) const { CanvasesMap::const_iterator it = _get_canvas(canvas); @@ -499,11 +506,11 @@ void GLCanvas3DManager::mirror_selection(wxGLCanvas* canvas, Axis axis) it->second->mirror_selection(axis); } -void GLCanvas3DManager::reload_scene(wxGLCanvas* canvas, bool force) +void GLCanvas3DManager::reload_scene(wxGLCanvas* canvas, bool refresh_immediately, bool force_full_scene_refresh) { CanvasesMap::iterator it = _get_canvas(canvas); if (it != m_canvases.end()) - it->second->reload_scene(force); + it->second->reload_scene(refresh_immediately, force_full_scene_refresh); } void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors) diff --git a/src/slic3r/GUI/GLCanvas3DManager.hpp b/src/slic3r/GUI/GLCanvas3DManager.hpp index 097d3a118..881befa1b 100644 --- a/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -131,6 +131,7 @@ public: void render(wxGLCanvas* canvas) const; void delete_selected(wxGLCanvas* canvas); + void ensure_on_bed(wxGLCanvas* canvas, unsigned int object_idx); std::vector get_current_print_zs(wxGLCanvas* canvas, bool active_only) const; void set_toolpaths_range(wxGLCanvas* canvas, double low, double high); @@ -140,7 +141,7 @@ public: void mirror_selection(wxGLCanvas* canvas, Axis axis); - void reload_scene(wxGLCanvas* canvas, bool force); + void reload_scene(wxGLCanvas* canvas, bool refresh_immediately, bool force_full_scene_refresh = false); void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors); void load_preview(wxGLCanvas* canvas, const std::vector& str_tool_colors); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 94b2d32f2..da358670b 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1205,7 +1205,10 @@ void ObjectList::delete_from_model_and_list(const std::vector& it else { del_subobject_from_object(item->obj_idx, item->sub_obj_idx, item->type); if (item->type&itVolume) + { m_objects_model->Delete(m_objects_model->GetItemByVolumeId(item->obj_idx, item->sub_obj_idx)); + _3DScene::ensure_on_bed(wxGetApp().canvas3D(), item->obj_idx); + } else m_objects_model->Delete(m_objects_model->GetItemByInstanceId(item->obj_idx, item->sub_obj_idx)); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5f6be2197..99c6148c7 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -930,7 +930,7 @@ struct Plater::priv priv(Plater *q, MainFrame *main_frame); - void update(bool force_autocenter = false); + void update(bool force_full_scene_refresh = false); void select_view(const std::string& direction); void update_ui_from_settings(); ProgressStatusBar* statusbar(); @@ -1144,10 +1144,10 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) q->Layout(); } -void Plater::priv::update(bool force_autocenter) +void Plater::priv::update(bool force_full_scene_refresh) { wxWindowUpdateLocker freeze_guard(q); - if (get_config("autocenter") == "1" || force_autocenter) { + if (get_config("autocenter") == "1") { // auto *bed_shape_opt = config->opt("bed_shape"); // const auto bed_shape = Slic3r::Polygon::new_scale(bed_shape_opt->values); // const BoundingBox bed_shape_bb = bed_shape.bounding_box(); @@ -1160,7 +1160,7 @@ void Plater::priv::update(bool force_autocenter) // pulls the correct data. this->update_background_process(); } - _3DScene::reload_scene(canvas3D, false); + _3DScene::reload_scene(canvas3D, false, force_full_scene_refresh); preview->reset_gcode_preview_data(); preview->reload_print(); @@ -1662,9 +1662,9 @@ void Plater::priv::arrange() // We enable back the arrange button _3DScene::enable_toolbar_item(canvas3D, "arrange", can_arrange()); - // FIXME: none of the following seem to work now. (update did the job previously) - // _3DScene::reload_scene(canvas3D, false); - update(); + // Do a full refresh of scene tree, including regenerating all the GLVolumes. + //FIXME The update function shall just reload the modified matrices. + update(true); } void Plater::priv::split_object() @@ -2268,7 +2268,7 @@ void Plater::load_files(const std::vector& input_files, bool load_mode void Plater::load_files(const std::vector &input_files) { p->load_files(input_files); } #endif // ENABLE_NEW_MENU_LAYOUT -void Plater::update(bool force_autocenter) { p->update(force_autocenter); } +void Plater::update() { p->update(); } void Plater::select_view(const std::string& direction) { p->select_view(direction); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index d6716c620..ddd5232f8 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -125,7 +125,7 @@ public: void load_files(const std::vector &input_files); #endif // ENABLE_NEW_MENU_LAYOUT - void update(bool force_autocenter = false); + void update(); void select_view(const std::string& direction); void remove(size_t obj_idx);