diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 6a15ab2a5..32529a9cd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -57,30 +57,32 @@ private: std::array m_varrays; }; +class GLGizmoTransparentRender +{ +public: + // Following function renders the triangles and cursor. Having this separated + // from usual on_render method allows to render them before transparent + // objects, so they can be seen inside them. The usual on_render is called + // after all volumes (including transparent ones) are rendered. + virtual void render_painter_gizmo() const = 0; +}; // Following class is a base class for a gizmo with ability to paint on mesh // using circular blush (such as FDM supports gizmo and seam painting gizmo). // The purpose is not to duplicate code related to mesh painting. -class GLGizmoPainterBase : public GLGizmoBase +class GLGizmoPainterBase : public GLGizmoTransparentRender, public GLGizmoBase { private: ObjectID m_old_mo_id; size_t m_old_volumes_size = 0; void on_render() override {} void on_render_for_picking() override {} - public: GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); ~GLGizmoPainterBase() override = default; virtual void set_painter_gizmo_data(const Selection& selection); virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); - // Following function renders the triangles and cursor. Having this separated - // from usual on_render method allows to render them before transparent objects, - // so they can be seen inside them. The usual on_render is called after all - // volumes (including transparent ones) are rendered. - virtual void render_painter_gizmo() const = 0; - protected: void render_triangles(const Selection& selection, const bool use_polygon_offset_fill = true) const; void render_cursor() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index 7ebbeec3a..c25f76c61 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -15,7 +15,7 @@ namespace Slic3r::GUI { GLGizmoSimplify::GLGizmoSimplify(GLCanvas3D & parent, const std::string &icon_filename, unsigned int sprite_id) - : GLGizmoPainterBase(parent, icon_filename, -1) + : GLGizmoBase(parent, icon_filename, -1) , m_state(State::settings) , m_is_valid_result(false) , m_exist_preview(false) @@ -29,6 +29,9 @@ GLGizmoSimplify::GLGizmoSimplify(GLCanvas3D & parent, , tr_preview(_u8L("Preview")) , tr_detail_level(_u8L("Detail level")) , tr_decimate_ratio(_u8L("Decimate ratio")) + + , m_wireframe_VBO_id(0) + , m_wireframe_IBO_id(0) {} GLGizmoSimplify::~GLGizmoSimplify() { @@ -51,15 +54,19 @@ std::string GLGizmoSimplify::on_get_name() const void GLGizmoSimplify::on_render() { } -void GLGizmoSimplify::on_render_for_picking() { } +void GLGizmoSimplify::on_render_for_picking() {} void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limit) { create_gui_cfg(); int obj_index; ModelVolume *act_volume = get_selected_volume(&obj_index); - if (act_volume == nullptr) { - close(); + if (act_volume == nullptr) { + switch (m_state) { + case State::settings: close(); break; + case State::canceling: break; + default: m_state = State::canceling; + } return; } @@ -79,6 +86,7 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi m_configuration.fix_count_by_ratio(m_volume->mesh().its.indices.size()); m_is_valid_result = false; m_exist_preview = false; + init_wireframe(m_volume->mesh().its); if (change_window_position) { ImVec2 pos = ImGui::GetMousePos(); @@ -240,7 +248,7 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi // set m_state must be before close() !!! m_state = State::settings; if (close_on_end) after_apply(); - + else init_wireframe(m_volume->mesh().its); // Fix warning icon in object list wxGetApp().obj_list()->update_item_error_icon(m_obj_index, -1); } @@ -317,7 +325,6 @@ void GLGizmoSimplify::process() } void GLGizmoSimplify::set_its(indexed_triangle_set &its) { - //init_contours(its); m_volume->set_mesh(its); m_volume->calculate_convex_hull(); m_volume->set_new_unique_id(); @@ -334,10 +341,18 @@ void GLGizmoSimplify::on_set_state() { // Closing gizmo. e.g. selecting another one if (GLGizmoBase::m_state == GLGizmoBase::Off) { - bool exist_selected_object = is_selected_object(); + // can appear when delete objects + bool empty_selection = m_parent.get_selection().is_empty(); + + // cancel processing + if (empty_selection && + m_state != State::settings && + m_state != State::canceling) + m_state = State::canceling; + // refuse outgoing during simlification // object is not selected when it is deleted(cancel and close gizmo) - if (m_state != State::settings && exist_selected_object) { + if (m_state != State::settings && !empty_selection) { GLGizmoBase::m_state = GLGizmoBase::On; auto notification_manager = wxGetApp().plater()->get_notification_manager(); notification_manager->push_notification( @@ -348,10 +363,13 @@ void GLGizmoSimplify::on_set_state() } // revert preview - if (m_exist_preview && exist_selected_object) { - set_its(*m_original_its); - m_parent.reload_scene(true); - m_need_reload = false; + if (m_exist_preview) { + m_exist_preview = false; + if (exist_volume(m_volume)) { + set_its(*m_original_its); + m_parent.reload_scene(false); + m_need_reload = false; + } } // invalidate selected model @@ -389,20 +407,27 @@ void GLGizmoSimplify::request_rerender() { }); } -bool GLGizmoSimplify::is_selected_object(int *object_idx) -{ - int index = (object_idx != nullptr) ? *object_idx : - m_parent.get_selection().get_object_idx(); - // no selected object --> can appear after delete model - if (index < 0) { - switch (m_state) { - case State::settings: close(); break; - case State::canceling: break; - default: m_state = State::canceling; - } - return false; +bool GLGizmoSimplify::exist_volume(ModelVolume *volume) { + auto objs = wxGetApp().plater()->model().objects; + for (const auto &obj : objs) { + const auto &vlms = obj->volumes; + auto item = std::find(vlms.begin(), vlms.end(), volume); + if (item != vlms.end()) return true; } - return true; + return false; +} + +ModelVolume *GLGizmoSimplify::get_selected_volume(int *object_idx_ptr) const +{ + const Selection &selection = m_parent.get_selection(); + int object_idx = selection.get_object_idx(); + if (object_idx_ptr != nullptr) *object_idx_ptr = object_idx; + if (object_idx < 0) return nullptr; + ModelObjectPtrs &objs = wxGetApp().plater()->model().objects; + if (objs.size() <= object_idx) return nullptr; + ModelObject *obj = objs[object_idx]; + if (obj->volumes.empty()) return nullptr; + return obj->volumes.front(); } void GLGizmoSimplify::init_wireframe(const indexed_triangle_set &its) @@ -436,21 +461,16 @@ void GLGizmoSimplify::init_wireframe(const indexed_triangle_set &its) glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } -void GLGizmoSimplify::render_wireframe() +void GLGizmoSimplify::render_wireframe() const { - const Selection &selection = m_parent.get_selection(); - int object_idx = selection.get_object_idx(); - if (!is_selected_object(&object_idx)) return; - - const GLVolume* vol = selection.get_volume(*selection.get_instance_idxs().begin()); - GLuint vbo_id = vol->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id; - ModelObject *obj = wxGetApp().plater()->model().objects[object_idx]; - ModelVolume *act_volume = obj->volumes.front(); - - init_wireframe(act_volume->mesh().its); + // is initialized? + if (m_wireframe_VBO_id == 0 || m_wireframe_IBO_id == 0) return; + ModelVolume *act_volume = get_selected_volume(); + if (act_volume == nullptr) return; const Transform3d trafo_matrix = - obj->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * + act_volume->get_object()->instances[m_parent.get_selection().get_instance_idx()] + ->get_transformation().get_matrix() * act_volume->get_matrix(); glsafe(::glPushMatrix()); @@ -461,14 +481,8 @@ void GLGizmoSimplify::render_wireframe() glsafe(::glDepthFunc(GL_LEQUAL)); glsafe(::glLineWidth(1.0f)); - /* - // bad indices - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, vbo_id)); - glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float)))); - /*/ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_wireframe_VBO_id)); glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr)); - //*/ glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_wireframe_IBO_id)); @@ -497,17 +511,4 @@ void GLGizmoSimplify::free_gpu() } } -ModelVolume *GLGizmoSimplify::get_selected_volume(int *object_idx_ptr) -{ - const Selection &selection = m_parent.get_selection(); - int object_idx = selection.get_object_idx(); - if (object_idx_ptr != nullptr) *object_idx_ptr = object_idx; - if (!is_selected_object(&object_idx)) return nullptr; - ModelObjectPtrs &objs = wxGetApp().plater()->model().objects; - if (objs.size() <= object_idx) return nullptr; - ModelObject *obj = objs[object_idx]; - if (obj->volumes.empty()) return nullptr; - return obj->volumes.front(); -} - } // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp index 6d9e99e4b..097e2bfd3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp @@ -19,7 +19,7 @@ class ModelVolume; namespace GUI { -class GLGizmoSimplify : public GLGizmoPainterBase // GLGizmoBase +class GLGizmoSimplify: public GLGizmoBase, public GLGizmoTransparentRender // GLGizmoBase { public: GLGizmoSimplify(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); @@ -35,7 +35,7 @@ protected: virtual void on_set_state() override; // GLGizmoPainterBase - virtual void render_painter_gizmo() const override{ const_cast(this)->render_wireframe(); } + virtual void render_painter_gizmo() const override{ render_wireframe(); } private: void after_apply(); void close(); @@ -43,8 +43,10 @@ private: void set_its(indexed_triangle_set &its); void create_gui_cfg(); void request_rerender(); - bool is_selected_object(int *object_idx_ptr = nullptr); - ModelVolume *get_selected_volume(int *object_idx = nullptr); + ModelVolume *get_selected_volume(int *object_idx = nullptr) const; + + // return false when volume was deleted + static bool exist_volume(ModelVolume *volume); std::atomic_bool m_is_valid_result; // differ what to do in apply std::atomic_bool m_exist_preview; // set when process end @@ -108,7 +110,7 @@ private: const std::string tr_decimate_ratio; // rendering wireframe - void render_wireframe(); + void render_wireframe() const; void init_wireframe(const indexed_triangle_set &its); void free_gpu(); GLuint m_wireframe_VBO_id, m_wireframe_IBO_id; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 7a9373a5f..ceb16b3be 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -52,8 +52,6 @@ std::vector GLGizmosManager::get_selectable_idxs() const return out; } - - size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const { if (! m_enabled) @@ -485,7 +483,7 @@ void GLGizmosManager::render_painter_gizmo() const if (!m_enabled || m_current == Undefined) return; - auto* gizmo = dynamic_cast(get_current()); + auto *gizmo = dynamic_cast(get_current()); assert(gizmo); // check the precondition gizmo->render_painter_gizmo(); }