* Suppress to split cut objects
* ObjectList:
  * Use another icons to mark the cut objects and connectors 
  * For the cut object show parts, which are not connectors
* Set different colors for the Plugs and Dowels
* CutGizmo:
  * Invalidate CutGizmo after changes in ObjectList or perform a cut
  * CupPlane in Connectors mode: Unselect selection, when click on empty space
  * Connectors mode: Fixed performance issue
This commit is contained in:
YuSanka 2022-09-27 13:54:44 +02:00
parent e689be65db
commit 0201a5055a
10 changed files with 123 additions and 45 deletions

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
<g id="add_x5F_part">
<g>
<path fill="#ED6B21" d="M14.62,4.37c-0.01-0.14,0.06-0.34,0.15-0.44l0.13-0.15c0.09-0.11,0.12-0.3,0.07-0.43l-0.2-0.49
c-0.05-0.13-0.21-0.24-0.35-0.25l-0.2-0.01c-0.14-0.01-0.33-0.1-0.42-0.21c-0.09-0.1-0.37-0.46-0.38-0.6l-0.01-0.2
c-0.01-0.14-0.12-0.3-0.25-0.35l-0.49-0.2C12.52,0.97,12.33,1,12.22,1.1l-0.15,0.13c-0.11,0.09-0.31,0.16-0.44,0.15
c-0.14-0.01-0.59-0.06-0.69-0.15L10.78,1.1c-0.11-0.09-0.3-0.12-0.43-0.07l-0.49,0.2C9.73,1.28,9.61,1.44,9.6,1.58l-0.01,0.2
C9.58,1.92,9.49,2.11,9.38,2.2c-0.1,0.09-0.46,0.37-0.6,0.38L8.58,2.6c-0.14,0.01-0.3,0.12-0.35,0.25l-0.2,0.49
C7.97,3.48,8,3.67,8.1,3.78l0.13,0.15c0.09,0.11,0.16,0.31,0.15,0.44C8.37,4.52,8.32,4.96,8.23,5.07L8.1,5.22
C8,5.33,7.97,5.52,8.03,5.65l0.2,0.49C8.28,6.27,8.44,6.39,8.58,6.4l0.2,0.01c0.14,0.01,0.33,0.1,0.42,0.21
c0.09,0.1,0.37,0.46,0.38,0.6l0.01,0.2c0.01,0.14,0.12,0.3,0.25,0.35l0.49,0.2C10.48,8.03,10.67,8,10.78,7.9l0.15-0.13
c0.11-0.09,0.31-0.16,0.44-0.15c0.14,0.01,0.59,0.06,0.69,0.15l0.15,0.13c0.11,0.09,0.3,0.12,0.43,0.07l0.49-0.2
c0.13-0.05,0.24-0.21,0.25-0.35l0.01-0.2c0.01-0.14,0.1-0.33,0.21-0.42s0.46-0.37,0.6-0.38l0.2-0.01c0.14-0.01,0.3-0.12,0.35-0.25
l0.2-0.49C15.03,5.52,15,5.33,14.9,5.22l-0.13-0.15C14.68,4.96,14.63,4.51,14.62,4.37z M11.5,6.6c-1.16,0-2.1-0.94-2.1-2.1
s0.94-2.1,2.1-2.1s2.1,0.94,2.1,2.1S12.66,6.6,11.5,6.6z"/>
</g>
<path fill="#808080" d="M10.98,9.78c-0.29,0-0.52,0.23-0.52,0.52v2.09v1.04c0,0.29-0.23,0.52-0.52,0.52H2.62
c-0.29,0-0.53-0.24-0.53-0.53L2.04,6.12c0-0.14,0.05-0.27,0.15-0.37c0.1-0.1,0.23-0.15,0.37-0.15l3.19,0v0
c0.29,0,0.52-0.23,0.52-0.52S6.04,4.55,5.75,4.55H3.66c-0.01,0-0.01,0-0.02,0l-1.08,0c-0.42,0-0.81,0.16-1.11,0.46
C1.16,5.31,1,5.71,1,6.13l0.04,7.31C1.05,14.3,1.75,15,2.62,15h7.31c0.86,0,1.57-0.7,1.57-1.57v-1.04V10.3
C11.5,10.01,11.27,9.78,10.98,9.78z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1191,11 +1191,21 @@ size_t ModelObject::parts_count() const
return num; return num;
} }
bool ModelObject::has_connectors() const
{
assert(is_cut());
for (const ModelVolume* v : this->volumes)
if (v->cut_info.is_connector)
return true;
return false;
}
indexed_triangle_set ModelObject::get_connector_mesh(CutConnectorAttributes connector_attributes) indexed_triangle_set ModelObject::get_connector_mesh(CutConnectorAttributes connector_attributes)
{ {
indexed_triangle_set connector_mesh; indexed_triangle_set connector_mesh;
int sectorCount; int sectorCount {1};
switch (CutConnectorShape(connector_attributes.shape)) { switch (CutConnectorShape(connector_attributes.shape)) {
case CutConnectorShape::Triangle: case CutConnectorShape::Triangle:
sectorCount = 3; sectorCount = 3;
@ -1238,7 +1248,7 @@ void ModelObject::apply_cut_connectors(const std::string& new_name)
new_volume->set_transformation(assemble_transform(connector.pos) * connector.rotation_m * new_volume->set_transformation(assemble_transform(connector.pos) * connector.rotation_m *
scale_transform(Vec3f(connector.radius, connector.radius, connector.height).cast<double>())); scale_transform(Vec3f(connector.radius, connector.radius, connector.height).cast<double>()));
new_volume->cut_info = { true, connector.attribs.type, connector.radius_tolerance, connector.height_tolerance }; new_volume->cut_info = { connector.attribs.type, connector.radius_tolerance, connector.height_tolerance };
new_volume->name = new_name + "-" + std::to_string(++connector_id); new_volume->name = new_name + "-" + std::to_string(++connector_id);
} }
cut_id.increase_connectors_cnt(cut_connectors.size()); cut_id.increase_connectors_cnt(cut_connectors.size());
@ -1298,7 +1308,8 @@ void ModelVolume::reset_extra_facets()
void ModelVolume::apply_tolerance() void ModelVolume::apply_tolerance()
{ {
if (!cut_info.is_connector) assert(cut_info.is_connector);
if (cut_info.is_processed)
return; return;
Vec3d sf = get_scaling_factor(); Vec3d sf = get_scaling_factor();
@ -1321,7 +1332,8 @@ void ModelVolume::apply_tolerance()
void ModelObject::process_connector_cut(ModelVolume* volume, ModelObjectCutAttributes attributes, ModelObject* upper, ModelObject* lower, void ModelObject::process_connector_cut(ModelVolume* volume, ModelObjectCutAttributes attributes, ModelObject* upper, ModelObject* lower,
std::vector<ModelObject*>& dowels, Vec3d& local_dowels_displace) std::vector<ModelObject*>& dowels, Vec3d& local_dowels_displace)
{ {
volume->cut_info.discard(); assert(volume->cut_info.is_connector);
volume->cut_info.set_processed();
const auto volume_matrix = volume->get_matrix(); const auto volume_matrix = volume->get_matrix();
@ -1546,10 +1558,10 @@ ModelObjectPtrs ModelObject::cut(size_t instance, const Transform3d& cut_matrix,
volume->reset_extra_facets(); volume->reset_extra_facets();
if (!volume->is_model_part()) { if (!volume->is_model_part()) {
if (volume->cut_info.is_connector) if (volume->cut_info.is_processed)
process_connector_cut(volume, attributes, upper, lower, dowels, local_dowels_displace);
else
process_modifier_cut(volume, instance_matrix, inverse_cut_matrix, attributes, upper, lower); process_modifier_cut(volume, instance_matrix, inverse_cut_matrix, attributes, upper, lower);
else
process_connector_cut(volume, attributes, upper, lower, dowels, local_dowels_displace);
} }
else if (!volume->mesh().empty()) else if (!volume->mesh().empty())
process_solid_part_cut(volume, instance_matrix, cut_matrix, attributes, upper, lower, local_displace); process_solid_part_cut(volume, instance_matrix, cut_matrix, attributes, upper, lower, local_displace);

View File

@ -477,6 +477,7 @@ public:
int get_repaired_errors_count(const int vol_idx = -1) const; int get_repaired_errors_count(const int vol_idx = -1) const;
bool is_cut() const { return cut_id.id().valid(); } bool is_cut() const { return cut_id.id().valid(); }
bool has_connectors() const;
private: private:
friend class Model; friend class Model;
@ -723,14 +724,26 @@ public:
struct CutInfo struct CutInfo
{ {
bool is_connector{ false }; bool is_connector{ false };
bool is_processed{ true };
CutConnectorType connector_type{ CutConnectorType::Plug }; CutConnectorType connector_type{ CutConnectorType::Plug };
float radius_tolerance;// [0.f : 1.f] float radius_tolerance{ 0.f };// [0.f : 1.f]
float height_tolerance;// [0.f : 1.f] float height_tolerance{ 0.f };// [0.f : 1.f]
void discard() { is_connector = false; } CutInfo() = default;
CutInfo(CutConnectorType type, float rad_tolerance, float h_tolerance) :
is_connector(true),
is_processed(false),
connector_type(type),
radius_tolerance(rad_tolerance),
height_tolerance(h_tolerance)
{}
void set_processed() { is_processed = true; }
}; };
CutInfo cut_info; CutInfo cut_info;
bool is_cut_connector() const { return cut_info.is_processed && cut_info.is_connector; }
// The triangular model. // The triangular model.
const TriangleMesh& mesh() const { return *m_mesh.get(); } const TriangleMesh& mesh() const { return *m_mesh.get(); }
#if ENABLE_RAYCAST_PICKING #if ENABLE_RAYCAST_PICKING

View File

@ -1881,13 +1881,8 @@ void ObjectList::del_info_item(const int obj_idx, InfoItemType type)
mv->seam_facets.reset(); mv->seam_facets.reset();
break; break;
case InfoItemType::Cut: case InfoItemType::CutConnectors:
if (0) { // #ysFIXME_Cut show_error(nullptr, _L("Connectors cannot be deleted from cut object."));
cnv->get_gizmos_manager().reset_all_states();
Plater::TakeSnapshot(plater, _L("Remove cut connectors"));
(*m_objects)[obj_idx]->cut_connectors.clear();
} else
Slic3r::GUI::show_error(nullptr, _L("Connectors cannot be deleted from cut object."));
break; break;
case InfoItemType::MmuSegmentation: case InfoItemType::MmuSegmentation:
@ -2422,9 +2417,12 @@ bool ObjectList::is_splittable(bool to_objects)
auto obj_idx = get_selected_obj_idx(); auto obj_idx = get_selected_obj_idx();
if (obj_idx < 0) if (obj_idx < 0)
return false; return false;
if ((*m_objects)[obj_idx]->volumes.size() > 1) const ModelObject* object = (*m_objects)[obj_idx];
if (object->is_cut())
return false;
if (object->volumes.size() > 1)
return true; return true;
return (*m_objects)[obj_idx]->volumes[0]->is_splittable(); return object->volumes[0]->is_splittable();
} }
return false; return false;
} }
@ -2595,19 +2593,13 @@ void ObjectList::part_selection_changed()
} }
case InfoItemType::CustomSupports: case InfoItemType::CustomSupports:
case InfoItemType::CustomSeam: case InfoItemType::CustomSeam:
// case InfoItemType::Cut:
case InfoItemType::MmuSegmentation: case InfoItemType::MmuSegmentation:
{ {
GLGizmosManager::EType gizmo_type = info_type == InfoItemType::CustomSupports ? GLGizmosManager::EType::FdmSupports : GLGizmosManager::EType gizmo_type = info_type == InfoItemType::CustomSupports ? GLGizmosManager::EType::FdmSupports :
info_type == InfoItemType::CustomSeam ? GLGizmosManager::EType::Seam : info_type == InfoItemType::CustomSeam ? GLGizmosManager::EType::Seam :
info_type == InfoItemType::Cut ? GLGizmosManager::EType::Cut :
GLGizmosManager::EType::MmuSegmentation; GLGizmosManager::EType::MmuSegmentation;
if (gizmos_mgr.get_current_type() != gizmo_type) if (gizmos_mgr.get_current_type() != gizmo_type)
gizmos_mgr.open_gizmo(gizmo_type); gizmos_mgr.open_gizmo(gizmo_type);
if (info_type == InfoItemType::Cut) {
GLGizmoCut3D* cut = dynamic_cast<GLGizmoCut3D*>(gizmos_mgr.get_current());
cut->set_connectors_editing();
}
break; break;
} }
case InfoItemType::Sinking: { break; } case InfoItemType::Sinking: { break; }
@ -2762,7 +2754,7 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
for (InfoItemType type : {InfoItemType::CustomSupports, for (InfoItemType type : {InfoItemType::CustomSupports,
InfoItemType::CustomSeam, InfoItemType::CustomSeam,
InfoItemType::Cut, InfoItemType::CutConnectors,
InfoItemType::MmuSegmentation, InfoItemType::MmuSegmentation,
InfoItemType::Sinking, InfoItemType::Sinking,
InfoItemType::VariableLayerHeight}) { InfoItemType::VariableLayerHeight}) {
@ -2783,11 +2775,8 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
}); });
break; break;
case InfoItemType::Cut : case InfoItemType::CutConnectors:
if (0) // #ysFIXME_Cut should_show = model_object->is_cut() && model_object->has_connectors() && model_object->volumes.size() > 1;
should_show = !model_object->cut_connectors.empty();
else
should_show = model_object->is_cut() && model_object->volumes.size() > 1;
break; break;
case InfoItemType::VariableLayerHeight : case InfoItemType::VariableLayerHeight :
should_show = printer_technology() == ptFFF should_show = printer_technology() == ptFFF
@ -2841,9 +2830,20 @@ void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed)
update_info_items(obj_idx, nullptr, call_selection_changed); update_info_items(obj_idx, nullptr, call_selection_changed);
bool can_add_volumes = model_object->volumes.size() > 1;
if (can_add_volumes && model_object->is_cut()) {
int no_connectors_cnt = 0;
for (const ModelVolume* v : model_object->volumes)
if (!v->is_cut_connector())
no_connectors_cnt++;
can_add_volumes = no_connectors_cnt > 1;
}
// add volumes to the object // add volumes to the object
if (model_object->volumes.size() > 1 && !model_object->is_cut()) { if (can_add_volumes) {
for (const ModelVolume* volume : model_object->volumes) { for (const ModelVolume* volume : model_object->volumes) {
if (model_object->is_cut() && volume->is_cut_connector())
continue;
const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(item, const wxDataViewItem& vol_item = m_objects_model->AddVolumeChild(item,
from_u8(volume->name), from_u8(volume->name),
volume->type(), volume->type(),

View File

@ -18,9 +18,17 @@
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
static const double Margin = 20.0;
static const ColorRGBA GRABBER_COLOR = ColorRGBA::YELLOW(); static const ColorRGBA GRABBER_COLOR = ColorRGBA::YELLOW();
// connector colors
static const ColorRGBA PLAG_COLOR = ColorRGBA::YELLOW();
static const ColorRGBA DOWEL_COLOR = ColorRGBA::DARK_YELLOW();
static const ColorRGBA HOVERED_PLAG_COLOR = ColorRGBA::CYAN();
static const ColorRGBA HOVERED_DOWEL_COLOR = ColorRGBA(0.0f, 0.5f, 0.5f, 1.0f);
static const ColorRGBA SELECTED_PLAG_COLOR = ColorRGBA::GRAY();
static const ColorRGBA SELECTED_DOWEL_COLOR = ColorRGBA::DARK_GRAY();
static const ColorRGBA CONNECTOR_DEF_COLOR = ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f);
const unsigned int AngleResolution = 64; const unsigned int AngleResolution = 64;
const unsigned int ScaleStepsCount = 72; const unsigned int ScaleStepsCount = 72;
const float ScaleStepRad = 2.0f * float(PI) / ScaleStepsCount; const float ScaleStepRad = 2.0f * float(PI) / ScaleStepsCount;
@ -1426,8 +1434,6 @@ void GLGizmoCut3D::render_connectors_input_window(CutConnectors &connectors)
unselect_all_connectors(); unselect_all_connectors();
set_connectors_editing(false); set_connectors_editing(false);
} }
m_parent.request_extra_frame();
} }
void GLGizmoCut3D::render_build_size() void GLGizmoCut3D::render_build_size()
@ -1455,10 +1461,22 @@ void GLGizmoCut3D::reset_cut_plane()
update_clipper(); update_clipper();
} }
void GLGizmoCut3D::invalidate_cut_plane()
{
m_rotation_m = Transform3d::Identity();
m_plane_center = Vec3d::Zero();
m_min_pos = Vec3d::Zero();
m_max_pos = Vec3d::Zero();
m_bb_center = Vec3d::Zero();
m_center_offset = Vec3d::Zero();
}
void GLGizmoCut3D::set_connectors_editing(bool connectors_editing) void GLGizmoCut3D::set_connectors_editing(bool connectors_editing)
{ {
m_connectors_editing = connectors_editing; m_connectors_editing = connectors_editing;
update_raycasters_for_picking(); update_raycasters_for_picking();
m_parent.request_extra_frame();
} }
void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors) void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
@ -1661,13 +1679,14 @@ void GLGizmoCut3D::render_connectors()
pos[Z] += sla_shift; pos[Z] += sla_shift;
// First decide about the color of the point. // First decide about the color of the point.
if (size_t(m_hover_id- m_connectors_group_id) == i) if (!m_connectors_editing)
render_color = ColorRGBA::CYAN(); render_color = CONNECTOR_DEF_COLOR;
else if (size_t(m_hover_id - m_connectors_group_id) == i)
render_color = connector.attribs.type == CutConnectorType::Dowel ? HOVERED_DOWEL_COLOR : HOVERED_PLAG_COLOR;
else if (m_selected[i]) else if (m_selected[i])
render_color = ColorRGBA::DARK_GRAY(); render_color = connector.attribs.type == CutConnectorType::Dowel ? SELECTED_DOWEL_COLOR : SELECTED_PLAG_COLOR;
else // neither hover nor picking else // neither hover nor picking
render_color = m_connectors_editing ? ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f) : ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f); render_color = connector.attribs.type == CutConnectorType::Dowel ? DOWEL_COLOR : PLAG_COLOR;
// ! #ysFIXME rework get_volume_transformation // ! #ysFIXME rework get_volume_transformation
if (0) { // else { // neither hover nor picking if (0) { // else { // neither hover nor picking
int mesh_id = -1; int mesh_id = -1;
@ -1773,6 +1792,8 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
else { else {
// the object is SLA-elevated and the plane is under it. // the object is SLA-elevated and the plane is under it.
} }
invalidate_cut_plane();
} }
@ -2005,7 +2026,8 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
if (action == SLAGizmoEventType::LeftDown && !shift_down) { if (action == SLAGizmoEventType::LeftDown && !shift_down) {
// If there is no selection and no hovering, add new point // If there is no selection and no hovering, add new point
if (m_hover_id == -1 && !control_down && !alt_down) if (m_hover_id == -1 && !control_down && !alt_down)
return add_connector(connectors, mouse_position); if (!add_connector(connectors, mouse_position))
unselect_all_connectors();
return true; return true;
} }
if (!m_connectors_editing) if (!m_connectors_editing)

View File

@ -149,6 +149,7 @@ public:
void update_clipper(); void update_clipper();
void update_clipper_on_render(); void update_clipper_on_render();
void set_connectors_editing() { m_connectors_editing = true; } void set_connectors_editing() { m_connectors_editing = true; }
void invalidate_cut_plane();
BoundingBoxf3 bounding_box() const; BoundingBoxf3 bounding_box() const;
BoundingBoxf3 transformed_bounding_box(bool revert_move = false) const; BoundingBoxf3 transformed_bounding_box(bool revert_move = false) const;

View File

@ -1228,7 +1228,7 @@ void NotificationManager::UpdatedItemsInfoNotification::add_type(InfoItemType ty
case InfoItemType::MmuSegmentation: text += format(_L_PLURAL("%1$d object was loaded with multimaterial painting.", "%1$d objects were loaded with multimaterial painting.",(*it).second), (*it).second) + "\n"; break; case InfoItemType::MmuSegmentation: text += format(_L_PLURAL("%1$d object was loaded with multimaterial painting.", "%1$d objects were loaded with multimaterial painting.",(*it).second), (*it).second) + "\n"; break;
case InfoItemType::VariableLayerHeight: text += format(_L_PLURAL("%1$d object was loaded with variable layer height.", "%1$d objects were loaded with variable layer height.", (*it).second), (*it).second) + "\n"; break; case InfoItemType::VariableLayerHeight: text += format(_L_PLURAL("%1$d object was loaded with variable layer height.", "%1$d objects were loaded with variable layer height.", (*it).second), (*it).second) + "\n"; break;
case InfoItemType::Sinking: text += format(_L_PLURAL("%1$d object was loaded with partial sinking.", "%1$d objects were loaded with partial sinking.", (*it).second), (*it).second) + "\n"; break; case InfoItemType::Sinking: text += format(_L_PLURAL("%1$d object was loaded with partial sinking.", "%1$d objects were loaded with partial sinking.", (*it).second), (*it).second) + "\n"; break;
case InfoItemType::Cut: text += format(_L_PLURAL("%1$d object was loaded as a part of cut object.", "%1$d objects were loaded as parts of cut object", (*it).second), (*it).second) + "\n"; break; case InfoItemType::CutConnectors: text += format(_L_PLURAL("%1$d object was loaded as a part of cut object.", "%1$d objects were loaded as parts of cut object", (*it).second), (*it).second) + "\n"; break;
default: BOOST_LOG_TRIVIAL(error) << "Unknown InfoItemType: " << (*it).second; break; default: BOOST_LOG_TRIVIAL(error) << "Unknown InfoItemType: " << (*it).second; break;
} }
} }

View File

@ -38,7 +38,7 @@ static constexpr char LayerRootIcon[] = "edit_layers_all";
static constexpr char LayerIcon[] = "edit_layers_some"; static constexpr char LayerIcon[] = "edit_layers_some";
static constexpr char WarningIcon[] = "exclamation"; static constexpr char WarningIcon[] = "exclamation";
static constexpr char WarningManifoldIcon[] = "exclamation_manifold"; static constexpr char WarningManifoldIcon[] = "exclamation_manifold";
static constexpr char LockIcon[] = "lock_closed"; static constexpr char LockIcon[] = "cut_";
struct InfoItemAtributes { struct InfoItemAtributes {
std::string name; std::string name;
@ -49,7 +49,7 @@ const std::map<InfoItemType, InfoItemAtributes> INFO_ITEMS{
// info_item Type info_item Name info_item BitmapName // info_item Type info_item Name info_item BitmapName
{ InfoItemType::CustomSupports, {L("Paint-on supports"), "fdm_supports_" }, }, { InfoItemType::CustomSupports, {L("Paint-on supports"), "fdm_supports_" }, },
{ InfoItemType::CustomSeam, {L("Paint-on seam"), "seam_" }, }, { InfoItemType::CustomSeam, {L("Paint-on seam"), "seam_" }, },
{ InfoItemType::Cut, {L("Cut connectors"), "cut_" }, }, { InfoItemType::CutConnectors, {L("Cut connectors"), "cut_connectors" }, },
{ InfoItemType::MmuSegmentation, {L("Multimaterial painting"), "mmu_segmentation_"}, }, { InfoItemType::MmuSegmentation, {L("Multimaterial painting"), "mmu_segmentation_"}, },
{ InfoItemType::Sinking, {L("Sinking"), "sinking"}, }, { InfoItemType::Sinking, {L("Sinking"), "sinking"}, },
{ InfoItemType::VariableLayerHeight, {L("Variable layer height"), "layers"}, }, { InfoItemType::VariableLayerHeight, {L("Variable layer height"), "layers"}, },

View File

@ -51,7 +51,7 @@ enum class InfoItemType
Undef, Undef,
CustomSupports, CustomSupports,
CustomSeam, CustomSeam,
Cut, CutConnectors,
MmuSegmentation, MmuSegmentation,
Sinking, Sinking,
VariableLayerHeight VariableLayerHeight

View File

@ -97,6 +97,7 @@
#include "MsgDialog.hpp" #include "MsgDialog.hpp"
#include "ProjectDirtyStateManager.hpp" #include "ProjectDirtyStateManager.hpp"
#include "Gizmos/GLGizmoSimplify.hpp" // create suggestion notification #include "Gizmos/GLGizmoSimplify.hpp" // create suggestion notification
#include "Gizmos/GLGizmoCut.hpp"
#ifdef __APPLE__ #ifdef __APPLE__
#include "Gizmos/GLGizmosManager.hpp" #include "Gizmos/GLGizmosManager.hpp"
@ -2980,6 +2981,9 @@ void Plater::priv::object_list_changed()
const bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() == ModelInstancePVS_Inside; const bool model_fits = view3D->get_canvas3d()->check_volumes_outside_state() == ModelInstancePVS_Inside;
sidebar->enable_buttons(!model.objects.empty() && !export_in_progress && model_fits); sidebar->enable_buttons(!model.objects.empty() && !export_in_progress && model_fits);
// invalidate CutGizmo after changes in ObjectList
static_cast<GLGizmoCut3D*>(q->canvas3D()->get_gizmos_manager().get_gizmo(GLGizmosManager::Cut))->invalidate_cut_plane();
} }
void Plater::priv::select_all() void Plater::priv::select_all()