NEW:add paint tool in assembly view

Change-Id: I108e1e24ca9d033d2279c8153585166971a347a6
This commit is contained in:
liz.li 2023-04-14 11:58:39 +08:00 committed by Lane.Wei
parent 5236f17792
commit ab0c6611c8
13 changed files with 265 additions and 108 deletions

View file

@ -1288,6 +1288,15 @@ void GLCanvas3D::on_change_color_mode(bool is_dark, bool reinit) {
m_gizmos.set_icon_dirty(); 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() 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); deleted_wipe_towers.emplace_back(volume, volume_id);
delete volume; delete volume;
} }
// BBS
m_explosion_ratio = 1.0;
} }
else { else {
// This GLVolume will be reused. // This GLVolume will be reused.
@ -3045,7 +3051,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
#else /* __APPLE__ */ #else /* __APPLE__ */
case WXK_CONTROL_Y: case WXK_CONTROL_Y:
#endif /* __APPLE__ */ #endif /* __APPLE__ */
if (m_canvas_type == CanvasView3D) { if (m_canvas_type == CanvasView3D || m_canvas_type == CanvasAssembleView) {
post_event(SimpleEvent(EVT_GLCANVAS_REDO)); post_event(SimpleEvent(EVT_GLCANVAS_REDO));
} }
break; break;
@ -3056,7 +3062,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
case WXK_CONTROL_Z: case WXK_CONTROL_Z:
#endif /* __APPLE__ */ #endif /* __APPLE__ */
// only support redu/undo in CanvasView3D // 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)); post_event(SimpleEvent(EVT_GLCANVAS_UNDO));
} }
break; break;
@ -6229,7 +6235,7 @@ bool GLCanvas3D::_init_assemble_view_toolbar()
item.tooltip = _utf8(L("Assembly View")); item.tooltip = _utf8(L("Assembly View"));
item.sprite_id = 1; item.sprite_id = 1;
item.left.toggable = false; 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.left.render_callback = GLToolbarItem::Default_Render_Callback;
item.visible = true; item.visible = true;
item.visibility_callback = [this]()->bool { return true; }; item.visibility_callback = [this]()->bool { return true; };
@ -6742,7 +6748,10 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with
else { else {
m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data()); 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"); GLShaderProgram* shader = wxGetApp().get_shader("gouraud");
ECanvasType canvas_type = this->m_canvas_type; 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()); const float size = int(GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale());
m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment m_gizmos.set_overlay_icon_size(size); //! #ys_FIXME_experiment
#endif /* __WXMSW__ */ #endif /* __WXMSW__ */
if (m_canvas_type == CanvasAssembleView)
return;
m_gizmos.render_overlay(); m_gizmos.render_overlay();
if (m_gizmo_highlighter.m_render_arrow) 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 (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) if (m_canvas != nullptr)
wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_3D)); wxPostEvent(m_canvas, SimpleEvent(EVT_GLVIEWTOOLBAR_3D));
const_cast<GLGizmosManager*>(&m_gizmos)->reset_all_states();
wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager().reset_all_states();
} }
ImGui::PopStyleColor(5); ImGui::PopStyleColor(5);
ImGui::PopStyleVar(1); 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); 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.end();
ImGui::PopStyleVar(3); ImGui::PopStyleVar(3);
ImGui::PopStyleColor(); ImGui::PopStyleColor();
@ -7861,6 +7870,10 @@ void GLCanvas3D::_render_assemble_control() const
GLVolume::explosion_ratio = m_explosion_ratio = 1.0; GLVolume::explosion_ratio = m_explosion_ratio = 1.0;
return; 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(); ImGuiWrapper* imgui = wxGetApp().imgui();

View file

@ -520,6 +520,7 @@ private:
mutable IMToolbar m_sel_plate_toolbar; mutable IMToolbar m_sel_plate_toolbar;
mutable GLToolbar m_assemble_view_toolbar; mutable GLToolbar m_assemble_view_toolbar;
mutable IMReturnToolbar m_return_toolbar; mutable IMReturnToolbar m_return_toolbar;
mutable float m_paint_toolbar_width;
//BBS: add canvas type for assemble view usage //BBS: add canvas type for assemble view usage
ECanvasType m_canvas_type; ECanvasType m_canvas_type;
@ -713,6 +714,7 @@ public:
bool init(); bool init();
void post_event(wxEvent &&event); 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); void on_change_color_mode(bool is_dark, bool reinit = true);
const bool get_dark_mode_status() { return m_is_dark; } const bool get_dark_mode_status() { return m_is_dark; }
void set_as_dirty(); void set_as_dirty();
@ -819,6 +821,7 @@ public:
float get_main_toolbar_width() { return m_main_toolbar.get_width();} 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_width() { return m_assemble_view_toolbar.get_width(); }
float get_assemble_view_toolbar_height() { return m_assemble_view_toolbar.get_height(); } 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_width() { return m_separator_toolbar.get_width(); }
float get_separator_toolbar_height() { return m_separator_toolbar.get_height(); } float get_separator_toolbar_height() { return m_separator_toolbar.get_height(); }
float get_collapse_toolbar_width(); float get_collapse_toolbar_width();

View file

@ -1194,13 +1194,15 @@ void ObjectList::list_manipulation(const wxPoint& mouse_pos, bool evt_context_me
} }
} }
else if (col_num == colColorPaint) { else if (col_num == colColorPaint) {
ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID(); if (wxGetApp().plater()->get_current_canvas3D()->get_canvas_type() != GLCanvas3D::CanvasAssembleView) {
if (node->HasColorPainting()) { ObjectDataViewModelNode* node = (ObjectDataViewModelNode*)item.GetID();
GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager(); if (node->HasColorPainting()) {
if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::MmuSegmentation) GLGizmosManager& gizmos_mgr = wxGetApp().plater()->get_view3D_canvas3D()->get_gizmos_manager();
gizmos_mgr.open_gizmo(GLGizmosManager::EType::MmuSegmentation); if (gizmos_mgr.get_current_type() != GLGizmosManager::EType::MmuSegmentation)
else gizmos_mgr.open_gizmo(GLGizmosManager::EType::MmuSegmentation);
gizmos_mgr.reset_all_states(); else
gizmos_mgr.reset_all_states();
}
} }
} }
else if (col_num == colSinking) { else if (col_num == colSinking) {
@ -2775,6 +2777,9 @@ void ObjectList::merge(bool to_multipart_object)
new_object->center_around_origin(); new_object->center_around_origin();
new_object->translate_instances(-new_object->origin_translation); new_object->translate_instances(-new_object->origin_translation);
new_object->origin_translation = Vec3d::Zero(); 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 //BBS: notify it before remove
notify_instance_updated(m_objects->size() - 1); notify_instance_updated(m_objects->size() - 1);
@ -4457,12 +4462,12 @@ void ObjectList::update_selections()
void ObjectList::update_selections_on_canvas() 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(); const int sel_cnt = GetSelectedItemsCount();
if (sel_cnt == 0) { if (sel_cnt == 0) {
selection.remove_all(); selection.remove_all();
wxGetApp().plater()->get_view3D_canvas3D()->update_gizmos_on_off_state(); wxGetApp().plater()->get_current_canvas3D()->update_gizmos_on_off_state();
return; return;
} }
@ -4566,7 +4571,7 @@ void ObjectList::update_selections_on_canvas()
selection.add_volumes(mode, volume_idxs, single_selection); 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(); wxGetApp().plater()->canvas3D()->render();
} }

View file

@ -212,7 +212,14 @@ void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const
++mesh_id; ++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.; bool is_left_handed = trafo_matrix.matrix().determinant() < 0.;
if (is_left_handed) if (is_left_handed)

View file

@ -85,10 +85,15 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection) const
continue; continue;
++mesh_id; ++mesh_id;
const Transform3d trafo_matrix = Transform3d trafo_matrix;
mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
mv->get_matrix(); 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.; bool is_left_handed = trafo_matrix.matrix().determinant() < 0.;
if (is_left_handed) if (is_left_handed)
@ -124,7 +129,16 @@ void GLGizmoPainterBase::render_cursor() const
std::vector<Transform3d> trafo_matrices; std::vector<Transform3d> trafo_matrices;
for (const ModelVolume* mv : mo->volumes) { for (const ModelVolume* mv : mo->volumes) {
if (mv->is_model_part()) 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. // Raycast and return if there's no hit.
update_raycast_cache(m_parent.get_local_mouse_position(), camera, trafo_matrices); 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(); const BoundingBoxf3 box = bounding_box();
Vec3d hit_world = trafo * Vec3d(m_rr.hit(0), m_rr.hit(1), m_rr.hit(2)); 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 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); float cursor_z = std::clamp((float)hit_world.z(), min_z, max_z);
std::array<float, 2> zs = { cursor_z, std::clamp(cursor_z + m_cursor_height, 0.f, max_z) }; std::array<float, 2> zs = { cursor_z, std::clamp(cursor_z + m_cursor_height, min_z, max_z) };
for (int i = 0; i < zs.size(); i++) {
update_contours(zs[i], 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; 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 Selection& selection = m_parent.get_selection();
const GLVolume* first_glvolume = selection.get_volume(*selection.get_volume_idxs().begin()); 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 ModelObject* model_object = wxGetApp().model().objects[selection.get_object_idx()];
const int instance_idx = selection.get_instance_idx(); const int instance_idx = selection.get_instance_idx();
if (0.0 < cursor_z && cursor_z < max_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) { 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; m_cut_contours.cut_z = cursor_z;
if (m_cut_contours.object_id != model_object->id()) m_cut_contours.mesh = vol_mesh;
m_cut_contours.mesh = model_object->raw_mesh();
m_cut_contours.position = box.center(); m_cut_contours.position = box.center();
m_cut_contours.shift = Vec3d::Zero(); m_cut_contours.shift = Vec3d::Zero();
m_cut_contours.object_id = model_object->id(); m_cut_contours.object_id = model_object->id();
m_cut_contours.instance_idx = instance_idx; m_cut_contours.instance_idx = instance_idx;
m_cut_contours.contours.reset(); m_cut_contours.contours.reset();
MeshSlicingParams slicing_params; MeshSlicingParams slicing_params;
slicing_params.trafo = first_glvolume->get_instance_transformation().get_matrix(); slicing_params.trafo = Transform3d::Identity().matrix();
const Polygons polys = slice_mesh(m_cut_contours.mesh.its, cursor_z, slicing_params); const Polygons polys = slice_mesh(m_cut_contours.mesh.its, cursor_z, slicing_params);
if (!polys.empty()) { if (!polys.empty()) {
m_cut_contours.contours.init_from(polys, static_cast<float>(cursor_z)); m_cut_contours.contours.init_from(polys, static_cast<float>(cursor_z));
m_cut_contours.contours.set_color(-1, { 1.0f, 1.0f, 1.0f, 1.0f }); 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) { else
m_cut_contours.shift = box.center() - m_cut_contours.position; m_cut_contours.contours.reset();
}
}
else
m_cut_contours.contours.reset();
} }
bool GLGizmoPainterBase::is_mesh_point_clipped(const Vec3d& point, const Transform3d& trafo) const bool GLGizmoPainterBase::is_mesh_point_clipped(const Vec3d& point, const Transform3d& trafo) const
@ -451,8 +482,12 @@ std::vector<GLGizmoPainterBase::ProjectedHeightRange> GLGizmoPainterBase::get_pr
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
const ModelObject* mo = m_c->selection_info()->model_object(); const ModelObject* mo = m_c->selection_info()->model_object();
const ModelInstance* mi = mo->instances[selection.get_instance_idx()]; const ModelInstance* mi = mo->instances[selection.get_instance_idx()];
const Transform3d instance_trafo = mi->get_transformation().get_matrix(); const Transform3d instance_trafo = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true); 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++) { for (int mesh_idx = 0; mesh_idx < part_volumes.size(); mesh_idx++) {
if (mesh_idx == m_rr.mesh_id) 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 Selection &selection = m_parent.get_selection();
const ModelObject *mo = m_c->selection_info()->model_object(); const ModelObject *mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; 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_not_translate = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
const Transform3d trafo_matrix = mi->get_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix(); 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_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_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f, true);
m_triangle_selectors[m_rr.mesh_id]->request_update_render_data(); 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 Selection &selection = m_parent.get_selection();
const ModelObject *mo = m_c->selection_info()->model_object(); const ModelObject *mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
const Transform3d instance_trafo = mi->get_transformation().get_matrix(); Transform3d instance_trafo = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true); 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<const ModelVolume*> part_volumes; std::vector<const ModelVolume*> part_volumes;
// Precalculate transformations of individual meshes. // Precalculate transformations of individual meshes.
@ -590,7 +633,14 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
std::vector<Transform3d> trafo_matrices_not_translate; std::vector<Transform3d> trafo_matrices_not_translate;
for (const ModelVolume *mv : mo->volumes) for (const ModelVolume *mv : mo->volumes)
if (mv->is_model_part()) { 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)); trafo_matrices_not_translate.emplace_back(instance_trafo_not_translate * mv->get_matrix(true));
part_volumes.push_back(mv); 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 Selection &selection = m_parent.get_selection();
const ModelObject *mo = m_c->selection_info()->model_object(); const ModelObject *mo = m_c->selection_info()->model_object();
const ModelInstance *mi = mo->instances[selection.get_instance_idx()]; const ModelInstance *mi = mo->instances[selection.get_instance_idx()];
const Transform3d instance_trafo = mi->get_transformation().get_matrix(); const Transform3d instance_trafo = m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
const Transform3d instance_trafo_not_translate = mi->get_transformation().get_matrix(true); 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. // Precalculate transformations of individual meshes.
std::vector<Transform3d> trafo_matrices; std::vector<Transform3d> trafo_matrices;
std::vector<Transform3d> trafo_matrices_not_translate; std::vector<Transform3d> trafo_matrices_not_translate;
for (const ModelVolume *mv : mo->volumes) for (const ModelVolume *mv : mo->volumes)
if (mv->is_model_part()) { 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)); 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, hit,
normal, normal,
m_c->object_clipper()->get_clipping_plane(), m_c->object_clipper()->get_clipping_plane(),
&facet)) &facet,
m_parent.get_canvas_type() != GLCanvas3D::CanvasAssembleView))
{ {
// In case this hit is clipped, skip it. // In case this hit is clipped, skip it.
if (is_mesh_point_clipped(hit.cast<double>(), trafo_matrices[mesh_id])) if (is_mesh_point_clipped(hit.cast<double>(), trafo_matrices[mesh_id]))

View file

@ -368,7 +368,7 @@ private:
mutable CutContours m_cut_contours; mutable CutContours m_cut_contours;
BoundingBoxf3 bounding_box() const; 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: protected:
void on_set_state() override; void on_set_state() override;

View file

@ -145,6 +145,11 @@ void InstancesHider::on_update()
const ModelObject* mo = get_pool()->selection_info()->model_object(); const ModelObject* mo = get_pool()->selection_info()->model_object();
int active_inst = get_pool()->selection_info()->get_active_instance(); int active_inst = get_pool()->selection_info()->get_active_instance();
GLCanvas3D* canvas = get_pool()->get_canvas(); GLCanvas3D* canvas = get_pool()->get_canvas();
double z_min;
if (canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView)
z_min = std::numeric_limits<double>::max();
else
z_min = -SINKING_Z_THRESHOLD;
if (mo && active_inst != -1) { if (mo && active_inst != -1) {
canvas->toggle_model_objects_visibility(false); 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->toggle_sla_auxiliaries_visibility(m_show_supports, mo, active_inst);
canvas->set_use_clipping_planes(true); canvas->set_use_clipping_planes(true);
// Some objects may be sinking, do not show whatever is below the bed. // 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<double>::max())); canvas->set_clipping_plane(1, ClippingPlane(-Vec3d::UnitZ(), std::numeric_limits<double>::max()));
@ -164,7 +169,7 @@ void InstancesHider::on_update()
m_clippers.clear(); m_clippers.clear();
for (const TriangleMesh* mesh : meshes) { for (const TriangleMesh* mesh : meshes) {
m_clippers.emplace_back(new MeshClipper); 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_clippers.back()->set_mesh(*mesh);
} }
m_old_meshes = meshes; m_old_meshes = meshes;
@ -404,18 +409,30 @@ void ObjectClipper::render_cut() const
return; return;
const SelectionInfo* sel_info = get_pool()->selection_info(); const SelectionInfo* sel_info = get_pool()->selection_info();
const ModelObject* mo = sel_info->model_object(); 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; size_t clipper_id = 0;
for (const ModelVolume* mv : mo->volumes) { for (const ModelVolume* mv : mo->volumes) {
Geometry::Transformation vol_trafo = mv->get_transformation(); Geometry::Transformation vol_trafo = mv->get_transformation();
Geometry::Transformation trafo = inst_trafo * vol_trafo; 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]; auto& clipper = m_clippers[clipper_id];
clipper->set_plane(*m_clp); clipper->set_plane(*m_clp);
clipper->set_transformation(trafo); 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<double>::max()));
else
clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
// BBS // BBS
glsafe(::glColor3f(0.25f, 0.25f, 0.25f)); 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; // camera_dir(2) = 0;
Vec3d normal = (keep_normal && m_clp) ? m_clp->get_normal() : /*-camera_dir;*/ -wxGetApp().plater()->get_camera().get_dir_forward(); 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); float dist = normal.dot(center);
if (pos < 0.) if (pos < 0.)
pos = m_clp_ratio; pos = m_clp_ratio;
m_clp_ratio = pos; 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(); get_pool()->get_canvas()->set_as_dirty();
} }

View file

@ -54,9 +54,16 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent)
std::vector<size_t> GLGizmosManager::get_selectable_idxs() const std::vector<size_t> GLGizmosManager::get_selectable_idxs() const
{ {
std::vector<size_t> out; std::vector<size_t> out;
for (size_t i=0; i<m_gizmos.size(); ++i) if (m_parent.get_canvas_type() == GLCanvas3D::CanvasAssembleView) {
if (m_gizmos[i]->is_selectable()) for (size_t i = 0; i < m_gizmos.size(); ++i)
out.push_back(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; return out;
} }
@ -78,6 +85,8 @@ size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const
#if BBS_TOOLBAR_ON_TOP #if BBS_TOOLBAR_ON_TOP
//float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale();; //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); 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 top_y = 0;
float stride_x = m_layout.scaled_stride_x(); 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 width = get_scaled_total_width();
float zoomed_border = m_layout.scaled_border() * inv_zoom; 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 #if BBS_TOOLBAR_ON_TOP
float main_toolbar_width = (float)m_parent.get_main_toolbar_width(); float main_toolbar_width = (float)m_parent.get_main_toolbar_width();
float assemble_view_width = (float)m_parent.get_assemble_view_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 collapse_width = (float)m_parent.get_collapse_toolbar_width();
//float space_width = GLGizmosManager::Default_Icons_Size * wxGetApp().toolbar_icon_scale(); //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 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 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 = 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; zoomed_top_x = main_toolbar_left + (main_toolbar_width)*inv_zoom;
}
float zoomed_top_y = 0.5f * cnv_h * inv_zoom; float zoomed_top_y = 0.5f * cnv_h * inv_zoom;
#else #else
//float zoomed_top_x = (-0.5f * cnv_w) * inv_zoom; //float zoomed_top_x = (-0.5f * cnv_w) * inv_zoom;

View file

@ -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, bool MeshRaycaster::unproject_on_mesh(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane, Vec3f& position, Vec3f& normal, const ClippingPlane* clipping_plane,
size_t* facet_idx) const size_t* facet_idx, bool sinking_limit) const
{ {
Vec3d point; Vec3d point;
Vec3d direction; 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). // Also, remove anything below the bed (sinking objects).
for (i=0; i<hits.size(); ++i) { for (i=0; i<hits.size(); ++i) {
Vec3d transformed_hit = trafo * hits[i].position(); Vec3d transformed_hit = trafo * hits[i].position();
if (transformed_hit.z() >= SINKING_Z_THRESHOLD && if (transformed_hit.z() >= sinking_limit ? SINKING_Z_THRESHOLD : -std::numeric_limits<double>::max() &&
(! clipping_plane || ! clipping_plane->is_point_clipped(transformed_hit))) (!clipping_plane || !clipping_plane->is_point_clipped(transformed_hit)))
break; break;
} }

View file

@ -150,7 +150,8 @@ public:
Vec3f& position, // where to save the positibon of the hit (mesh coords) Vec3f& position, // where to save the positibon of the hit (mesh coords)
Vec3f& normal, // normal of the triangle that was hit Vec3f& normal, // normal of the triangle that was hit
const ClippingPlane* clipping_plane = nullptr, // clipping plane (if active) 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; ) const;
// Given a vector of points in woorld coordinates, this returns vector // Given a vector of points in woorld coordinates, this returns vector

View file

@ -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_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_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_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()) { if (wxGetApp().is_editor()) {
@ -4158,6 +4160,7 @@ void Plater::priv::reset(bool apply_presets_change)
// Stop and reset the Print content. // Stop and reset the Print content.
this->background_process.reset(); this->background_process.reset();
model.clear_objects(); model.clear_objects();
assemble_view->get_canvas3d()->reset_explosion_ratio();
update(); update();
//BBS //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"); 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) if (snapshot_type == UndoRedo::SnapshotType::ProjectSeparator)
this->undo_redo_stack().clear(); 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) { 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. // 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, // The remaining snapshot will be renamed to a more generic name,
// depending on what gizmo is being left. // depending on what gizmo is being left.
assert(gizmos.get_current() != nullptr); if (gizmos.get_current() != nullptr) {
std::string new_name = gizmos.get_current()->get_action_snapshot_name(); std::string new_name = gizmos.get_current()->get_action_snapshot_name();
this->undo_redo_stack().reduce_noisy_snapshots(new_name); this->undo_redo_stack().reduce_noisy_snapshots(new_name);
}
} else if (snapshot_type == UndoRedo::SnapshotType::ProjectSeparator) { } else if (snapshot_type == UndoRedo::SnapshotType::ProjectSeparator) {
// Reset the "dirty project" flag. // Reset the "dirty project" flag.
m_undo_redo_stack_main.mark_current_as_saved(); m_undo_redo_stack_main.mark_current_as_saved();
@ -7296,6 +7300,13 @@ void Plater::priv::undo()
// BBS: undo-redo until modify record // BBS: undo-redo until modify record
while (--it_current != snapshots.begin() && !snapshot_modifies_project(*it_current)); while (--it_current != snapshots.begin() && !snapshot_modifies_project(*it_current));
if (it_current == snapshots.begin()) return; 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); this->undo_redo_to(it_current);
} }
@ -7398,8 +7409,8 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
const UndoRedo::Snapshot snapshot_copy = *it_snapshot; const UndoRedo::Snapshot snapshot_copy = *it_snapshot;
// Do the jump in time. // Do the jump in time.
if (it_snapshot->timestamp < this->undo_redo_stack().active_snapshot_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().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, this->view3D->get_canvas3d()->get_gizmos_manager(), this->partplate_list, 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) { if (printer_technology_changed) {
// Switch to the other printer technology. Switch to the last printer active for that particular technology. // Switch to the other printer technology. Switch to the last printer active for that particular technology.
AppConfig *app_config = wxGetApp().app_config; AppConfig *app_config = wxGetApp().app_config;
@ -7476,7 +7487,7 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bool /* temp_snapshot_was_taken */) 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). // 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); 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. // 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. // 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(); 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) //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); get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot); 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(); wxGetApp().obj_list()->update_after_undo_redo();

View file

@ -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)}; 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); 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); object_idxs.push_back(m_model->objects.size() - 1);
#ifdef _DEBUG #ifdef _DEBUG
check_model_ids_validity(*m_model); check_model_ids_validity(*m_model);

View file

@ -479,10 +479,11 @@ public:
assert(! m_history.empty()); assert(! m_history.empty());
auto it = std::lower_bound(m_history.begin(), m_history.end(), MutableHistoryInterval(timestamp, timestamp)); auto it = std::lower_bound(m_history.begin(), m_history.end(), MutableHistoryInterval(timestamp, timestamp));
if (it == m_history.end() || it->begin() > timestamp) { if (it == m_history.end() || it->begin() > timestamp) {
assert(it != m_history.begin()); //assert(it != m_history.begin());
-- it; 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()); return std::string(it->data(), it->data() + it->size());
} }