diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index c43f215d9..d61033ec4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -294,6 +294,7 @@ void GLGizmoSimplify::live_preview() { // wait until cancel if (m_worker.joinable()) { m_state = State::canceling; + m_dealy_process_cv.notify_one(); m_worker.join(); } } @@ -304,20 +305,38 @@ void GLGizmoSimplify::live_preview() { void GLGizmoSimplify::process() { - class SimplifyCanceledException : public std::exception { - public: - const char* what() const throw() { return L("Model simplification has been canceled"); } - }; + if (m_volume == nullptr) return; + if (m_volume->mesh().its.indices.empty()) return; + size_t count_triangles = m_volume->mesh().its.indices.size(); + if (m_configuration.use_count && + m_configuration.wanted_count >= count_triangles) + return; - if (!m_original_its.has_value()) + // when not store original volume store it for cancelation + if (!m_original_its.has_value()) { m_original_its = m_volume->mesh().its; // copy - auto plater = wxGetApp().plater(); - plater->take_snapshot(_L("Simplify ") + m_volume->name); - plater->clear_before_change_mesh(m_obj_index); + // store previous state + auto plater = wxGetApp().plater(); + plater->take_snapshot(_L("Simplify ") + m_volume->name); + plater->clear_before_change_mesh(m_obj_index); + } + m_progress = 0; if (m_worker.joinable()) m_worker.join(); - m_worker = std::thread([this]() { + + m_worker = std::thread([this]() { + {// delay before process + std::unique_lock lk(m_state_mutex); + auto is_modify = [this]() { return m_state == State::canceling; }; + if (m_dealy_process_cv.wait_for(lk, m_gui_cfg->prcess_delay, is_modify)) { + // exist modification + m_state = State::settings; + request_rerender(); + return; + } + } + // store original triangles uint32_t triangle_count = (m_configuration.use_count) ? m_configuration.wanted_count : 0; float max_error = (!m_configuration.use_count) ? m_configuration.max_error : std::numeric_limits::max(); @@ -357,6 +376,7 @@ void GLGizmoSimplify::process() } void GLGizmoSimplify::set_its(indexed_triangle_set &its) { + if (m_volume == nullptr) return; // could appear after process m_volume->set_mesh(its); m_volume->calculate_convex_hull(); m_volume->set_new_unique_id(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp index b609c5cdd..793512344 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp @@ -7,6 +7,9 @@ #include "GLGizmoPainterBase.hpp" // for render wireframe #include "admesh/stl.h" // indexed_triangle_set #include +#include +#include +#include #include #include @@ -47,6 +50,7 @@ private: void set_its(indexed_triangle_set &its); void create_gui_cfg(); void request_rerender(); + // move to global functions static ModelVolume *get_volume(const Selection &selection, Model &model); static const ModelVolume *get_volume(const GLVolume::CompositeID &cid, const Model &model); @@ -62,10 +66,14 @@ private: size_t m_obj_index; std::optional m_original_its; - bool m_show_wireframe; + bool m_show_wireframe; volatile bool m_need_reload; // after simplify, glReload must be on main thread + std::thread m_worker; + // wait before process + std::mutex m_state_mutex; + std::condition_variable m_dealy_process_cv; enum class State { settings, @@ -87,8 +95,14 @@ private: void fix_count_by_ratio(size_t triangle_count) { - wanted_count = static_cast( - std::round(triangle_count * (100.f-decimate_ratio) / 100.f)); + if (decimate_ratio <= 0.f) { + wanted_count = static_cast(triangle_count); + return; + } else if (decimate_ratio >= 1.f) { + wanted_count = 0; + return; + } + wanted_count = static_cast(std::round(triangle_count * (100.f-decimate_ratio) / 100.f)); } } m_configuration; @@ -106,6 +120,10 @@ private: // trunc model name when longer size_t max_char_in_name = 30; + + // to prevent freezing when move in gui + // delay before process in [ms] + std::chrono::duration prcess_delay = std::chrono::milliseconds(250); }; std::optional m_gui_cfg; @@ -122,6 +140,16 @@ private: void free_gpu(); GLuint m_wireframe_VBO_id, m_wireframe_IBO_id; size_t m_wireframe_IBO_size; + + // cancel exception + class SimplifyCanceledException: public std::exception + { + public: + const char *what() const throw() + { + return L("Model simplification has been canceled"); + } + }; }; } // namespace GUI