diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index a625958992..46945b75f8 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1288,6 +1288,15 @@ void GLCanvas3D::on_change_color_mode(bool is_dark, bool reinit) { m_gizmos.set_icon_dirty(); } } + if (m_canvas_type == CanvasAssembleView) { + m_gizmos.on_change_color_mode(is_dark); + if (reinit) { + // reset svg + m_gizmos.switch_gizmos_icon_filename(); + // set dirty to re-generate icon texture + m_gizmos.set_icon_dirty(); + } + } } void GLCanvas3D::set_as_dirty() @@ -2369,9 +2378,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re deleted_wipe_towers.emplace_back(volume, volume_id); delete volume; } - - // BBS - m_explosion_ratio = 1.0; } else { // This GLVolume will be reused. @@ -3045,7 +3051,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) #else /* __APPLE__ */ case WXK_CONTROL_Y: #endif /* __APPLE__ */ - if (m_canvas_type == CanvasView3D) { + if (m_canvas_type == CanvasView3D || m_canvas_type == CanvasAssembleView) { post_event(SimpleEvent(EVT_GLCANVAS_REDO)); } break; @@ -3056,7 +3062,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt) case WXK_CONTROL_Z: #endif /* __APPLE__ */ // only support redu/undo in CanvasView3D - if (m_canvas_type == CanvasView3D) { + if (m_canvas_type == CanvasView3D || m_canvas_type == CanvasAssembleView) { post_event(SimpleEvent(EVT_GLCANVAS_UNDO)); } break; @@ -6229,7 +6235,7 @@ bool GLCanvas3D::_init_assemble_view_toolbar() item.tooltip = _utf8(L("Assembly View")); item.sprite_id = 1; item.left.toggable = false; - item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_ASSEMBLE)); }; + item.left.action_callback = [this]() { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_ASSEMBLE)); m_gizmos.reset_all_states(); wxGetApp().plater()->get_assmeble_canvas3D()->get_gizmos_manager().reset_all_states(); }; item.left.render_callback = GLToolbarItem::Default_Render_Callback; item.visible = true; item.visibility_callback = [this]()->bool { return true; }; @@ -6742,7 +6748,10 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with else { m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data()); } - m_volumes.set_show_sinking_contours(! m_gizmos.is_hiding_instances()); + if (m_canvas_type == CanvasAssembleView) + m_volumes.set_show_sinking_contours(false); + else + m_volumes.set_show_sinking_contours(!m_gizmos.is_hiding_instances()); GLShaderProgram* shader = wxGetApp().get_shader("gouraud"); ECanvasType canvas_type = this->m_canvas_type; @@ -7233,9 +7242,6 @@ void GLCanvas3D::_render_gizmos_overlay() const float size = int(GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale()); m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment #endif /* __WXMSW__ */ - if (m_canvas_type == CanvasAssembleView) - return; - m_gizmos.render_overlay(); if (m_gizmo_highlighter.m_render_arrow) @@ -7648,6 +7654,8 @@ void GLCanvas3D::_render_return_toolbar() const if (ImGui::ImageTextButton(real_size,_utf8(L("return")).c_str(), m_return_toolbar.get_return_texture_id(), button_icon_size, uv0, uv1, -1, bg_col, tint_col, margin)) { if (m_canvas != nullptr) wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_3D)); + const_cast(&m_gizmos)->reset_all_states(); + wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().reset_all_states(); } ImGui::PopStyleColor(5); ImGui::PopStyleVar(1); @@ -7849,6 +7857,7 @@ void GLCanvas3D::_render_paint_toolbar() const ImGui::BBLRenderArrow(draw_list, right_arrow_button.GetCenter() - ImVec2(draw_list->_Data->FontSize, draw_list->_Data->FontSize) * 0.5f, arrow_color, ImGuiDir_Right, 2.0f); } + m_paint_toolbar_width = (ImGui::GetWindowWidth() + 50.0f * em_unit * f_scale); imgui.end(); ImGui::PopStyleVar(3); ImGui::PopStyleColor(); @@ -7861,6 +7870,10 @@ void GLCanvas3D::_render_assemble_control() const GLVolume::explosion_ratio = m_explosion_ratio = 1.0; return; } + if (m_gizmos.get_current_type() == GLGizmosManager::EType::MmuSegmentation) { + m_gizmos.m_assemble_view_data->model_objects_clipper()->set_position(0.0, true); + return; + } ImGuiWrapper* imgui = wxGetApp().imgui(); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 2493627c1f..18fc75a953 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -520,6 +520,7 @@ private: mutable IMToolbar m_sel_plate_toolbar; mutable GLToolbar m_assemble_view_toolbar; mutable IMReturnToolbar m_return_toolbar; + mutable float m_paint_toolbar_width; //BBS: add canvas type for assemble view usage ECanvasType m_canvas_type; @@ -713,6 +714,7 @@ public: bool init(); void post_event(wxEvent &&event); + void reset_explosion_ratio() { m_explosion_ratio = 1.0; } void on_change_color_mode(bool is_dark, bool reinit = true); const bool get_dark_mode_status() { return m_is_dark; } void set_as_dirty(); @@ -819,6 +821,7 @@ public: float get_main_toolbar_width() { return m_main_toolbar.get_width();} float get_assemble_view_toolbar_width() { return m_assemble_view_toolbar.get_width(); } float get_assemble_view_toolbar_height() { return m_assemble_view_toolbar.get_height(); } + float get_assembly_paint_toolbar_width() { return m_paint_toolbar_width; } float get_separator_toolbar_width() { return m_separator_toolbar.get_width(); } float get_separator_toolbar_height() { return m_separator_toolbar.get_height(); } float get_collapse_toolbar_width(); diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index e5fa9cef20..1593624808 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1194,13 +1194,15 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me } } else if (col_num == colColorPaint) { - ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID(); - if (node->HasColorPainting()) { - GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager(); - if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::MmuSegmentation) - gizmos_mgr.open_gizmo(GLGizmosManager::EType::MmuSegmentation); - else - gizmos_mgr.reset_all_states(); + if (wxGetApp().plater()->get_current_canvas3D()->get_canvas_type() != GLCanvas3D::CanvasAssembleView) { + ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID(); + if (node->HasColorPainting()) { + GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager(); + if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::MmuSegmentation) + gizmos_mgr.open_gizmo(GLGizmosManager::EType::MmuSegmentation); + else + gizmos_mgr.reset_all_states(); + } } } else if (col_num == colSinking) { @@ -2775,6 +2777,9 @@ void ObjectList::merge(bool to_multipart_object) new_object->center_around_origin(); new_object->translate_instances(-new_object->origin_translation); new_object->origin_translation = Vec3d::Zero(); + //BBS init asssmble transformation + Geometry::Transformation t = new_object->instances[0]->get_transformation(); + new_object->instances[0]->set_assemble_transformation(t); //BBS: notify it before remove notify_instance_updated(m_objects->size() - 1); @@ -4457,12 +4462,12 @@ void ObjectList::update_selections() void ObjectList::update_selections_on_canvas() { - Selection& selection = wxGetApp().plater()->get_view3D_canvas3D()->get_selection(); + Selection& selection = wxGetApp().plater()->get_current_canvas3D()->get_selection(); const int sel_cnt = GetSelectedItemsCount(); if (sel_cnt == 0) { selection.remove_all(); - wxGetApp().plater()->get_view3D_canvas3D()->update_gizmos_on_off_state(); + wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state(); return; } @@ -4566,7 +4571,7 @@ void ObjectList::update_selections_on_canvas() selection.add_volumes(mode, volume_idxs, single_selection); } - wxGetApp().plater()->get_view3D_canvas3D()->update_gizmos_on_off_state(); + wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state(); wxGetApp().plater()->canvas3D()->render(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 03ff70761d..8ad89a9f2d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -212,7 +212,14 @@ void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const ++mesh_id; - const Transform3d trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * mv->get_matrix(); + Transform3d trafo_matrix; + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + trafo_matrix = mo->instances[selection.get_instance_idx()]->get_assemble_transformation().get_matrix() * mv->get_matrix(); + trafo_matrix.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mo->instances[selection.get_instance_idx()]->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0)); + } + else { + trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix()* mv->get_matrix(); + } bool is_left_handed = trafo_matrix.matrix().determinant() < 0.; if (is_left_handed) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 8d00510c9c..6b421b1531 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -85,10 +85,15 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const continue; ++mesh_id; - - const Transform3d trafo_matrix = - mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * - mv->get_matrix(); + + Transform3d trafo_matrix; + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + trafo_matrix = mo->instances[selection.get_instance_idx()]->get_assemble_transformation().get_matrix() * mv->get_matrix(); + trafo_matrix.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mo->instances[selection.get_instance_idx()]->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0)); + } + else { + trafo_matrix = mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix()* mv->get_matrix(); + } bool is_left_handed = trafo_matrix.matrix().determinant() < 0.; if (is_left_handed) @@ -124,7 +129,16 @@ void GLGizmoPainterBase::render_cursor() const std::vector trafo_matrices; for (const ModelVolume* mv : mo->volumes) { if (mv->is_model_part()) - trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix()); + { + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + Transform3d temp = mi->get_assemble_transformation().get_matrix() * mv->get_matrix(); + temp.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mi->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0)); + trafo_matrices.emplace_back(temp); + } + else { + trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix()); + } + } } // Raycast and return if there's no hit. update_raycast_cache(m_parent.get_local_mouse_position(), camera, trafo_matrices); @@ -230,17 +244,35 @@ void GLGizmoPainterBase::render_cursor_height_range(const Transform3d& trafo) co const BoundingBoxf3 box = bounding_box(); Vec3d hit_world = trafo * Vec3d(m_rr.hit(0), m_rr.hit(1), m_rr.hit(2)); float max_z = (float)box.max.z(); + float min_z = (float)box.min.z(); - float cursor_z = std::clamp((float)hit_world.z(), 0.f, max_z); - std::array zs = { cursor_z, std::clamp(cursor_z + m_cursor_height, 0.f, max_z) }; - for (int i = 0; i < zs.size(); i++) { - update_contours(zs[i], max_z); + float cursor_z = std::clamp((float)hit_world.z(), min_z, max_z); + std::array zs = { cursor_z, std::clamp(cursor_z + m_cursor_height, min_z, max_z) }; + + const Selection& selection = m_parent.get_selection(); + const ModelObject* model_object = wxGetApp().model().objects[selection.get_object_idx()]; + const ModelInstance* mi = model_object->instances[selection.get_instance_idx()]; + for (const ModelVolume* mv : model_object->volumes) { + TriangleMesh vol_mesh = mv->mesh(); + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + Transform3d temp = mi->get_assemble_transformation().get_matrix() * mv->get_matrix(); + temp.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mi->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0)); + vol_mesh.transform(temp); + } + else { + vol_mesh.transform(mi->get_transformation().get_matrix() * mv->get_matrix()); + } + + for (int i = 0; i < zs.size(); i++) { + update_contours(vol_mesh, zs[i], max_z, min_z); + + glsafe(::glPushMatrix()); + glsafe(::glTranslated(m_cut_contours.shift.x(), m_cut_contours.shift.y(), m_cut_contours.shift.z())); + glsafe(::glLineWidth(2.0f)); + m_cut_contours.contours.render(); + glsafe(::glPopMatrix()); + } - glsafe(::glPushMatrix()); - glsafe(::glTranslated(m_cut_contours.shift.x(), m_cut_contours.shift.y(), m_cut_contours.shift.z())); - glsafe(::glLineWidth(2.0f)); - m_cut_contours.contours.render(); - glsafe(::glPopMatrix()); } } @@ -257,7 +289,7 @@ BoundingBoxf3 GLGizmoPainterBase::bounding_box() const return ret; } -void GLGizmoPainterBase::update_contours(float cursor_z, float max_z) const +void GLGizmoPainterBase::update_contours(const TriangleMesh& vol_mesh, float cursor_z, float max_z, float min_z) const { const Selection& selection = m_parent.get_selection(); const GLVolume* first_glvolume = selection.get_volume(*selection.get_volume_idxs().begin()); @@ -266,33 +298,32 @@ void GLGizmoPainterBase::update_contours(float cursor_z, float max_z) const const ModelObject* model_object = wxGetApp().model().objects[selection.get_object_idx()]; const int instance_idx = selection.get_instance_idx(); - if (0.0 < cursor_z && cursor_z < max_z) { - if (m_cut_contours.cut_z != cursor_z || m_cut_contours.object_id != model_object->id() || m_cut_contours.instance_idx != instance_idx) { - m_cut_contours.cut_z = cursor_z; + if (min_z < cursor_z && cursor_z < max_z) { + if (m_cut_contours.cut_z != cursor_z || m_cut_contours.object_id != model_object->id() || m_cut_contours.instance_idx != instance_idx) { + m_cut_contours.cut_z = cursor_z; - if (m_cut_contours.object_id != model_object->id()) - m_cut_contours.mesh = model_object->raw_mesh(); + m_cut_contours.mesh = vol_mesh; - m_cut_contours.position = box.center(); - m_cut_contours.shift = Vec3d::Zero(); - m_cut_contours.object_id = model_object->id(); - m_cut_contours.instance_idx = instance_idx; - m_cut_contours.contours.reset(); + m_cut_contours.position = box.center(); + m_cut_contours.shift = Vec3d::Zero(); + m_cut_contours.object_id = model_object->id(); + m_cut_contours.instance_idx = instance_idx; + m_cut_contours.contours.reset(); - MeshSlicingParams slicing_params; - slicing_params.trafo = first_glvolume->get_instance_transformation().get_matrix(); - const Polygons polys = slice_mesh(m_cut_contours.mesh.its, cursor_z, slicing_params); - if (!polys.empty()) { - m_cut_contours.contours.init_from(polys, static_cast(cursor_z)); - m_cut_contours.contours.set_color(-1, { 1.0f, 1.0f, 1.0f, 1.0f }); + MeshSlicingParams slicing_params; + slicing_params.trafo = Transform3d::Identity().matrix(); + const Polygons polys = slice_mesh(m_cut_contours.mesh.its, cursor_z, slicing_params); + if (!polys.empty()) { + m_cut_contours.contours.init_from(polys, static_cast(cursor_z)); + m_cut_contours.contours.set_color(-1, { 1.0f, 1.0f, 1.0f, 1.0f }); + } + } + else if (box.center() != m_cut_contours.position) { + m_cut_contours.shift = box.center() - m_cut_contours.position; } } - else if (box.center() != m_cut_contours.position) { - m_cut_contours.shift = box.center() - m_cut_contours.position; - } - } - else - m_cut_contours.contours.reset(); + else + m_cut_contours.contours.reset(); } bool GLGizmoPainterBase::is_mesh_point_clipped(const Vec3d& point, const Transform3d& trafo) const @@ -451,8 +482,12 @@ std::vector GLGizmoPainterBase::get_pr const Selection& selection = m_parent.get_selection(); const ModelObject* mo = m_c->selection_info()->model_object(); const ModelInstance* mi = mo->instances[selection.get_instance_idx()]; - const Transform3d instance_trafo = mi->get_transformation().get_matrix(); - const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true); + const Transform3d instance_trafo = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ? + mi->get_assemble_transformation().get_matrix() : + mi->get_transformation().get_matrix(); + const Transform3d instance_trafo_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ? + mi->get_assemble_transformation().get_matrix(true) : + mi->get_transformation().get_matrix(true); for (int mesh_idx = 0; mesh_idx < part_volumes.size(); mesh_idx++) { if (mesh_idx == m_rr.mesh_id) @@ -518,8 +553,12 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous const Selection &selection = m_parent.get_selection(); const ModelObject *mo = m_c->selection_info()->model_object(); const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; - const Transform3d trafo_matrix_not_translate = mi->get_transformation().get_matrix(true) * mo->volumes[m_rr.mesh_id]->get_matrix(true); - const Transform3d trafo_matrix = mi->get_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix(); + const Transform3d trafo_matrix_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ? + mi->get_assemble_transformation().get_matrix(true) * mo->volumes[m_rr.mesh_id]->get_matrix(true) : + mi->get_transformation().get_matrix(true) * mo->volumes[m_rr.mesh_id]->get_matrix(true); + const Transform3d trafo_matrix = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ? + mi->get_assemble_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix() : + mi->get_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix(); m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), trafo_matrix_not_translate, this->get_clipping_plane_in_volume_coordinates(trafo_matrix), m_smart_fill_angle, m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f, true); m_triangle_selectors[m_rr.mesh_id]->request_update_render_data(); @@ -581,8 +620,12 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous const Selection &selection = m_parent.get_selection(); const ModelObject *mo = m_c->selection_info()->model_object(); const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; - const Transform3d instance_trafo = mi->get_transformation().get_matrix(); - const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true); + Transform3d instance_trafo = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ? + mi->get_assemble_transformation().get_matrix() : + mi->get_transformation().get_matrix(); + Transform3d instance_trafo_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ? + mi->get_assemble_transformation().get_matrix(true) : + mi->get_transformation().get_matrix(true); std::vector part_volumes; // Precalculate transformations of individual meshes. @@ -590,7 +633,14 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous std::vector trafo_matrices_not_translate; for (const ModelVolume *mv : mo->volumes) if (mv->is_model_part()) { - trafo_matrices.emplace_back(instance_trafo * mv->get_matrix()); + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + Transform3d temp = instance_trafo * mv->get_matrix(); + temp.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mi->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0)); + trafo_matrices.emplace_back(temp); + } + else { + trafo_matrices.emplace_back(instance_trafo* mv->get_matrix()); + } trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true)); part_volumes.push_back(mv); } @@ -713,15 +763,26 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous const Selection &selection = m_parent.get_selection(); const ModelObject *mo = m_c->selection_info()->model_object(); const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; - const Transform3d instance_trafo = mi->get_transformation().get_matrix(); - const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true); + const Transform3d instance_trafo = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ? + mi->get_assemble_transformation().get_matrix() : + mi->get_transformation().get_matrix(); + const Transform3d instance_trafo_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ? + mi->get_assemble_transformation().get_matrix(true) : + mi->get_transformation().get_matrix(true); // Precalculate transformations of individual meshes. std::vector trafo_matrices; std::vector trafo_matrices_not_translate; for (const ModelVolume *mv : mo->volumes) if (mv->is_model_part()) { - trafo_matrices.emplace_back(instance_trafo * mv->get_matrix()); + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + Transform3d temp = instance_trafo * mv->get_matrix(); + temp.translate(mv->get_transformation().get_offset() * (GLVolume::explosion_ratio - 1.0) + mi->get_offset_to_assembly() * (GLVolume::explosion_ratio - 1.0)); + trafo_matrices.emplace_back(temp); + } + else { + trafo_matrices.emplace_back(instance_trafo * mv->get_matrix()); + } trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true)); } @@ -811,7 +872,8 @@ void GLGizmoPainterBase::update_raycast_cache(const Vec2d& mouse_position, hit, normal, m_c->object_clipper()->get_clipping_plane(), - &facet)) + &facet, + m_parent.get_canvas_type() != GLCanvas3D::CanvasAssembleView)) { // In case this hit is clipped, skip it. if (is_mesh_point_clipped(hit.cast(), trafo_matrices[mesh_id])) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index aa4554413c..db56d58656 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -368,7 +368,7 @@ private: mutable CutContours m_cut_contours; BoundingBoxf3 bounding_box() const; - void update_contours(float cursor_z, float max_z) const; + void update_contours(const TriangleMesh& vol_mesh, float cursor_z, float max_z, float min_z) const; protected: void on_set_state() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index 524264cd3d..4e29d10afb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -145,6 +145,11 @@ void InstancesHider::on_update() const ModelObject* mo = get_pool()->selection_info()->model_object(); int active_inst = get_pool()->selection_info()->get_active_instance(); GLCanvas3D* canvas = get_pool()->get_canvas(); + double z_min; + if (canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView) + z_min = std::numeric_limits::max(); + else + z_min = -SINKING_Z_THRESHOLD; if (mo && active_inst != -1) { canvas->toggle_model_objects_visibility(false); @@ -152,7 +157,7 @@ void InstancesHider::on_update() canvas->toggle_sla_auxiliaries_visibility(m_show_supports, mo, active_inst); canvas->set_use_clipping_planes(true); // Some objects may be sinking, do not show whatever is below the bed. - canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD)); + canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), z_min)); canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), std::numeric_limits::max())); @@ -164,7 +169,7 @@ void InstancesHider::on_update() m_clippers.clear(); for (const TriangleMesh* mesh : meshes) { m_clippers.emplace_back(new MeshClipper); - m_clippers.back()->set_plane(ClippingPlane(-Vec3d::UnitZ(), -SINKING_Z_THRESHOLD)); + m_clippers.back()->set_plane(ClippingPlane(-Vec3d::UnitZ(), z_min)); m_clippers.back()->set_mesh(*mesh); } m_old_meshes = meshes; @@ -404,18 +409,30 @@ void ObjectClipper::render_cut() const return; const SelectionInfo* sel_info = get_pool()->selection_info(); const ModelObject* mo = sel_info->model_object(); - Geometry::Transformation inst_trafo = mo->instances[sel_info->get_active_instance()]->get_transformation(); + Geometry::Transformation inst_trafo; + bool is_assem_cnv = get_pool()->get_canvas()->get_canvas_type() == GLCanvas3D::CanvasAssembleView; + inst_trafo = is_assem_cnv ? + mo->instances[sel_info->get_active_instance()]->get_assemble_transformation() : + mo->instances[sel_info->get_active_instance()]->get_transformation(); + auto offset_to_assembly = mo->instances[0]->get_offset_to_assembly(); size_t clipper_id = 0; for (const ModelVolume* mv : mo->volumes) { Geometry::Transformation vol_trafo = mv->get_transformation(); Geometry::Transformation trafo = inst_trafo * vol_trafo; - trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift())); - + if (is_assem_cnv) { + trafo.set_offset(trafo.get_offset() + offset_to_assembly * (GLVolume::explosion_ratio - 1.0) + vol_trafo.get_offset() * (GLVolume::explosion_ratio - 1.0)); + } + else { + trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift())); + } auto& clipper = m_clippers[clipper_id]; clipper->set_plane(*m_clp); clipper->set_transformation(trafo); - clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD)); + if (is_assem_cnv) + clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), std::numeric_limits::max())); + else + clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD)); glsafe(::glPushMatrix()); // BBS glsafe(::glColor3f(0.25f, 0.25f, 0.25f)); @@ -438,14 +455,27 @@ void ObjectClipper::set_position(double pos, bool keep_normal) // camera_dir(2) = 0; Vec3d normal = (keep_normal && m_clp) ? m_clp->get_normal() : /*-camera_dir;*/ -wxGetApp().plater()->get_camera().get_dir_forward(); - const Vec3d& center = mo->instances[active_inst]->get_offset() + Vec3d(0., 0., z_shift); + Vec3d center; + + if (get_pool()->get_canvas()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + const SelectionInfo* sel_info = get_pool()->selection_info(); + auto trafo = mo->instances[sel_info->get_active_instance()]->get_assemble_transformation(); + auto offset_to_assembly = mo->instances[0]->get_offset_to_assembly(); + center = trafo.get_offset() + offset_to_assembly * (GLVolume::explosion_ratio - 1.0); + } + else { + center = mo->instances[active_inst]->get_offset() + Vec3d(0., 0., z_shift); + } + float dist = normal.dot(center); if (pos < 0.) pos = m_clp_ratio; m_clp_ratio = pos; - m_clp.reset(new ClippingPlane(normal, (dist - (-m_active_inst_bb_radius) - m_clp_ratio * 2*m_active_inst_bb_radius))); + + m_clp.reset(new ClippingPlane(normal, (dist - (-m_active_inst_bb_radius) - m_clp_ratio * 2 * m_active_inst_bb_radius))); + get_pool()->get_canvas()->set_as_dirty(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 7575d1dd7d..947895f09a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -54,9 +54,16 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent) std::vector GLGizmosManager::get_selectable_idxs() const { std::vector out; - for (size_t i=0; iis_selectable()) - out.push_back(i); + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + for (size_t i = 0; i < m_gizmos.size(); ++i) + if (m_gizmos[i]->get_sprite_id() == (unsigned int)MmuSegmentation) + out.push_back(i); + } + else { + for (size_t i = 0; i < m_gizmos.size(); ++i) + if (m_gizmos[i]->is_selectable()) + out.push_back(i); + } return out; } @@ -78,6 +85,8 @@ size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const #if BBS_TOOLBAR_ON_TOP //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();; float top_x = std::max(m_parent.get_main_toolbar_width() + border, 0.5f * (cnv_w - width + m_parent.get_main_toolbar_width() + m_parent.get_collapse_toolbar_width() - m_parent.get_assemble_view_toolbar_width()) + border); + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) + top_x = 0.5f * cnv_w + 0.5f * (m_parent.get_assembly_paint_toolbar_width()); float top_y = 0; float stride_x = m_layout.scaled_stride_x(); @@ -1372,17 +1381,23 @@ void GLGizmosManager::do_render_overlay() const float width = get_scaled_total_width(); float zoomed_border = m_layout.scaled_border() * inv_zoom; - //BBS: GUI refactor: GLToolbar&&Gizmo adjust + float zoomed_top_x; + if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + zoomed_top_x = 0.5f * m_parent.get_assembly_paint_toolbar_width() * inv_zoom; + } + else { + //BBS: GUI refactor: GLToolbar&&Gizmo adjust #if BBS_TOOLBAR_ON_TOP - float main_toolbar_width = (float)m_parent.get_main_toolbar_width(); - float assemble_view_width = (float)m_parent.get_assemble_view_toolbar_width(); - float collapse_width = (float)m_parent.get_collapse_toolbar_width(); - //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); - //float zoomed_top_x = 0.5f *(cnv_w + main_toolbar_width - 2 * space_width - width) * inv_zoom; + float main_toolbar_width = (float)m_parent.get_main_toolbar_width(); + float assemble_view_width = (float)m_parent.get_assemble_view_toolbar_width(); + float collapse_width = (float)m_parent.get_collapse_toolbar_width(); + //float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); + //float zoomed_top_x = 0.5f *(cnv_w + main_toolbar_width - 2 * space_width - width) * inv_zoom; - float main_toolbar_left = std::max(-0.5f * cnv_w, -0.5f * (main_toolbar_width + get_scaled_total_width() + assemble_view_width - collapse_width)) * inv_zoom; - //float zoomed_top_x = 0.5f *(main_toolbar_width + collapse_width - width - assemble_view_width) * inv_zoom; - float zoomed_top_x = main_toolbar_left + (main_toolbar_width) *inv_zoom; + float main_toolbar_left = std::max(-0.5f * cnv_w, -0.5f * (main_toolbar_width + get_scaled_total_width() + assemble_view_width - collapse_width)) * inv_zoom; + //float zoomed_top_x = 0.5f *(main_toolbar_width + collapse_width - width - assemble_view_width) * inv_zoom; + zoomed_top_x = main_toolbar_left + (main_toolbar_width)*inv_zoom; + } float zoomed_top_y = 0.5f * cnv_h * inv_zoom; #else //float zoomed_top_x = (-0.5f * cnv_w) * inv_zoom; diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index 6fd3a54b8e..0a7c8c58fd 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -241,7 +241,7 @@ void MeshRaycaster::line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3 bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera, Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane, - size_t* facet_idx) const + size_t* facet_idx, bool sinking_limit) const { Vec3d point; Vec3d direction; @@ -258,8 +258,8 @@ bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& // Also, remove anything below the bed (sinking objects). for (i=0; i= SINKING_Z_THRESHOLD && - (! clipping_plane || ! clipping_plane->is_point_clipped(transformed_hit))) + if (transformed_hit.z() >= sinking_limit ? SINKING_Z_THRESHOLD : -std::numeric_limits::max() && + (!clipping_plane || !clipping_plane->is_point_clipped(transformed_hit))) break; } diff --git a/src/slic3r/GUI/MeshUtils.hpp b/src/slic3r/GUI/MeshUtils.hpp index 02c597da3c..123b8a7852 100644 --- a/src/slic3r/GUI/MeshUtils.hpp +++ b/src/slic3r/GUI/MeshUtils.hpp @@ -150,7 +150,8 @@ public: Vec3f& position, // where to save the positibon of the hit (mesh coords) Vec3f& normal, // normal of the triangle that was hit const ClippingPlane* clipping_plane = nullptr, // clipping plane (if active) - size_t* facet_idx = nullptr // index of the facet hit + size_t* facet_idx = nullptr, // index of the facet hit + bool sinking_limit = true ) const; // Given a vector of points in woorld coordinates, this returns vector diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e0e9ef4218..3f66664322 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2481,6 +2481,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) assemble_canvas->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this); assemble_canvas->Bind(EVT_GLVIEWTOOLBAR_3D, [q](SimpleEvent&) { q->select_view_3D("3D"); }); assemble_canvas->Bind(EVT_GLCANVAS_RIGHT_CLICK, &priv::on_right_click, this); + assemble_canvas->Bind(EVT_GLCANVAS_UNDO, [this](SimpleEvent&) { this->undo(); }); + assemble_canvas->Bind(EVT_GLCANVAS_REDO, [this](SimpleEvent&) { this->redo(); }); } if (wxGetApp().is_editor()) { @@ -4158,6 +4160,7 @@ void Plater::priv::reset(bool apply_presets_change) // Stop and reset the Print content. this->background_process.reset(); model.clear_objects(); + assemble_view->get_canvas3d()->reset_explosion_ratio(); update(); //BBS @@ -7263,18 +7266,19 @@ void Plater::priv::take_snapshot(const std::string& snapshot_name, const UndoRed tower.rotation = proj_cfg.opt_float("wipe_tower_rotation_angle"); } } - const GLGizmosManager& gizmos = view3D->get_canvas3d()->get_gizmos_manager(); + const GLGizmosManager& gizmos = get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : view3D->get_canvas3d()->get_gizmos_manager(); if (snapshot_type == UndoRedo::SnapshotType::ProjectSeparator) this->undo_redo_stack().clear(); - this->undo_redo_stack().take_snapshot(snapshot_name, model, view3D->get_canvas3d()->get_selection(), view3D->get_canvas3d()->get_gizmos_manager(), partplate_list, snapshot_data); + this->undo_redo_stack().take_snapshot(snapshot_name, model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection() : view3D->get_canvas3d()->get_selection(), gizmos, partplate_list, snapshot_data); if (snapshot_type == UndoRedo::SnapshotType::LeavingGizmoWithAction) { // Filter all but the last UndoRedo::SnapshotType::GizmoAction in a row between the last UndoRedo::SnapshotType::EnteringGizmo and UndoRedo::SnapshotType::LeavingGizmoWithAction. // The remaining snapshot will be renamed to a more generic name, // depending on what gizmo is being left. - assert(gizmos.get_current() != nullptr); - std::string new_name = gizmos.get_current()->get_action_snapshot_name(); - this->undo_redo_stack().reduce_noisy_snapshots(new_name); + if (gizmos.get_current() != nullptr) { + std::string new_name = gizmos.get_current()->get_action_snapshot_name(); + this->undo_redo_stack().reduce_noisy_snapshots(new_name); + } } else if (snapshot_type == UndoRedo::SnapshotType::ProjectSeparator) { // Reset the "dirty project" flag. m_undo_redo_stack_main.mark_current_as_saved(); @@ -7296,6 +7300,13 @@ void Plater::priv::undo() // BBS: undo-redo until modify record while (--it_current != snapshots.begin() && !snapshot_modifies_project(*it_current)); if (it_current == snapshots.begin()) return; + if (get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView) { + if (it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::GizmoAction && + it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::EnteringGizmo && + it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::LeavingGizmoNoAction && + it_current->snapshot_data.snapshot_type != UndoRedo::SnapshotType::LeavingGizmoWithAction) + return; + } this->undo_redo_to(it_current); } @@ -7398,8 +7409,8 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator const UndoRedo::Snapshot snapshot_copy = *it_snapshot; // Do the jump in time. if (it_snapshot->timestamp < this->undo_redo_stack().active_snapshot_time() ? - this->undo_redo_stack().undo(model, this->view3D->get_canvas3d()->get_selection(), this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, top_snapshot_data, it_snapshot->timestamp) : - this->undo_redo_stack().redo(model, this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, it_snapshot->timestamp)) { + this->undo_redo_stack().undo(model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection() : this->view3D->get_canvas3d()->get_selection(), get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, top_snapshot_data, it_snapshot->timestamp) : + this->undo_redo_stack().redo(model, get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_gizmos_manager() : this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, it_snapshot->timestamp)) { if (printer_technology_changed) { // Switch to the other printer technology. Switch to the last printer active for that particular technology. AppConfig *app_config = wxGetApp().app_config; @@ -7476,7 +7487,7 @@ void Plater::priv::undo_redo_to(std::vector::const_iterator void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bool /* temp_snapshot_was_taken */) { - this->view3D->get_canvas3d()->get_selection().clear(); + get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? assemble_view->get_canvas3d()->get_selection().clear() : this->view3D->get_canvas3d()->get_selection().clear(); // Update volumes from the deserializd model, always stop / update the background processing (for both the SLA and FFF technologies). this->update((unsigned int)UpdateParams::FORCE_BACKGROUND_PROCESSING_UPDATE | (unsigned int)UpdateParams::POSTPONE_VALIDATION_ERROR_MESSAGE); // Release old snapshots if the memory allocated is excessive. This may remove the top most snapshot if jumping to the very first snapshot. @@ -7485,8 +7496,12 @@ void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bo // triangle meshes may have gotten released from the scene or the background processing, therefore now being calculated into the Undo / Redo stack size. this->undo_redo_stack().release_least_recently_used(); //YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time) - this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances); - this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot); + get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? + assemble_view->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances) : + this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances); + get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ? + assemble_view->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot) : + this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot); wxGetApp().obj_list()->update_after_undo_redo(); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index d2908035cf..c007703c7a 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -2712,9 +2712,14 @@ void Selection::paste_objects_from_clipboard() displacement = {empty_cell.x() + point_offset.x(), empty_cell.y() + point_offset.y(), start_offset(2)}; } - for (ModelInstance* inst : dst_object->instances) + for (ModelInstance* inst : dst_object->instances) { inst->set_offset(displacement); + //BBS init asssmble transformation + Geometry::Transformation t = inst->get_transformation(); + inst->set_assemble_transformation(t); + } + object_idxs.push_back(m_model->objects.size() - 1); #ifdef _DEBUG check_model_ids_validity(*m_model); diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp index 3351917b3c..56a5172ab3 100644 --- a/src/slic3r/Utils/UndoRedo.cpp +++ b/src/slic3r/Utils/UndoRedo.cpp @@ -479,10 +479,11 @@ public: assert(! m_history.empty()); auto it = std::lower_bound(m_history.begin(), m_history.end(), MutableHistoryInterval(timestamp, timestamp)); if (it == m_history.end() || it->begin() > timestamp) { - assert(it != m_history.begin()); - -- it; + //assert(it != m_history.begin()); + if (it != m_history.begin()) + --it; } - assert(timestamp >= it->begin() && timestamp < it->end()); + //assert(timestamp >= it->begin() && timestamp < it->end()); return std::string(it->data(), it->data() + it->size()); }