mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-24 04:54:29 +08:00
SPE-2486: Add a new gizmo for fuzzy skin painting.
This commit is contained in:
parent
859a9cf308
commit
886faac74e
6
resources/icons/fuzzy_skin_painting.svg
Normal file
6
resources/icons/fuzzy_skin_painting.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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"
|
||||
width="128px" height="128px" viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<path fill="#ED6B21" d="m 88,38.93 c -0.83,0 -1.5,0.67 -1.5,1.5 V 70.5 h -5 V 45.14 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 V 70.5 h -5 V 49.8 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 v 20.7 h -5 V 53.84 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 V 70.5 h -5 V 49.8 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 v 20.7 h -5 V 45.14 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 V 70.5 h -5 V 40.43 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 V 72 82.99 c 0,3.59 2.92,6.51 6.51,6.51 h 2.98 c 0.67,0.01 6.51,0.24 6.51,6.5 v 16 c 0,3.29 1.99,9.5 9.5,9.5 7.51,0 9.5,-6.21 9.5,-9.5 V 96 c 0,-6.26 5.84,-6.49 6.5,-6.5 h 3 c 3.59,0 6.5,-2.92 6.5,-6.5 V 72 40.43 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 z M 86.5,83 c 0,1.93 -1.57,3.5 -3.5,3.5 h -3 c -3.29,0 -9.5,1.99 -9.5,9.5 v 15.99 c -0.01,0.67 -0.24,6.51 -6.5,6.51 -6.26,0 -6.49,-5.84 -6.5,-6.5 V 96 c 0,-7.51 -6.21,-9.5 -9.5,-9.5 h -2.99 c -1.94,0 -3.51,-1.57 -3.51,-3.51 V 73.5 h 45 z"/>
|
||||
<path fill="#FFFFFF" d="m 109.62313,6.5793356 c -4.05489,0 -7.35886,2.5891328 -7.50904,5.8406014 -9.836863,0.301062 -15.018101,6.442725 -15.018101,12.223115 l -7.509041,0.06022 c -9.461393,0 -14.64263,5.840601 -15.018083,11.500567 -0.07509,0 -0.07509,0 -0.15018,0 h -0.675814 c 0,0 -0.07509,0 -0.150181,0 C 63.217238,30.423447 57.960909,24.70327 48.574608,24.70327 h -7.509042 c 0.225272,0 -0.150181,-0.120425 -0.300361,-0.180637 0.375451,-5.720177 -4.805787,-11.922053 -14.56754,-12.10269 -0.375453,-3.0708319 -3.604341,-5.6599647 -7.509042,-5.6599647 -4.129973,0 -7.509041,2.5289204 -7.509041,5.8406017 0,4.455716 2.327803,7.165274 4.280154,8.670584 4.280153,3.251469 9.686663,3.251469 10.737929,3.191257 0,8.670583 8.785578,12.042478 14.64263,12.283327 h 7.809403 c 0,4.154655 2.252712,6.743788 4.129972,8.188885 4.355245,3.371894 10.137207,3.371894 11.263562,3.311682 h 0.525633 c 0.825994,0 6.607956,0.06022 10.963201,-3.311682 1.87726,-1.445097 4.129972,-4.094442 4.129972,-8.249098 h 7.509041 c 6.232505,-0.180636 15.018101,-3.612743 15.018101,-12.10269 0.97617,-0.120424 6.45777,-0.120424 10.66284,-3.371892 1.95235,-1.505311 4.28015,-4.214868 4.28015,-8.670585 0,-3.2514693 -3.37907,-5.9610268 -7.50904,-5.9610268 z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
6
resources/icons/fuzzy_skin_painting_.svg
Normal file
6
resources/icons/fuzzy_skin_painting_.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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"
|
||||
width="128px" height="128px" viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
|
||||
<path fill="#ED6B21" d="m 88,38.93 c -0.83,0 -1.5,0.67 -1.5,1.5 V 70.5 h -5 V 45.14 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 V 70.5 h -5 V 49.8 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 v 20.7 h -5 V 53.84 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 V 70.5 h -5 V 49.8 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 v 20.7 h -5 V 45.14 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 V 70.5 h -5 V 40.43 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 -0.83,0 -1.5,0.67 -1.5,1.5 V 72 82.99 c 0,3.59 2.92,6.51 6.51,6.51 h 2.98 c 0.67,0.01 6.51,0.24 6.51,6.5 v 16 c 0,3.29 1.99,9.5 9.5,9.5 7.51,0 9.5,-6.21 9.5,-9.5 V 96 c 0,-6.26 5.84,-6.49 6.5,-6.5 h 3 c 3.59,0 6.5,-2.92 6.5,-6.5 V 72 40.43 c 0,-0.83 -0.67,-1.5 -1.5,-1.5 z M 86.5,83 c 0,1.93 -1.57,3.5 -3.5,3.5 h -3 c -3.29,0 -9.5,1.99 -9.5,9.5 v 15.99 c -0.01,0.67 -0.24,6.51 -6.5,6.51 -6.26,0 -6.49,-5.84 -6.5,-6.5 V 96 c 0,-7.51 -6.21,-9.5 -9.5,-9.5 h -2.99 c -1.94,0 -3.51,-1.57 -3.51,-3.51 V 73.5 h 45 z"/>
|
||||
<path fill="#808080" d="m 109.62313,6.5793356 c -4.05489,0 -7.35886,2.5891328 -7.50904,5.8406014 -9.836863,0.301062 -15.018101,6.442725 -15.018101,12.223115 l -7.509041,0.06022 c -9.461393,0 -14.64263,5.840601 -15.018083,11.500567 -0.07509,0 -0.07509,0 -0.15018,0 h -0.675814 c 0,0 -0.07509,0 -0.150181,0 C 63.217238,30.423447 57.960909,24.70327 48.574608,24.70327 h -7.509042 c 0.225272,0 -0.150181,-0.120425 -0.300361,-0.180637 0.375451,-5.720177 -4.805787,-11.922053 -14.56754,-12.10269 -0.375453,-3.0708319 -3.604341,-5.6599647 -7.509042,-5.6599647 -4.129973,0 -7.509041,2.5289204 -7.509041,5.8406017 0,4.455716 2.327803,7.165274 4.280154,8.670584 4.280153,3.251469 9.686663,3.251469 10.737929,3.191257 0,8.670583 8.785578,12.042478 14.64263,12.283327 h 7.809403 c 0,4.154655 2.252712,6.743788 4.129972,8.188885 4.355245,3.371894 10.137207,3.371894 11.263562,3.311682 h 0.525633 c 0.825994,0 6.607956,0.06022 10.963201,-3.311682 1.87726,-1.445097 4.129972,-4.094442 4.129972,-8.249098 h 7.509041 c 6.232505,-0.180636 15.018101,-3.612743 15.018101,-12.10269 0.97617,-0.120424 6.45777,-0.120424 10.66284,-3.371892 1.95235,-1.505311 4.28015,-4.214868 4.28015,-8.670585 0,-3.2514693 -3.37907,-5.9610268 -7.50904,-5.9610268 z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.5 KiB |
@ -133,6 +133,7 @@ static constexpr const char* INSTANCESCOUNT_ATTR = "instances_count";
|
||||
static constexpr const char* CUSTOM_SUPPORTS_ATTR = "slic3rpe:custom_supports";
|
||||
static constexpr const char* CUSTOM_SEAM_ATTR = "slic3rpe:custom_seam";
|
||||
static constexpr const char* MM_SEGMENTATION_ATTR = "slic3rpe:mmu_segmentation";
|
||||
static constexpr const char* FUZZY_SKIN_ATTR = "slic3rpe:fuzzy_skin";
|
||||
|
||||
static constexpr const char* KEY_ATTR = "key";
|
||||
static constexpr const char* VALUE_ATTR = "value";
|
||||
@ -374,6 +375,7 @@ namespace Slic3r {
|
||||
std::vector<std::string> custom_supports;
|
||||
std::vector<std::string> custom_seam;
|
||||
std::vector<std::string> mm_segmentation;
|
||||
std::vector<std::string> fuzzy_skin;
|
||||
|
||||
bool empty() { return vertices.empty() || triangles.empty(); }
|
||||
|
||||
@ -383,6 +385,7 @@ namespace Slic3r {
|
||||
custom_supports.clear();
|
||||
custom_seam.clear();
|
||||
mm_segmentation.clear();
|
||||
fuzzy_skin.clear();
|
||||
}
|
||||
};
|
||||
|
||||
@ -2075,6 +2078,7 @@ namespace Slic3r {
|
||||
|
||||
m_curr_object.geometry.custom_supports.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SUPPORTS_ATTR));
|
||||
m_curr_object.geometry.custom_seam.push_back(get_attribute_value_string(attributes, num_attributes, CUSTOM_SEAM_ATTR));
|
||||
m_curr_object.geometry.fuzzy_skin.push_back(get_attribute_value_string(attributes, num_attributes, FUZZY_SKIN_ATTR));
|
||||
|
||||
// Now load MM segmentation data. Unfortunately, BambuStudio has changed the attribute name after they forked us,
|
||||
// leading to https://github.com/prusa3d/PrusaSlicer/issues/12502. Let's try to load both keys if the usual
|
||||
@ -2579,10 +2583,11 @@ namespace Slic3r {
|
||||
if (has_transform)
|
||||
volume->source.transform = Slic3r::Geometry::Transformation(volume_matrix_to_object);
|
||||
|
||||
// recreate custom supports, seam and mm segmentation from previously loaded attribute
|
||||
// recreate custom supports, seam, mm segmentation and fuzzy skin from previously loaded attribute
|
||||
volume->supported_facets.reserve(triangles_count);
|
||||
volume->seam_facets.reserve(triangles_count);
|
||||
volume->mm_segmentation_facets.reserve(triangles_count);
|
||||
volume->fuzzy_skin_facets.reserve(triangles_count);
|
||||
for (size_t i=0; i<triangles_count; ++i) {
|
||||
size_t index = volume_data.first_triangle_id + i;
|
||||
assert(index < geometry.custom_supports.size());
|
||||
@ -2592,10 +2597,12 @@ namespace Slic3r {
|
||||
volume->supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]);
|
||||
volume->seam_facets.set_triangle_from_string(i, geometry.custom_seam[index]);
|
||||
volume->mm_segmentation_facets.set_triangle_from_string(i, geometry.mm_segmentation[index]);
|
||||
volume->fuzzy_skin_facets.set_triangle_from_string(i, geometry.fuzzy_skin[index]);
|
||||
}
|
||||
volume->supported_facets.shrink_to_fit();
|
||||
volume->seam_facets.shrink_to_fit();
|
||||
volume->mm_segmentation_facets.shrink_to_fit();
|
||||
volume->fuzzy_skin_facets.shrink_to_fit();
|
||||
|
||||
if (auto &es = volume_data.shape_configuration; es.has_value())
|
||||
volume->emboss_shape = std::move(es);
|
||||
@ -3278,6 +3285,15 @@ namespace Slic3r {
|
||||
output_buffer += "\"";
|
||||
}
|
||||
|
||||
std::string fuzzy_skin_data_string = volume->fuzzy_skin_facets.get_triangle_as_string(i);
|
||||
if (!fuzzy_skin_data_string.empty()) {
|
||||
output_buffer += " ";
|
||||
output_buffer += FUZZY_SKIN_ATTR;
|
||||
output_buffer += "=\"";
|
||||
output_buffer += fuzzy_skin_data_string;
|
||||
output_buffer += "\"";
|
||||
}
|
||||
|
||||
output_buffer += "/>\n";
|
||||
|
||||
if (! flush())
|
||||
|
@ -648,6 +648,11 @@ bool Model::is_mm_painted() const
|
||||
return std::any_of(this->objects.cbegin(), this->objects.cend(), [](const ModelObject *mo) { return mo->is_mm_painted(); });
|
||||
}
|
||||
|
||||
bool Model::is_fuzzy_skin_painted() const
|
||||
{
|
||||
return std::any_of(this->objects.cbegin(), this->objects.cend(), [](const ModelObject *mo) { return mo->is_fuzzy_skin_painted(); });
|
||||
}
|
||||
|
||||
ModelObject::~ModelObject()
|
||||
{
|
||||
this->clear_volumes();
|
||||
@ -831,6 +836,11 @@ bool ModelObject::is_mm_painted() const
|
||||
return std::any_of(this->volumes.cbegin(), this->volumes.cend(), [](const ModelVolume *mv) { return mv->is_mm_painted(); });
|
||||
}
|
||||
|
||||
bool ModelObject::is_fuzzy_skin_painted() const
|
||||
{
|
||||
return std::any_of(this->volumes.cbegin(), this->volumes.cend(), [](const ModelVolume *mv) { return mv->is_fuzzy_skin_painted(); });
|
||||
}
|
||||
|
||||
bool ModelObject::is_text() const
|
||||
{
|
||||
return this->volumes.size() == 1 && this->volumes[0]->is_text();
|
||||
@ -1248,6 +1258,7 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, ConversionType con
|
||||
vol->supported_facets.assign(volume->supported_facets);
|
||||
vol->seam_facets.assign(volume->seam_facets);
|
||||
vol->mm_segmentation_facets.assign(volume->mm_segmentation_facets);
|
||||
vol->fuzzy_skin_facets.assign(volume->fuzzy_skin_facets);
|
||||
|
||||
// Perform conversion only if the target "imperial" state is different from the current one.
|
||||
// This check supports conversion of "mixed" set of volumes, each with different "imperial" state.
|
||||
@ -1360,6 +1371,7 @@ void ModelVolume::reset_extra_facets()
|
||||
this->supported_facets.reset();
|
||||
this->seam_facets.reset();
|
||||
this->mm_segmentation_facets.reset();
|
||||
this->fuzzy_skin_facets.reset();
|
||||
}
|
||||
|
||||
|
||||
@ -1926,6 +1938,7 @@ void ModelVolume::assign_new_unique_ids_recursive()
|
||||
supported_facets.set_new_unique_id();
|
||||
seam_facets.set_new_unique_id();
|
||||
mm_segmentation_facets.set_new_unique_id();
|
||||
fuzzy_skin_facets.set_new_unique_id();
|
||||
}
|
||||
|
||||
void ModelVolume::rotate(double angle, Axis axis)
|
||||
@ -2273,6 +2286,13 @@ bool model_mmu_segmentation_data_changed(const ModelObject& mo, const ModelObjec
|
||||
[](const ModelVolume &mv_old, const ModelVolume &mv_new){ return mv_old.mm_segmentation_facets.timestamp_matches(mv_new.mm_segmentation_facets); });
|
||||
}
|
||||
|
||||
bool model_fuzzy_skin_data_changed(const ModelObject &mo, const ModelObject &mo_new)
|
||||
{
|
||||
return model_property_changed(mo, mo_new,
|
||||
[](const ModelVolumeType t) { return t == ModelVolumeType::MODEL_PART; },
|
||||
[](const ModelVolume &mv_old, const ModelVolume &mv_new){ return mv_old.fuzzy_skin_facets.timestamp_matches(mv_new.fuzzy_skin_facets); });
|
||||
}
|
||||
|
||||
bool model_has_parameter_modifiers_in_objects(const Model &model)
|
||||
{
|
||||
for (const auto& model_object : model.objects)
|
||||
|
@ -393,6 +393,8 @@ public:
|
||||
bool is_seam_painted() const;
|
||||
// Checks if any of object volume is painted using the multi-material painting gizmo.
|
||||
bool is_mm_painted() const;
|
||||
// Checks if any of object volume is painted using the fuzzy skin painting gizmo.
|
||||
bool is_fuzzy_skin_painted() const;
|
||||
// Checks if object contains just one volume and it's a text
|
||||
bool is_text() const;
|
||||
// This object may have a varying layer height by painting or by a table.
|
||||
@ -802,6 +804,9 @@ public:
|
||||
// List of mesh facets painted for MM segmentation.
|
||||
FacetsAnnotation mm_segmentation_facets;
|
||||
|
||||
// List of mesh facets painted for fuzzy skin.
|
||||
FacetsAnnotation fuzzy_skin_facets;
|
||||
|
||||
// Is set only when volume is Embossed Text type
|
||||
// Contain information how to re-create volume
|
||||
std::optional<TextConfiguration> text_configuration;
|
||||
@ -906,11 +911,13 @@ public:
|
||||
this->supported_facets.set_new_unique_id();
|
||||
this->seam_facets.set_new_unique_id();
|
||||
this->mm_segmentation_facets.set_new_unique_id();
|
||||
this->fuzzy_skin_facets.set_new_unique_id();
|
||||
}
|
||||
|
||||
bool is_fdm_support_painted() const { return !this->supported_facets.empty(); }
|
||||
bool is_seam_painted() const { return !this->seam_facets.empty(); }
|
||||
bool is_mm_painted() const { return !this->mm_segmentation_facets.empty(); }
|
||||
bool is_fuzzy_skin_painted() const { return !this->fuzzy_skin_facets.empty(); }
|
||||
|
||||
// Returns 0-based indices of extruders painted by multi-material painting gizmo.
|
||||
std::vector<size_t> get_extruders_from_multi_material_painting() const;
|
||||
@ -958,10 +965,12 @@ private:
|
||||
assert(this->supported_facets.id().valid());
|
||||
assert(this->seam_facets.id().valid());
|
||||
assert(this->mm_segmentation_facets.id().valid());
|
||||
assert(this->fuzzy_skin_facets.id().valid());
|
||||
assert(this->id() != this->config.id());
|
||||
assert(this->id() != this->supported_facets.id());
|
||||
assert(this->id() != this->seam_facets.id());
|
||||
assert(this->id() != this->mm_segmentation_facets.id());
|
||||
assert(this->id() != this->fuzzy_skin_facets.id());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -988,13 +997,14 @@ private:
|
||||
name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull),
|
||||
config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation),
|
||||
supported_facets(other.supported_facets), seam_facets(other.seam_facets), mm_segmentation_facets(other.mm_segmentation_facets),
|
||||
cut_info(other.cut_info), text_configuration(other.text_configuration), emboss_shape(other.emboss_shape)
|
||||
fuzzy_skin_facets(other.fuzzy_skin_facets), cut_info(other.cut_info), text_configuration(other.text_configuration), emboss_shape(other.emboss_shape)
|
||||
{
|
||||
assert(this->id().valid());
|
||||
assert(this->config.id().valid());
|
||||
assert(this->supported_facets.id().valid());
|
||||
assert(this->seam_facets.id().valid());
|
||||
assert(this->mm_segmentation_facets.id().valid());
|
||||
assert(this->fuzzy_skin_facets.id().valid());
|
||||
assert(this->id() != this->config.id());
|
||||
assert(this->id() != this->supported_facets.id());
|
||||
assert(this->id() != this->seam_facets.id());
|
||||
@ -1004,6 +1014,7 @@ private:
|
||||
assert(this->supported_facets.id() == other.supported_facets.id());
|
||||
assert(this->seam_facets.id() == other.seam_facets.id());
|
||||
assert(this->mm_segmentation_facets.id() == other.mm_segmentation_facets.id());
|
||||
assert(this->fuzzy_skin_facets.id() == other.fuzzy_skin_facets.id());
|
||||
this->set_material_id(other.material_id());
|
||||
}
|
||||
// Providing a new mesh, therefore this volume will get a new unique ID assigned.
|
||||
@ -1016,10 +1027,12 @@ private:
|
||||
assert(this->supported_facets.id().valid());
|
||||
assert(this->seam_facets.id().valid());
|
||||
assert(this->mm_segmentation_facets.id().valid());
|
||||
assert(this->fuzzy_skin_facets.id().valid());
|
||||
assert(this->id() != this->config.id());
|
||||
assert(this->id() != this->supported_facets.id());
|
||||
assert(this->id() != this->seam_facets.id());
|
||||
assert(this->id() != this->mm_segmentation_facets.id());
|
||||
assert(this->id() != this->fuzzy_skin_facets.id());
|
||||
assert(this->id() != other.id());
|
||||
assert(this->config.id() == other.config.id());
|
||||
this->set_material_id(other.material_id());
|
||||
@ -1031,10 +1044,12 @@ private:
|
||||
assert(this->supported_facets.id() != other.supported_facets.id());
|
||||
assert(this->seam_facets.id() != other.seam_facets.id());
|
||||
assert(this->mm_segmentation_facets.id() != other.mm_segmentation_facets.id());
|
||||
assert(this->fuzzy_skin_facets.id() != other.fuzzy_skin_facets.id());
|
||||
assert(this->id() != this->config.id());
|
||||
assert(this->supported_facets.empty());
|
||||
assert(this->seam_facets.empty());
|
||||
assert(this->mm_segmentation_facets.empty());
|
||||
assert(this->fuzzy_skin_facets.empty());
|
||||
}
|
||||
|
||||
ModelVolume& operator=(ModelVolume &rhs) = delete;
|
||||
@ -1042,12 +1057,13 @@ private:
|
||||
friend class cereal::access;
|
||||
friend class UndoRedo::StackImpl;
|
||||
// Used for deserialization, therefore no IDs are allocated.
|
||||
ModelVolume() : ObjectBase(-1), config(-1), supported_facets(-1), seam_facets(-1), mm_segmentation_facets(-1), object(nullptr) {
|
||||
ModelVolume() : ObjectBase(-1), config(-1), supported_facets(-1), seam_facets(-1), mm_segmentation_facets(-1), fuzzy_skin_facets(-1), object(nullptr) {
|
||||
assert(this->id().invalid());
|
||||
assert(this->config.id().invalid());
|
||||
assert(this->supported_facets.id().invalid());
|
||||
assert(this->seam_facets.id().invalid());
|
||||
assert(this->mm_segmentation_facets.id().invalid());
|
||||
assert(this->fuzzy_skin_facets.id().invalid());
|
||||
}
|
||||
template<class Archive> void load(Archive &ar) {
|
||||
bool has_convex_hull;
|
||||
@ -1055,6 +1071,7 @@ private:
|
||||
cereal::load_by_value(ar, supported_facets);
|
||||
cereal::load_by_value(ar, seam_facets);
|
||||
cereal::load_by_value(ar, mm_segmentation_facets);
|
||||
cereal::load_by_value(ar, fuzzy_skin_facets);
|
||||
cereal::load_by_value(ar, config);
|
||||
cereal::load(ar, text_configuration);
|
||||
cereal::load(ar, emboss_shape);
|
||||
@ -1073,6 +1090,7 @@ private:
|
||||
cereal::save_by_value(ar, supported_facets);
|
||||
cereal::save_by_value(ar, seam_facets);
|
||||
cereal::save_by_value(ar, mm_segmentation_facets);
|
||||
cereal::save_by_value(ar, fuzzy_skin_facets);
|
||||
cereal::save_by_value(ar, config);
|
||||
cereal::save(ar, text_configuration);
|
||||
cereal::save(ar, emboss_shape);
|
||||
@ -1337,6 +1355,8 @@ public:
|
||||
bool is_seam_painted() const;
|
||||
// Checks if any of objects is painted using the multi-material painting gizmo.
|
||||
bool is_mm_painted() const;
|
||||
// Checks if any of objects is painted using the fuzzy skin painting gizmo.
|
||||
bool is_fuzzy_skin_painted() const;
|
||||
|
||||
private:
|
||||
explicit Model(int) : ObjectBase(-1) { assert(this->id().invalid()); }
|
||||
@ -1381,6 +1401,10 @@ bool model_custom_seam_data_changed(const ModelObject& mo, const ModelObject& mo
|
||||
// The function assumes that volumes list is synchronized.
|
||||
extern bool model_mmu_segmentation_data_changed(const ModelObject& mo, const ModelObject& mo_new);
|
||||
|
||||
// Test whether the now ModelObject has newer fuzzy skin data than the old one.
|
||||
// The function assumes that volumes list is synchronized.
|
||||
extern bool model_fuzzy_skin_data_changed(const ModelObject &mo, const ModelObject &mo_new);
|
||||
|
||||
// If the model has object(s) which contains a modofoer, then it is currently not supported by the SLA mode.
|
||||
// Either the model cannot be loaded, or a SLA printer has to be activated.
|
||||
bool model_has_parameter_modifiers_in_objects(const Model& model);
|
||||
|
@ -105,6 +105,8 @@ static inline void model_volume_list_copy_configs(ModelObject &model_object_dst,
|
||||
mv_dst.seam_facets.assign(mv_src.seam_facets);
|
||||
assert(mv_dst.mm_segmentation_facets.id() == mv_src.mm_segmentation_facets.id());
|
||||
mv_dst.mm_segmentation_facets.assign(mv_src.mm_segmentation_facets);
|
||||
assert(mv_dst.fuzzy_skin_facets.id() == mv_src.fuzzy_skin_facets.id());
|
||||
mv_dst.fuzzy_skin_facets.assign(mv_src.fuzzy_skin_facets);
|
||||
//FIXME what to do with the materials?
|
||||
// mv_dst.m_material_id = mv_src.m_material_id;
|
||||
++ i_src;
|
||||
@ -1196,7 +1198,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
// Only volume IDs, volume types, transformation matrices and their order are checked, configuration and other parameters are NOT checked.
|
||||
bool solid_or_modifier_differ = model_volume_list_changed(model_object, model_object_new, solid_or_modifier_types) ||
|
||||
model_mmu_segmentation_data_changed(model_object, model_object_new) ||
|
||||
(model_object_new.is_mm_painted() && num_extruders_changed);
|
||||
(model_object_new.is_mm_painted() && num_extruders_changed) ||
|
||||
model_fuzzy_skin_data_changed(model_object, model_object_new);
|
||||
bool supports_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER) ||
|
||||
model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER);
|
||||
bool layer_height_ranges_differ = ! layer_height_ranges_equal(model_object.layer_config_ranges, model_object_new.layer_config_ranges, model_object_new.layer_height_profile.empty());
|
||||
|
@ -37,6 +37,8 @@ enum class TriangleStateType : int8_t {
|
||||
NONE = 0,
|
||||
ENFORCER = 1,
|
||||
BLOCKER = 2,
|
||||
// For the fuzzy skin, we use just two values (NONE and FUZZY_SKIN).
|
||||
FUZZY_SKIN = ENFORCER,
|
||||
// Maximum is 15. The value is serialized in TriangleSelector into 6 bits using a 2 bit prefix code.
|
||||
Extruder1 = ENFORCER,
|
||||
Extruder2 = BLOCKER,
|
||||
|
@ -81,6 +81,8 @@ set(SLIC3R_GUI_SOURCES
|
||||
GUI/Gizmos/GLGizmoSlaSupports.hpp
|
||||
GUI/Gizmos/GLGizmoFdmSupports.cpp
|
||||
GUI/Gizmos/GLGizmoFdmSupports.hpp
|
||||
GUI/Gizmos/GLGizmoFuzzySkin.cpp
|
||||
GUI/Gizmos/GLGizmoFuzzySkin.hpp
|
||||
GUI/Gizmos/GLGizmoFlatten.cpp
|
||||
GUI/Gizmos/GLGizmoFlatten.hpp
|
||||
GUI/Gizmos/GLGizmoCut.cpp
|
||||
|
@ -1555,11 +1555,12 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject
|
||||
auto gizmo_type = gm.get_current_type();
|
||||
if ( (gizmo_type == GLGizmosManager::FdmSupports
|
||||
|| gizmo_type == GLGizmosManager::Seam
|
||||
|| gizmo_type == GLGizmosManager::Cut)
|
||||
|| gizmo_type == GLGizmosManager::Cut
|
||||
|| gizmo_type == GLGizmosManager::FuzzySkin)
|
||||
&& !vol->is_modifier) {
|
||||
vol->force_neutral_color = true;
|
||||
}
|
||||
else if (gizmo_type == GLGizmosManager::MmuSegmentation)
|
||||
else if (gizmo_type == GLGizmosManager::MmSegmentation)
|
||||
vol->is_active = false;
|
||||
else
|
||||
vol->force_native_color = true;
|
||||
@ -3149,8 +3150,9 @@ void GLCanvas3D::on_key(wxKeyEvent& evt)
|
||||
const GLGizmosManager::EType gizmo_type = m_gizmos.get_current_type();
|
||||
if (keyCode == WXK_ALT && (gizmo_type == GLGizmosManager::FdmSupports ||
|
||||
gizmo_type == GLGizmosManager::Seam ||
|
||||
gizmo_type == GLGizmosManager::MmuSegmentation)) {
|
||||
// Prevents focusing on the menu bar when ALT is pressed in painting gizmos (FdmSupports, Seam, and MmuSegmentation).
|
||||
gizmo_type == GLGizmosManager::MmSegmentation ||
|
||||
gizmo_type == GLGizmosManager::FuzzySkin)) {
|
||||
// Prevents focusing on the menu bar when ALT is pressed in painting gizmos (FdmSupports, Seam, MmSegmentation, and FuzzySkin).
|
||||
evt.Skip(false);
|
||||
} else if (keyCode != WXK_TAB
|
||||
&& keyCode != WXK_LEFT
|
||||
@ -3359,7 +3361,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_dirty = true;
|
||||
// do not return if dragging or tooltip not empty to allow for tooltip update
|
||||
// also, do not return if the mouse is moving and also is inside MM gizmo to allow update seed fill selection
|
||||
if (!m_mouse.dragging && m_tooltip.is_empty() && (m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation || !evt.Moving()))
|
||||
if (!m_mouse.dragging && m_tooltip.is_empty() && (m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation || !evt.Moving()))
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3540,7 +3542,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
||||
m_gizmos.get_current_type() != GLGizmosManager::Seam &&
|
||||
m_gizmos.get_current_type() != GLGizmosManager::Cut &&
|
||||
m_gizmos.get_current_type() != GLGizmosManager::Measure &&
|
||||
m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation) {
|
||||
m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation &&
|
||||
m_gizmos.get_current_type() != GLGizmosManager::FuzzySkin) {
|
||||
m_rectangle_selection.start_dragging(m_mouse.position, evt.ShiftDown() ? GLSelectionRectangle::EState::Select : GLSelectionRectangle::EState::Deselect);
|
||||
m_dirty = true;
|
||||
}
|
||||
@ -5797,7 +5800,8 @@ void GLCanvas3D::_render_bed(const Transform3d& view_matrix, const Transform3d&
|
||||
&& m_gizmos.get_current_type() != GLGizmosManager::SlaSupports
|
||||
&& m_gizmos.get_current_type() != GLGizmosManager::Hollow
|
||||
&& m_gizmos.get_current_type() != GLGizmosManager::Seam
|
||||
&& m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation);
|
||||
&& m_gizmos.get_current_type() != GLGizmosManager::MmSegmentation
|
||||
&& m_gizmos.get_current_type() != GLGizmosManager::FuzzySkin);
|
||||
|
||||
m_bed.render(*this, view_matrix, projection_matrix, bottom, scale_factor, show_texture);
|
||||
}
|
||||
@ -5950,12 +5954,13 @@ void GLCanvas3D::_render_sequential_clearance()
|
||||
{
|
||||
case GLGizmosManager::EType::Flatten:
|
||||
case GLGizmosManager::EType::Cut:
|
||||
case GLGizmosManager::EType::MmuSegmentation:
|
||||
case GLGizmosManager::EType::MmSegmentation:
|
||||
case GLGizmosManager::EType::Measure:
|
||||
case GLGizmosManager::EType::Emboss:
|
||||
case GLGizmosManager::EType::Simplify:
|
||||
case GLGizmosManager::EType::FdmSupports:
|
||||
case GLGizmosManager::EType::Seam: { return; }
|
||||
case GLGizmosManager::EType::Seam:
|
||||
case GLGizmosManager::EType::FuzzySkin: { return; }
|
||||
default: { break; }
|
||||
}
|
||||
|
||||
|
@ -1921,13 +1921,20 @@ void ObjectList::del_info_item(const int obj_idx, InfoItemType type)
|
||||
}
|
||||
break;
|
||||
|
||||
case InfoItemType::MmuSegmentation:
|
||||
case InfoItemType::MmSegmentation:
|
||||
cnv->get_gizmos_manager().reset_all_states();
|
||||
Plater::TakeSnapshot(plater, _L("Remove Multi Material painting"));
|
||||
for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes)
|
||||
mv->mm_segmentation_facets.reset();
|
||||
break;
|
||||
|
||||
case InfoItemType::FuzzySkin:
|
||||
cnv->get_gizmos_manager().reset_all_states();
|
||||
Plater::TakeSnapshot(plater, _L("Remove paint-on fuzzy skin"));
|
||||
for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes)
|
||||
mv->fuzzy_skin_facets.reset();
|
||||
break;
|
||||
|
||||
case InfoItemType::Sinking:
|
||||
Plater::TakeSnapshot(plater, _L("Shift objects to bed"));
|
||||
(*m_objects)[obj_idx]->ensure_on_bed();
|
||||
@ -2132,8 +2139,8 @@ void ObjectList::split()
|
||||
|
||||
take_snapshot(_(L("Split to Parts")));
|
||||
|
||||
// Before splitting volume we have to remove all custom supports, seams, and multimaterial painting.
|
||||
wxGetApp().plater()->clear_before_change_mesh(obj_idx, _u8L("Custom supports, seams and multimaterial painting were "
|
||||
// Before splitting volume we have to remove all custom supports, seams, fuzzy skin and multi-material painting.
|
||||
wxGetApp().plater()->clear_before_change_mesh(obj_idx, _u8L("Custom supports, seams, fuzzy skin and multi-material painting were "
|
||||
"removed after splitting the object."));
|
||||
|
||||
volume->split(nozzle_dmrs_cnt);
|
||||
@ -2148,8 +2155,8 @@ void ObjectList::split()
|
||||
// update printable state for new volumes on canvas3D
|
||||
wxGetApp().plater()->canvas3D()->update_instance_printable_state_for_object(obj_idx);
|
||||
|
||||
// After removing custom supports, seams, and multimaterial painting, we have to update info about the object to remove information about
|
||||
// custom supports, seams, and multimaterial painting in the right panel.
|
||||
// After removing custom supports, seams, fuzzy skin, and multi-material painting, we have to update info about the object to remove information about
|
||||
// custom supports, seams, fuzzy skin, and multi-material painting in the right panel.
|
||||
wxGetApp().obj_list()->update_info_items(obj_idx);
|
||||
}
|
||||
|
||||
@ -2727,11 +2734,13 @@ void ObjectList::part_selection_changed()
|
||||
}
|
||||
case InfoItemType::CustomSupports:
|
||||
case InfoItemType::CustomSeam:
|
||||
case InfoItemType::MmuSegmentation:
|
||||
case InfoItemType::MmSegmentation:
|
||||
case InfoItemType::FuzzySkin:
|
||||
{
|
||||
GLGizmosManager::EType gizmo_type = info_type == InfoItemType::CustomSupports ? GLGizmosManager::EType::FdmSupports :
|
||||
info_type == InfoItemType::CustomSeam ? GLGizmosManager::EType::Seam :
|
||||
GLGizmosManager::EType::MmuSegmentation;
|
||||
info_type == InfoItemType::FuzzySkin ? GLGizmosManager::EType::FuzzySkin :
|
||||
GLGizmosManager::EType::MmSegmentation;
|
||||
if (gizmos_mgr.get_current_type() != gizmo_type)
|
||||
gizmos_mgr.open_gizmo(gizmo_type);
|
||||
break;
|
||||
@ -2901,7 +2910,8 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
|
||||
for (InfoItemType type : {InfoItemType::CustomSupports,
|
||||
InfoItemType::CustomSeam,
|
||||
InfoItemType::CutConnectors,
|
||||
InfoItemType::MmuSegmentation,
|
||||
InfoItemType::MmSegmentation,
|
||||
InfoItemType::FuzzySkin,
|
||||
InfoItemType::Sinking,
|
||||
InfoItemType::VariableLayerHeight}) {
|
||||
wxDataViewItem item = m_objects_model->GetInfoItemByType(item_obj, type);
|
||||
@ -2911,12 +2921,14 @@ void ObjectList::update_info_items(size_t obj_idx, wxDataViewItemArray* selectio
|
||||
switch (type) {
|
||||
case InfoItemType::CustomSupports :
|
||||
case InfoItemType::CustomSeam :
|
||||
case InfoItemType::MmuSegmentation :
|
||||
case InfoItemType::MmSegmentation :
|
||||
case InfoItemType::FuzzySkin :
|
||||
should_show = printer_technology() == ptFFF
|
||||
&& std::any_of(model_object->volumes.begin(), model_object->volumes.end(),
|
||||
[type](const ModelVolume *mv) {
|
||||
return !(type == InfoItemType::CustomSupports ? mv->supported_facets.empty() :
|
||||
type == InfoItemType::CustomSeam ? mv->seam_facets.empty() :
|
||||
type == InfoItemType::FuzzySkin ? mv->fuzzy_skin_facets.empty() :
|
||||
mv->mm_segmentation_facets.empty());
|
||||
});
|
||||
break;
|
||||
@ -4642,7 +4654,7 @@ void ObjectList::fix_through_winsdk()
|
||||
msg += "\n";
|
||||
}
|
||||
|
||||
plater->clear_before_change_mesh(obj_idx, _u8L("Custom supports, seams and multimaterial painting were "
|
||||
plater->clear_before_change_mesh(obj_idx, _u8L("Custom supports, seams, fuzzy skin and multimaterial painting were "
|
||||
"removed after repairing the mesh."));
|
||||
std::string res;
|
||||
if (!fix_model_by_win10_sdk_gui(*(object(obj_idx)), vol_idx, progress_dlg, msg, res))
|
||||
@ -4984,10 +4996,5 @@ ModelObject* ObjectList::object(const int obj_idx) const
|
||||
return (*m_objects)[obj_idx];
|
||||
}
|
||||
|
||||
bool ObjectList::has_paint_on_segmentation()
|
||||
{
|
||||
return m_objects_model->HasInfoItem(InfoItemType::MmuSegmentation);
|
||||
}
|
||||
|
||||
} //namespace GUI
|
||||
} //namespace Slic3r
|
||||
|
@ -410,7 +410,6 @@ public:
|
||||
void set_extruder_for_selected_items(const int extruder) const ;
|
||||
wxDataViewItemArray reorder_volumes_and_get_selection(size_t obj_idx, std::function<bool(const ModelVolume*)> add_to_selection = nullptr);
|
||||
void apply_volumes_order();
|
||||
bool has_paint_on_segmentation();
|
||||
|
||||
bool is_editing() const { return m_is_editing_started; }
|
||||
|
||||
|
311
src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp
Normal file
311
src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.cpp
Normal file
@ -0,0 +1,311 @@
|
||||
#include "GLGizmoFuzzySkin.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||
#include "slic3r/GUI/ImGuiWrapper.hpp"
|
||||
#include "slic3r/GUI/MsgDialog.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "slic3r/Utils/UndoRedo.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
void GLGizmoFuzzySkin::on_shutdown()
|
||||
{
|
||||
m_parent.use_slope(false);
|
||||
m_parent.toggle_model_objects_visibility(true);
|
||||
}
|
||||
|
||||
std::string GLGizmoFuzzySkin::on_get_name() const
|
||||
{
|
||||
return _u8L("Paint-on fuzzy skin");
|
||||
}
|
||||
|
||||
bool GLGizmoFuzzySkin::on_init()
|
||||
{
|
||||
m_shortcut_key = WXK_CONTROL_H;
|
||||
|
||||
m_desc["clipping_of_view"] = _u8L("Clipping of view") + ": ";
|
||||
m_desc["reset_direction"] = _u8L("Reset direction");
|
||||
m_desc["cursor_size"] = _u8L("Brush size") + ": ";
|
||||
m_desc["cursor_type"] = _u8L("Brush shape") + ": ";
|
||||
m_desc["add_fuzzy_skin_caption"] = _u8L("Left mouse button") + ": ";
|
||||
m_desc["add_fuzzy_skin"] = _u8L("Add fuzzy skin");
|
||||
m_desc["remove_fuzzy_skin_caption"] = _u8L("Shift + Left mouse button") + ": ";
|
||||
m_desc["remove_fuzzy_skin"] = _u8L("Remove fuzzy skin");
|
||||
m_desc["remove_all"] = _u8L("Remove all selection");
|
||||
m_desc["circle"] = _u8L("Circle");
|
||||
m_desc["sphere"] = _u8L("Sphere");
|
||||
m_desc["pointer"] = _u8L("Triangles");
|
||||
m_desc["tool_type"] = _u8L("Tool type") + ": ";
|
||||
m_desc["tool_brush"] = _u8L("Brush");
|
||||
m_desc["tool_smart_fill"] = _u8L("Smart fill");
|
||||
m_desc["smart_fill_angle"] = _u8L("Smart fill angle");
|
||||
m_desc["split_triangles"] = _u8L("Split triangles");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLGizmoFuzzySkin::render_painter_gizmo()
|
||||
{
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
render_triangles(selection);
|
||||
m_c->object_clipper()->render_cut();
|
||||
m_c->instances_hider()->render_cut();
|
||||
render_cursor();
|
||||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
void GLGizmoFuzzySkin::on_render_input_window(float x, float y, float bottom_limit)
|
||||
{
|
||||
if (!m_c->selection_info()->model_object())
|
||||
return;
|
||||
|
||||
const float approx_height = m_imgui->scaled(22.f);
|
||||
|
||||
y = std::min(y, bottom_limit - approx_height);
|
||||
ImGuiPureWrap::set_next_window_pos(x, y, ImGuiCond_Always);
|
||||
|
||||
ImGuiPureWrap::begin(get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
|
||||
const float clipping_slider_left = std::max(ImGuiPureWrap::calc_text_size(m_desc.at("clipping_of_view")).x,
|
||||
ImGuiPureWrap::calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f);
|
||||
const float cursor_slider_left = ImGuiPureWrap::calc_text_size(m_desc.at("cursor_size")).x + m_imgui->scaled(1.f);
|
||||
const float smart_fill_slider_left = ImGuiPureWrap::calc_text_size(m_desc.at("smart_fill_angle")).x + m_imgui->scaled(1.f);
|
||||
|
||||
const float cursor_type_radio_circle = ImGuiPureWrap::calc_text_size(m_desc["circle"]).x + m_imgui->scaled(2.5f);
|
||||
const float cursor_type_radio_sphere = ImGuiPureWrap::calc_text_size(m_desc["sphere"]).x + m_imgui->scaled(2.5f);
|
||||
const float cursor_type_radio_pointer = ImGuiPureWrap::calc_text_size(m_desc["pointer"]).x + m_imgui->scaled(2.5f);
|
||||
|
||||
const float button_width = ImGuiPureWrap::calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f);
|
||||
const float buttons_width = m_imgui->scaled(0.5f);
|
||||
const float minimal_slider_width = m_imgui->scaled(4.f);
|
||||
|
||||
const float tool_type_radio_left = ImGuiPureWrap::calc_text_size(m_desc["tool_type"]).x + m_imgui->scaled(1.f);
|
||||
const float tool_type_radio_brush = ImGuiPureWrap::calc_text_size(m_desc["tool_brush"]).x + m_imgui->scaled(2.5f);
|
||||
const float tool_type_radio_smart_fill = ImGuiPureWrap::calc_text_size(m_desc["tool_smart_fill"]).x + m_imgui->scaled(2.5f);
|
||||
|
||||
const float split_triangles_checkbox_width = ImGuiPureWrap::calc_text_size(m_desc["split_triangles"]).x + m_imgui->scaled(2.5f);
|
||||
|
||||
float caption_max = 0.f;
|
||||
float total_text_max = 0.f;
|
||||
for (const std::string t : {"add_fuzzy_skin", "remove_fuzzy_skin"}) {
|
||||
caption_max = std::max(caption_max, ImGuiPureWrap::calc_text_size(m_desc[t + "_caption"]).x);
|
||||
total_text_max = std::max(total_text_max, ImGuiPureWrap::calc_text_size(m_desc[t]).x);
|
||||
}
|
||||
|
||||
total_text_max += caption_max + m_imgui->scaled(1.f);
|
||||
caption_max += m_imgui->scaled(1.f);
|
||||
|
||||
const float sliders_left_width = std::max(smart_fill_slider_left, std::max(cursor_slider_left, clipping_slider_left));
|
||||
const float slider_icon_width = ImGuiPureWrap::get_slider_icon_size().x;
|
||||
float window_width = minimal_slider_width + sliders_left_width + slider_icon_width;
|
||||
window_width = std::max(window_width, total_text_max);
|
||||
window_width = std::max(window_width, button_width);
|
||||
window_width = std::max(window_width, split_triangles_checkbox_width);
|
||||
window_width = std::max(window_width, cursor_type_radio_circle + cursor_type_radio_sphere + cursor_type_radio_pointer);
|
||||
window_width = std::max(window_width, tool_type_radio_left + tool_type_radio_brush + tool_type_radio_smart_fill);
|
||||
window_width = std::max(window_width, 2.f * buttons_width + m_imgui->scaled(1.f));
|
||||
|
||||
auto draw_text_with_caption = [&caption_max](const std::string &caption, const std::string &text) {
|
||||
ImGuiPureWrap::text_colored(ImGuiPureWrap::COL_ORANGE_LIGHT, caption);
|
||||
ImGui::SameLine(caption_max);
|
||||
ImGuiPureWrap::text(text);
|
||||
};
|
||||
|
||||
for (const std::string t : {"add_fuzzy_skin", "remove_fuzzy_skin"}) {
|
||||
draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t));
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
std::string format_str = std::string("%.f") + I18N::translate_utf8("°",
|
||||
"Degree sign to use in the respective slider in fuzzy skin gizmo,"
|
||||
"placed after the number with no whitespace in between.");
|
||||
|
||||
const float max_tooltip_width = ImGui::GetFontSize() * 20.0f;
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGuiPureWrap::text(m_desc["tool_type"]);
|
||||
|
||||
float tool_type_offset = tool_type_radio_left + (window_width - tool_type_radio_left - tool_type_radio_brush - tool_type_radio_smart_fill + m_imgui->scaled(0.5f)) / 2.f;
|
||||
ImGui::SameLine(tool_type_offset);
|
||||
ImGui::PushItemWidth(tool_type_radio_brush);
|
||||
if (ImGuiPureWrap::radio_button(m_desc["tool_brush"], m_tool_type == ToolType::BRUSH))
|
||||
m_tool_type = ToolType::BRUSH;
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGuiPureWrap::tooltip(_u8L("Paints facets according to the chosen painting brush."), max_tooltip_width);
|
||||
|
||||
ImGui::SameLine(tool_type_offset + tool_type_radio_brush);
|
||||
ImGui::PushItemWidth(tool_type_radio_smart_fill);
|
||||
if (ImGuiPureWrap::radio_button(m_desc["tool_smart_fill"], m_tool_type == ToolType::SMART_FILL))
|
||||
m_tool_type = ToolType::SMART_FILL;
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGuiPureWrap::tooltip(_u8L("Paints neighboring facets whose relative angle is less or equal to set angle."), max_tooltip_width);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (m_tool_type == ToolType::BRUSH) {
|
||||
ImGuiPureWrap::text(m_desc.at("cursor_type"));
|
||||
ImGui::NewLine();
|
||||
|
||||
float cursor_type_offset = (window_width - cursor_type_radio_sphere - cursor_type_radio_circle - cursor_type_radio_pointer + m_imgui->scaled(1.5f)) / 2.f;
|
||||
ImGui::SameLine(cursor_type_offset);
|
||||
ImGui::PushItemWidth(cursor_type_radio_sphere);
|
||||
if (ImGuiPureWrap::radio_button(m_desc["sphere"], m_cursor_type == TriangleSelector::CursorType::SPHERE))
|
||||
m_cursor_type = TriangleSelector::CursorType::SPHERE;
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGuiPureWrap::tooltip(_u8L("Paints all facets inside, regardless of their orientation."), max_tooltip_width);
|
||||
|
||||
ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere);
|
||||
ImGui::PushItemWidth(cursor_type_radio_circle);
|
||||
|
||||
if (ImGuiPureWrap::radio_button(m_desc["circle"], m_cursor_type == TriangleSelector::CursorType::CIRCLE))
|
||||
m_cursor_type = TriangleSelector::CursorType::CIRCLE;
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGuiPureWrap::tooltip(_u8L("Ignores facets facing away from the camera."), max_tooltip_width);
|
||||
|
||||
ImGui::SameLine(cursor_type_offset + cursor_type_radio_sphere + cursor_type_radio_circle);
|
||||
ImGui::PushItemWidth(cursor_type_radio_pointer);
|
||||
|
||||
if (ImGuiPureWrap::radio_button(m_desc["pointer"], m_cursor_type == TriangleSelector::CursorType::POINTER))
|
||||
m_cursor_type = TriangleSelector::CursorType::POINTER;
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGuiPureWrap::tooltip(_u8L("Paints only one facet."), max_tooltip_width);
|
||||
|
||||
m_imgui->disabled_begin(m_cursor_type != TriangleSelector::CursorType::SPHERE && m_cursor_type != TriangleSelector::CursorType::CIRCLE);
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGuiPureWrap::text(m_desc.at("cursor_size"));
|
||||
ImGui::SameLine(sliders_left_width);
|
||||
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
|
||||
m_imgui->slider_float("##cursor_radius", &m_cursor_radius, CursorRadiusMin, CursorRadiusMax, "%.2f", 1.0f, true, _L("Alt + Mouse wheel"));
|
||||
|
||||
ImGuiPureWrap::checkbox(m_desc["split_triangles"], m_triangle_splitting_enabled);
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGuiPureWrap::tooltip(_u8L("Splits bigger facets into smaller ones while the object is painted."), max_tooltip_width);
|
||||
|
||||
m_imgui->disabled_end();
|
||||
} else {
|
||||
assert(m_tool_type == ToolType::SMART_FILL);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGuiPureWrap::text(m_desc["smart_fill_angle"] + ":");
|
||||
|
||||
ImGui::SameLine(sliders_left_width);
|
||||
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
|
||||
if (m_imgui->slider_float("##smart_fill_angle", &m_smart_fill_angle, SmartFillAngleMin, SmartFillAngleMax, format_str.data(), 1.0f, true, _L("Alt + Mouse wheel")))
|
||||
for (auto &triangle_selector : m_triangle_selectors) {
|
||||
triangle_selector->seed_fill_unselect_all_triangles();
|
||||
triangle_selector->request_update_render_data();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (m_c->object_clipper()->get_position() == 0.f) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGuiPureWrap::text(m_desc.at("clipping_of_view"));
|
||||
} else {
|
||||
if (ImGuiPureWrap::button(m_desc.at("reset_direction"))) {
|
||||
wxGetApp().CallAfter([this]() { m_c->object_clipper()->set_position_by_ratio(-1., false); });
|
||||
}
|
||||
}
|
||||
|
||||
auto clp_dist = float(m_c->object_clipper()->get_position());
|
||||
ImGui::SameLine(sliders_left_width);
|
||||
ImGui::PushItemWidth(window_width - sliders_left_width - slider_icon_width);
|
||||
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f", 1.0f, true, from_u8(GUI::shortkey_ctrl_prefix()) + _L("Mouse wheel")))
|
||||
m_c->object_clipper()->set_position_by_ratio(clp_dist, true);
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGuiPureWrap::button(m_desc.at("remove_all"))) {
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Reset selection"), UndoRedo::SnapshotType::GizmoAction);
|
||||
ModelObject *mo = m_c->selection_info()->model_object();
|
||||
int idx = -1;
|
||||
for (ModelVolume *mv : mo->volumes)
|
||||
if (mv->is_model_part()) {
|
||||
++idx;
|
||||
m_triangle_selectors[idx]->reset();
|
||||
m_triangle_selectors[idx]->request_update_render_data();
|
||||
}
|
||||
|
||||
update_model_object();
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
|
||||
ImGuiPureWrap::end();
|
||||
}
|
||||
|
||||
void GLGizmoFuzzySkin::update_model_object() const
|
||||
{
|
||||
bool updated = false;
|
||||
ModelObject *mo = m_c->selection_info()->model_object();
|
||||
int idx = -1;
|
||||
for (ModelVolume *mv : mo->volumes) {
|
||||
if (!mv->is_model_part())
|
||||
continue;
|
||||
|
||||
++idx;
|
||||
updated |= mv->fuzzy_skin_facets.set(*m_triangle_selectors[idx]);
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
const ModelObjectPtrs &mos = wxGetApp().model().objects;
|
||||
wxGetApp().obj_list()->update_info_items(std::find(mos.begin(), mos.end(), mo) - mos.begin());
|
||||
|
||||
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoFuzzySkin::update_from_model_object()
|
||||
{
|
||||
wxBusyCursor wait;
|
||||
|
||||
const ModelObject *mo = m_c->selection_info()->model_object();
|
||||
m_triangle_selectors.clear();
|
||||
|
||||
int volume_id = -1;
|
||||
for (const ModelVolume *mv : mo->volumes) {
|
||||
if (!mv->is_model_part())
|
||||
continue;
|
||||
|
||||
++volume_id;
|
||||
|
||||
// This mesh does not account for the possible Z up SLA offset.
|
||||
const TriangleMesh *mesh = &mv->mesh();
|
||||
|
||||
m_triangle_selectors.emplace_back(std::make_unique<TriangleSelectorGUI>(*mesh));
|
||||
// Reset of TriangleSelector is done inside TriangleSelectorGUI's constructor, so we don't need it to perform it again in deserialize().
|
||||
m_triangle_selectors.back()->deserialize(mv->fuzzy_skin_facets.get_data(), false);
|
||||
m_triangle_selectors.back()->request_update_render_data();
|
||||
}
|
||||
}
|
||||
|
||||
PainterGizmoType GLGizmoFuzzySkin::get_painter_type() const
|
||||
{
|
||||
return PainterGizmoType::FUZZY_SKIN;
|
||||
}
|
||||
|
||||
wxString GLGizmoFuzzySkin::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const
|
||||
{
|
||||
return shift_down ? _L("Remove fuzzy skin") : _L("Add fuzzy skin");
|
||||
}
|
||||
|
||||
} // namespace Slic3r::GUI
|
47
src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp
Normal file
47
src/slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef slic3r_GLGizmoFuzzySkin_hpp_
|
||||
#define slic3r_GLGizmoFuzzySkin_hpp_
|
||||
|
||||
#include "GLGizmoPainterBase.hpp"
|
||||
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
|
||||
class GLGizmoFuzzySkin : public GLGizmoPainterBase
|
||||
{
|
||||
public:
|
||||
GLGizmoFuzzySkin(GLCanvas3D &parent, const std::string &icon_filename, unsigned int sprite_id) : GLGizmoPainterBase(parent, icon_filename, sprite_id) {}
|
||||
|
||||
void render_painter_gizmo() override;
|
||||
|
||||
protected:
|
||||
void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
std::string on_get_name() const override;
|
||||
|
||||
wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override;
|
||||
|
||||
std::string get_gizmo_entering_text() const override { return _u8L("Entering Paint-on fuzzy skin"); }
|
||||
std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Paint-on fuzzy skin"); }
|
||||
std::string get_action_snapshot_name() const override { return _u8L("Paint-on fuzzy skin editing"); }
|
||||
|
||||
TriangleStateType get_left_button_state_type() const override { return TriangleStateType::FUZZY_SKIN; }
|
||||
TriangleStateType get_right_button_state_type() const override { return TriangleStateType::NONE; }
|
||||
|
||||
private:
|
||||
bool on_init() override;
|
||||
|
||||
void update_model_object() const override;
|
||||
void update_from_model_object() override;
|
||||
|
||||
void on_opening() override {}
|
||||
void on_shutdown() override;
|
||||
PainterGizmoType get_painter_type() const override;
|
||||
|
||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||
// etc. When language changes, GUI is recreated, and this class constructed again, so the change takes effect.
|
||||
std::map<std::string, std::string> m_desc;
|
||||
};
|
||||
|
||||
} // namespace Slic3r::GUI
|
||||
|
||||
#endif // slic3r_GLGizmoFuzzySkin_hpp_
|
@ -560,7 +560,7 @@ void GLGizmoMmuSegmentation::update_from_model_object()
|
||||
|
||||
PainterGizmoType GLGizmoMmuSegmentation::get_painter_type() const
|
||||
{
|
||||
return PainterGizmoType::MMU_SEGMENTATION;
|
||||
return PainterGizmoType::MM_SEGMENTATION;
|
||||
}
|
||||
|
||||
ColorRGBA GLGizmoMmuSegmentation::get_cursor_sphere_left_button_color() const
|
||||
|
@ -31,7 +31,8 @@ class Selection;
|
||||
enum class PainterGizmoType {
|
||||
FDM_SUPPORTS,
|
||||
SEAM,
|
||||
MMU_SEGMENTATION
|
||||
MM_SEGMENTATION,
|
||||
FUZZY_SKIN
|
||||
};
|
||||
|
||||
class TriangleSelectorGUI : public TriangleSelector {
|
||||
|
@ -36,6 +36,7 @@ enum class SLAGizmoEventType : unsigned char {
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFlatten.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoCut.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoHollow.hpp"
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFlatten.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoFuzzySkin.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoCut.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoHollow.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmoSeam.hpp"
|
||||
@ -113,8 +114,9 @@ bool GLGizmosManager::init()
|
||||
m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, "sla_supports.svg", 6));
|
||||
m_gizmos.emplace_back(new GLGizmoFdmSupports(m_parent, "fdm_supports.svg", 7));
|
||||
m_gizmos.emplace_back(new GLGizmoSeam(m_parent, "seam.svg", 8));
|
||||
m_gizmos.emplace_back(new GLGizmoMmuSegmentation(m_parent, "mmu_segmentation.svg", 9));
|
||||
m_gizmos.emplace_back(new GLGizmoMeasure(m_parent, "measure.svg", 10));
|
||||
m_gizmos.emplace_back(new GLGizmoFuzzySkin(m_parent, "fuzzy_skin_painting.svg", 9));
|
||||
m_gizmos.emplace_back(new GLGizmoMmuSegmentation(m_parent, "mmu_segmentation.svg", 10));
|
||||
m_gizmos.emplace_back(new GLGizmoMeasure(m_parent, "measure.svg", 11));
|
||||
m_gizmos.emplace_back(new GLGizmoEmboss(m_parent));
|
||||
m_gizmos.emplace_back(new GLGizmoSVG(m_parent));
|
||||
m_gizmos.emplace_back(new GLGizmoSimplify(m_parent));
|
||||
@ -294,12 +296,14 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p
|
||||
return dynamic_cast<GLGizmoFdmSupports*>(m_gizmos[FdmSupports].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == Seam)
|
||||
return dynamic_cast<GLGizmoSeam*>(m_gizmos[Seam].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == MmuSegmentation)
|
||||
return dynamic_cast<GLGizmoMmuSegmentation*>(m_gizmos[MmuSegmentation].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == MmSegmentation)
|
||||
return dynamic_cast<GLGizmoMmuSegmentation*>(m_gizmos[MmSegmentation].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == Measure)
|
||||
return dynamic_cast<GLGizmoMeasure*>(m_gizmos[Measure].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == Cut)
|
||||
return dynamic_cast<GLGizmoCut3D*>(m_gizmos[Cut].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else if (m_current == FuzzySkin)
|
||||
return dynamic_cast<GLGizmoFuzzySkin*>(m_gizmos[FuzzySkin].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@ -367,7 +371,7 @@ bool GLGizmosManager::on_mouse_wheel(const wxMouseEvent &evt)
|
||||
{
|
||||
bool processed = false;
|
||||
|
||||
if (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) {
|
||||
if (m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmSegmentation || m_current == FuzzySkin) {
|
||||
float rot = (float)evt.GetWheelRotation() / (float)evt.GetWheelDelta();
|
||||
if (gizmo_event((rot > 0.f ? SLAGizmoEventType::MouseWheelUp : SLAGizmoEventType::MouseWheelDown), Vec2d::Zero(), evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
|
||||
processed = true;
|
||||
@ -540,7 +544,7 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt)
|
||||
case 'r' :
|
||||
case 'R' :
|
||||
{
|
||||
if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmuSegmentation) && gizmo_event(SLAGizmoEventType::ResetClippingPlane))
|
||||
if ((m_current == SlaSupports || m_current == Hollow || m_current == FdmSupports || m_current == Seam || m_current == MmSegmentation || m_current == FuzzySkin) && gizmo_event(SLAGizmoEventType::ResetClippingPlane))
|
||||
processed = true;
|
||||
|
||||
break;
|
||||
|
@ -80,7 +80,8 @@ public:
|
||||
SlaSupports,
|
||||
FdmSupports,
|
||||
Seam,
|
||||
MmuSegmentation,
|
||||
FuzzySkin,
|
||||
MmSegmentation,
|
||||
Measure,
|
||||
Emboss,
|
||||
Svg,
|
||||
|
@ -164,6 +164,7 @@ void KBShortcutsDialog::fill_shortcuts()
|
||||
{ "C", L("Gizmo cut") },
|
||||
{ "F", L("Gizmo Place face on bed") },
|
||||
{ "H", L("Gizmo SLA hollow") },
|
||||
{ "H", L("Gizmo FDM paint-on fuzzy skin") },
|
||||
{ "L", L("Gizmo SLA support points") },
|
||||
{ "L", L("Gizmo FDM paint-on supports") },
|
||||
{ "P", L("Gizmo FDM paint-on seam") },
|
||||
|
@ -1722,10 +1722,11 @@ void NotificationManager::UpdatedItemsInfoNotification::add_type(InfoItemType ty
|
||||
switch ((*it).first) {
|
||||
case InfoItemType::CustomSupports: text += format(_L_PLURAL("%1$d object was loaded with custom supports.", "%1$d objects were loaded with custom supports.", (*it).second), (*it).second) + "\n"; break;
|
||||
case InfoItemType::CustomSeam: text += format(_L_PLURAL("%1$d object was loaded with custom seam.", "%1$d objects were loaded with custom seam.", (*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::MmSegmentation: 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::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::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;
|
||||
case InfoItemType::FuzzySkin: text += format(_L_PLURAL("%1$d object was loaded with fuzzy skin painting.", "%1$d objects were loaded with fuzzy skin painting.", (*it).second), (*it).second) + "\n"; break;
|
||||
default: BOOST_LOG_TRIVIAL(error) << "Unknown InfoItemType: " << (*it).second; break;
|
||||
}
|
||||
}
|
||||
|
@ -68,12 +68,13 @@ struct InfoItemAtributes {
|
||||
|
||||
const std::map<InfoItemType, InfoItemAtributes> INFO_ITEMS{
|
||||
// info_item Type info_item Name info_item BitmapName
|
||||
{ InfoItemType::CustomSupports, {L("Paint-on supports"), "fdm_supports_" }, },
|
||||
{ InfoItemType::CustomSeam, {L("Paint-on seam"), "seam_" }, },
|
||||
{ InfoItemType::CutConnectors, {L("Connectors"), "cut_connectors" }, },
|
||||
{ InfoItemType::MmuSegmentation, {L("Multimaterial painting"), "mmu_segmentation_"}, },
|
||||
{ InfoItemType::Sinking, {L("Sinking"), "sinking"}, },
|
||||
{ InfoItemType::VariableLayerHeight, {L("Variable layer height"), "layers"}, },
|
||||
{ InfoItemType::CustomSupports, {L("Paint-on supports"), "fdm_supports_" }, },
|
||||
{ InfoItemType::CustomSeam, {L("Paint-on seam"), "seam_" }, },
|
||||
{ InfoItemType::CutConnectors, {L("Connectors"), "cut_connectors" }, },
|
||||
{ InfoItemType::MmSegmentation, {L("Multimaterial painting"), "mmu_segmentation_" }, },
|
||||
{ InfoItemType::Sinking, {L("Sinking"), "sinking" }, },
|
||||
{ InfoItemType::VariableLayerHeight, {L("Variable layer height"), "layers" }, },
|
||||
{ InfoItemType::FuzzySkin, {L("Paint-on fuzzy skin"), "fuzzy_skin_painting_" }, },
|
||||
};
|
||||
|
||||
ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent,
|
||||
|
@ -56,7 +56,8 @@ enum class InfoItemType
|
||||
CustomSupports,
|
||||
CustomSeam,
|
||||
CutConnectors,
|
||||
MmuSegmentation,
|
||||
MmSegmentation,
|
||||
FuzzySkin,
|
||||
Sinking,
|
||||
VariableLayerHeight
|
||||
};
|
||||
|
@ -2438,6 +2438,7 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const
|
||||
new_volume->supported_facets.assign(old_volume->supported_facets);
|
||||
new_volume->seam_facets.assign(old_volume->seam_facets);
|
||||
new_volume->mm_segmentation_facets.assign(old_volume->mm_segmentation_facets);
|
||||
new_volume->fuzzy_skin_facets.assign(old_volume->fuzzy_skin_facets);
|
||||
}
|
||||
std::swap(old_model_object->volumes[volume_idx], old_model_object->volumes.back());
|
||||
old_model_object->delete_volume(old_model_object->volumes.size() - 1);
|
||||
@ -6686,11 +6687,12 @@ bool Plater::set_printer_technology(PrinterTechnology printer_technology)
|
||||
}
|
||||
|
||||
void Plater::clear_before_change_volume(ModelVolume &mv, const std::string ¬ification_msg) {
|
||||
// When we change the geometry of the volume, we remove any custom supports/seams/multi-material painting.
|
||||
if (const bool paint_removed = !mv.supported_facets.empty() || !mv.seam_facets.empty() || !mv.mm_segmentation_facets.empty(); paint_removed) {
|
||||
// When we change the geometry of the volume, we remove any custom supports/seams/multi-material/fuzzy skin painting.
|
||||
if (const bool paint_removed = !mv.supported_facets.empty() || !mv.seam_facets.empty() || !mv.mm_segmentation_facets.empty() || !mv.fuzzy_skin_facets.empty(); paint_removed) {
|
||||
mv.supported_facets.reset();
|
||||
mv.seam_facets.reset();
|
||||
mv.mm_segmentation_facets.reset();
|
||||
mv.fuzzy_skin_facets.reset();
|
||||
|
||||
get_notification_manager()->push_notification(
|
||||
NotificationType::CustomSupportsAndSeamRemovedAfterRepair,
|
||||
@ -6703,14 +6705,15 @@ void Plater::clear_before_change_mesh(int obj_idx, const std::string ¬ificati
|
||||
{
|
||||
ModelObject* mo = model().objects[obj_idx];
|
||||
|
||||
// If there are custom supports/seams/mmu segmentation, remove them. Fixed mesh
|
||||
// If there are custom supports/seams/mm segmentation/fuzzy skin, remove them. Fixed mesh
|
||||
// may be different and they would make no sense.
|
||||
bool paint_removed = false;
|
||||
for (ModelVolume* mv : mo->volumes) {
|
||||
paint_removed |= ! mv->supported_facets.empty() || ! mv->seam_facets.empty() || ! mv->mm_segmentation_facets.empty();
|
||||
for (ModelVolume *mv : mo->volumes) {
|
||||
paint_removed |= !mv->supported_facets.empty() || !mv->seam_facets.empty() || !mv->mm_segmentation_facets.empty() || !mv->fuzzy_skin_facets.empty();
|
||||
mv->supported_facets.reset();
|
||||
mv->seam_facets.reset();
|
||||
mv->mm_segmentation_facets.reset();
|
||||
mv->fuzzy_skin_facets.reset();
|
||||
}
|
||||
if (paint_removed) {
|
||||
// snapshot_time is captured by copy so the lambda knows where to undo/redo to.
|
||||
|
Loading…
x
Reference in New Issue
Block a user