Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsupermerill <merill@free.fr>2022-02-08 19:15:37 +0300
committersupermerill <merill@free.fr>2022-02-08 19:15:37 +0300
commit9e6fbb18968913b692b646732c815689d9343e29 (patch)
tree221d2c789c122bbb5335c597cdcb49295acc7dbc /src
parent5379031d3aba0a98be9ae2f46f99733ebd439145 (diff)
parentbee8247cb22d9f68404f50c7995bd049c6a616c2 (diff)
Merge branch 'merill-merge' (2.3.57.10) into dev
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt8
-rw-r--r--src/libslic3r/AppConfig.cpp2
-rw-r--r--src/libslic3r/BridgeDetector.cpp2
-rw-r--r--src/libslic3r/Brim.cpp43
-rw-r--r--src/libslic3r/ClipperUtils.cpp6
-rw-r--r--src/libslic3r/ClipperUtils.hpp1
-rw-r--r--src/libslic3r/Config.cpp2
-rw-r--r--src/libslic3r/Extruder.cpp8
-rw-r--r--src/libslic3r/Extruder.hpp1
-rw-r--r--src/libslic3r/ExtrusionEntity.cpp16
-rw-r--r--src/libslic3r/ExtrusionEntityCollection.cpp46
-rw-r--r--src/libslic3r/ExtrusionEntityCollection.hpp52
-rw-r--r--src/libslic3r/Fill/Fill.cpp56
-rw-r--r--src/libslic3r/Fill/FillBase.cpp19
-rw-r--r--src/libslic3r/Fill/FillBase.hpp2
-rw-r--r--src/libslic3r/Fill/FillConcentric.cpp21
-rw-r--r--src/libslic3r/Fill/FillRectilinear.cpp16
-rw-r--r--src/libslic3r/Fill/FillSmooth.cpp8
-rw-r--r--src/libslic3r/Format/AMF.cpp34
-rw-r--r--src/libslic3r/GCode.cpp162
-rw-r--r--src/libslic3r/GCode.hpp10
-rw-r--r--src/libslic3r/GCode/AvoidCrossingPerimeters.cpp6
-rw-r--r--src/libslic3r/GCode/PrintExtents.cpp6
-rw-r--r--src/libslic3r/GCode/ToolOrdering.cpp20
-rw-r--r--src/libslic3r/GCode/ToolOrdering.hpp2
-rw-r--r--src/libslic3r/GCode/WipeTower.cpp2
-rw-r--r--src/libslic3r/Geometry/MedialAxis.cpp22
-rw-r--r--src/libslic3r/Geometry/MedialAxis.hpp4
-rw-r--r--src/libslic3r/Layer.hpp3
-rw-r--r--src/libslic3r/MedialAxis.cpp22
-rw-r--r--src/libslic3r/MedialAxis.hpp4
-rw-r--r--src/libslic3r/PerimeterGenerator.cpp146
-rw-r--r--src/libslic3r/PlaceholderParser.cpp42
-rw-r--r--src/libslic3r/Print.cpp6
-rw-r--r--src/libslic3r/Print.hpp1
-rw-r--r--src/libslic3r/PrintConfig.cpp48
-rw-r--r--src/libslic3r/PrintObject.cpp95
-rw-r--r--src/libslic3r/SLA/SupportTree.cpp1
-rw-r--r--src/libslic3r/Semver.hpp83
-rw-r--r--src/libslic3r/ShortestPath.cpp2
-rw-r--r--src/libslic3r/SupportMaterial.cpp48
-rw-r--r--src/libslic3r/Surface.hpp5
-rw-r--r--src/libslic3r/pchheader.hpp1
-rw-r--r--src/platform/unix/BuildLinuxImage.sh.in8
-rw-r--r--src/platform/unix/build_appimage.sh.in2
-rw-r--r--src/semver/semver.c162
-rw-r--r--src/semver/semver.h14
-rw-r--r--src/slic3r/GUI/3DScene.cpp2
-rw-r--r--src/slic3r/GUI/CalibrationOverBridgeDialog.cpp3
-rw-r--r--src/slic3r/GUI/CalibrationRetractionDialog.hpp2
-rw-r--r--src/slic3r/GUI/FreeCADDialog.cpp2
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp12
-rw-r--r--src/slic3r/GUI/GUI_App.cpp11
-rw-r--r--src/slic3r/GUI/InstanceCheck.cpp1
-rw-r--r--src/slic3r/GUI/Plater.hpp2
-rw-r--r--src/slic3r/GUI/RemovableDriveManager.hpp2
-rw-r--r--src/slic3r/GUI/Tab.cpp7
-rw-r--r--src/slic3r/GUI/UnsavedChangesDialog.cpp5
-rw-r--r--src/slic3r/Utils/PresetUpdater.cpp51
59 files changed, 859 insertions, 511 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8b553a9e1..597bf9d94 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -255,16 +255,18 @@ else ()
COMMAND ls
# COMMAND ln -sf Slic3r slic3r
#was: COMMAND ln -sf Slic3r prusa-gcodeviewer
- COMMAND ln -sf Slic3r ${GCODEVIEWER_APP_CMD}
+ COMMAND ln -sf ${SLIC3R_APP_CMD} ${GCODEVIEWER_APP_CMD}
#was: COMMAND ln -sf Slic3r PrusaGCodeViewer
- COMMAND ln -sf Slic3r ${GCODEVIEWER_APP_KEY}
+ COMMAND ln -sf ${SLIC3R_APP_CMD} ${GCODEVIEWER_APP_KEY}
+ #for tests
WORKING_DIRECTORY "$<TARGET_FILE_DIR:Slic3r>"
COMMENT "Symlinking the G-code viewer to Slic3r, symlinking to slic3r and gcodeviewer"
VERBATIM)
else ()
add_custom_command(TARGET Slic3r POST_BUILD
#was: COMMAND ln -sf Slic3r prusa-gcodeviewer
- COMMAND ln -sf slic3r ${GCODEVIEWER_APP_CMD}
+ COMMAND ln -sf ${SLIC3R_APP_CMD} ${GCODEVIEWER_APP_CMD}
+ #for tests
WORKING_DIRECTORY "$<TARGET_FILE_DIR:Slic3r>"
COMMENT "Symlinking the G-code viewer to Slic3r"
VERBATIM)
diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp
index b7fba10dc..887039f96 100644
--- a/src/libslic3r/AppConfig.cpp
+++ b/src/libslic3r/AppConfig.cpp
@@ -616,7 +616,7 @@ std::string AppConfig::load(const std::string &path)
// Make 1.40.0 alphas compare well
ini_ver->set_metadata(boost::none);
ini_ver->set_prerelease(boost::none);
- m_legacy_datadir = ini_ver < Semver(1, 40, 0);
+ m_legacy_datadir = ini_ver < Semver(1, 40, 0, 0);
}
// Legacy conversion
diff --git a/src/libslic3r/BridgeDetector.cpp b/src/libslic3r/BridgeDetector.cpp
index 407a8d7ce..43c4bccda 100644
--- a/src/libslic3r/BridgeDetector.cpp
+++ b/src/libslic3r/BridgeDetector.cpp
@@ -427,7 +427,7 @@ std::vector<BridgeDetector::BridgeDirection> BridgeDetector::bridge_direction_ca
}
/* compare first value with last one and remove the greatest one (PI)
in case they are parallel (PI, 0) */
- if (Slic3r::Geometry::directions_parallel(angles.front().angle, angles.back().angle, min_resolution))
+ if (angles.size() > 1 && Slic3r::Geometry::directions_parallel(angles.front().angle, angles.back().angle, min_resolution))
angles.pop_back();
return angles;
diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp
index 0ed4741f1..3acdaacfa 100644
--- a/src/libslic3r/Brim.cpp
+++ b/src/libslic3r/Brim.cpp
@@ -697,63 +697,68 @@ void extrude_brim_from_tree(const Print& print, std::vector<std::vector<BrimLoop
if (!i_have_line && to_cut.children.empty()) {
//nothing
} else if (i_have_line && to_cut.children.empty()) {
+ ExtrusionEntitiesPtr to_add;
for (Polyline& line : to_cut.lines)
if (line.points.back() == line.points.front()) {
ExtrusionPath path(erSkirt, mm3_per_mm, width, height);
path.polyline.points = line.points;
- parent->entities.emplace_back(new ExtrusionLoop(std::move(path), elrSkirt));
+ to_add.push_back(new ExtrusionLoop(std::move(path), elrSkirt));
} else {
ExtrusionPath* extrusion_path = new ExtrusionPath(erSkirt, mm3_per_mm, width, height);
- parent->entities.push_back(extrusion_path);
+ to_add.push_back(extrusion_path);
extrusion_path->polyline = line;
}
+ parent->append(std::move(to_add));
} else if (!i_have_line && !to_cut.children.empty()) {
if (to_cut.children.size() == 1) {
(*extrude_ptr)(to_cut.children[0], parent);
} else {
ExtrusionEntityCollection* mycoll = new ExtrusionEntityCollection();
//mycoll->no_sort = true;
- parent->entities.push_back(mycoll);
for (BrimLoop& child : to_cut.children)
(*extrude_ptr)(child, mycoll);
//remove un-needed collection if possible
- if (mycoll->entities.size() == 1) {
- parent->entities.back() = mycoll->entities.front();
- mycoll->entities.clear();
+ if (mycoll->entities().size() == 1) {
+ parent->append(*mycoll->entities().front());
delete mycoll;
- } else if (mycoll->entities.size() == 0) {
- parent->remove(parent->entities.size() - 1);
+ } else if (mycoll->entities().size() == 0) {
+ delete mycoll;
+ } else {
+ parent->append(ExtrusionEntitiesPtr{ mycoll });
}
}
} else {
ExtrusionEntityCollection* print_me_first = new ExtrusionEntityCollection();
- parent->entities.push_back(print_me_first);
+ ExtrusionEntitiesPtr to_add;
+ to_add.push_back(print_me_first);
print_me_first->set_can_sort_reverse(false, false);
for (Polyline& line : to_cut.lines)
if (line.points.back() == line.points.front()) {
ExtrusionPath path(erSkirt, mm3_per_mm, width, height);
path.polyline.points = line.points;
- print_me_first->entities.emplace_back(new ExtrusionLoop(std::move(path), elrSkirt));
+ to_add.emplace_back(new ExtrusionLoop(std::move(path), elrSkirt));
} else {
ExtrusionPath* extrusion_path = new ExtrusionPath(erSkirt, mm3_per_mm, width, height);
- print_me_first->entities.push_back(extrusion_path);
+ to_add.emplace_back(extrusion_path);
extrusion_path->polyline = line;
}
+ parent->append(std::move(to_add));
if (to_cut.children.size() == 1) {
(*extrude_ptr)(to_cut.children[0], print_me_first);
} else {
ExtrusionEntityCollection* children = new ExtrusionEntityCollection();
//children->no_sort = true;
- print_me_first->entities.push_back(children);
for (BrimLoop& child : to_cut.children)
(*extrude_ptr)(child, children);
//remove un-needed collection if possible
- if (children->entities.size() == 1) {
- print_me_first->entities.back() = children->entities.front();
- children->entities.clear();
+ if (children->entities().size() == 1) {
+ parent->append(*children->entities().front());
+
delete children;
- } else if (children->entities.size() == 0) {
- print_me_first->remove(parent->entities.size() - 1);
+ } else if (children->entities().size() == 0) {
+ delete children;
+ } else {
+ parent->append(ExtrusionEntitiesPtr{ children });
}
}
}
@@ -1086,7 +1091,7 @@ void make_brim_ears(const Print& print, const Flow& flow, const PrintObjectPtrs&
//push into extrusions
extrusion_entities_append_paths(
- out.entities,
+ out.set_entities(),
lines_sorted,
erSkirt,
float(flow.mm3_per_mm()),
@@ -1127,7 +1132,7 @@ void make_brim_ears(const Print& print, const Flow& flow, const PrintObjectPtrs&
filler->init_spacing(flow.spacing(), fill_params);
for (const ExPolygon& expoly : new_brim_area) {
Surface surface(stPosInternal | stDensSparse, expoly);
- filler->fill_surface_extrusion(&surface, fill_params, out.entities);
+ filler->fill_surface_extrusion(&surface, fill_params, out.set_entities());
}
unbrimmable.insert(unbrimmable.end(), new_brim_area.begin(), new_brim_area.end());
diff --git a/src/libslic3r/ClipperUtils.cpp b/src/libslic3r/ClipperUtils.cpp
index 4eedd281a..b07a1c39d 100644
--- a/src/libslic3r/ClipperUtils.cpp
+++ b/src/libslic3r/ClipperUtils.cpp
@@ -499,6 +499,12 @@ Slic3r::Polygons opening(const Slic3r::Surfaces &surfaces, const double delta1,
//FIXME it may be more efficient to offset to_expolygons(surfaces) instead of to_polygons(surfaces).
return to_polygons(expand_paths<ClipperLib::Paths>(shrink_paths<ClipperLib::Paths>(ClipperUtils::SurfacesProvider(surfaces), delta1, joinType, miterLimit), delta2, joinType, miterLimit));
}
+Slic3r::ExPolygons opening_ex(const Slic3r::Polygons& polygons, const double delta1, const double delta2, ClipperLib::JoinType joinType, double miterLimit)
+{
+ assert(delta1 > 0);
+ assert(delta2 > 0);
+ return PolyTreeToExPolygons(expand_paths<ClipperLib::PolyTree>(shrink_paths<ClipperLib::Paths>(ClipperUtils::PolygonsProvider(polygons), delta1, joinType, miterLimit), delta2, joinType, miterLimit));
+}
bool test_path(const ClipperLib::Path &path) {
diff --git a/src/libslic3r/ClipperUtils.hpp b/src/libslic3r/ClipperUtils.hpp
index e6213edca..09f4dcc01 100644
--- a/src/libslic3r/ClipperUtils.hpp
+++ b/src/libslic3r/ClipperUtils.hpp
@@ -372,6 +372,7 @@ inline Slic3r::Polygons opening(const Slic3r::ExPolygons &expolygons, const do
{ return opening(expolygons, delta, delta, joinType, miterLimit); }
inline Slic3r::Polygons opening(const Slic3r::Surfaces &surfaces, const double delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit)
{ return opening(surfaces, delta, delta, joinType, miterLimit); }
+Slic3r::ExPolygons opening_ex(const Slic3r::Polygons & polygons, const double delta1, const double delta2, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit);
inline Slic3r::ExPolygons opening_ex(const Slic3r::ExPolygons &polygons, const double delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit)
{ assert(delta > 0); return offset2_ex(polygons, - delta, delta, joinType, miterLimit); }
inline Slic3r::ExPolygons opening_ex(const Slic3r::Surfaces &surfaces, const double delta, ClipperLib::JoinType joinType = DefaultJoinType, double miterLimit = DefaultMiterLimit)
diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp
index 65295e837..77a3f2a59 100644
--- a/src/libslic3r/Config.cpp
+++ b/src/libslic3r/Config.cpp
@@ -1060,7 +1060,7 @@ ConfigSubstitutions ConfigBase::load_from_gcode_file(const std::string &file, Fo
for (; j < header.size() && header[j] != ' '; ++ j) ;
try {
Semver semver(header.substr(i, j - i));
- has_delimiters = semver >= Semver(2, 4, 0, nullptr, "alpha0");
+ has_delimiters = semver >= Semver(2, 4, 0, 0, nullptr, "alpha0");
} catch (const RuntimeError &) {
}
header_found = true;
diff --git a/src/libslic3r/Extruder.cpp b/src/libslic3r/Extruder.cpp
index cfbd5a248..1edad1857 100644
--- a/src/libslic3r/Extruder.cpp
+++ b/src/libslic3r/Extruder.cpp
@@ -77,6 +77,14 @@ double Tool::unretract()
return dE;
}
+// Called after a M600 or somethgin like that, so you don't have to unretract, but the absolute position won't change.
+void Tool::reset_retract() {
+ m_retracted = 0.;
+ m_restart_extra = 0.;
+ if (m_restart_extra_toolchange != 0)
+ m_restart_extra_toolchange = 0.;
+}
+
// Used filament volume in mm^3.
double Tool::extruded_volume() const
{
diff --git a/src/libslic3r/Extruder.hpp b/src/libslic3r/Extruder.hpp
index 8e1ac0f4f..9daec0dec 100644
--- a/src/libslic3r/Extruder.hpp
+++ b/src/libslic3r/Extruder.hpp
@@ -27,6 +27,7 @@ public:
virtual double extrude(double dE);
virtual double retract(double length, double restart_extra, double restart_extra_from_toolchange);
virtual double unretract();
+ virtual void reset_retract();
double E() const { return m_E; }
void reset_E() { m_E = 0.; }
double e_per_mm(double mm3_per_mm) const { return mm3_per_mm * m_e_per_mm3; }
diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp
index 2e67e0b0b..1c8a298f3 100644
--- a/src/libslic3r/ExtrusionEntity.cpp
+++ b/src/libslic3r/ExtrusionEntity.cpp
@@ -55,9 +55,11 @@ double ExtrusionPath::length() const
void ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const
{
+ ExtrusionEntitiesPtr to_add;
for (const Polyline &polyline : polylines)
- collection->entities.emplace_back(new ExtrusionPath(polyline, *this));
- }
+ to_add.emplace_back(new ExtrusionPath(polyline, *this));
+ collection->append(std::move(to_add));
+}
void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{
@@ -386,9 +388,9 @@ void ExtrusionPrinter::use(const ExtrusionLoop &loop) {
}
void ExtrusionPrinter::use(const ExtrusionEntityCollection &collection) {
ss << "ExtrusionEntityCollection:" << (uint16_t)collection.role() << "{";
- for (int i = 0; i < collection.entities.size(); i++) {
+ for (int i = 0; i < collection.entities().size(); i++) {
if (i != 0) ss << ",";
- collection.entities[i]->visit(*this);
+ collection.entities()[i]->visit(*this);
}
if(!collection.can_sort()) ss<<", no_sort=true";
ss << "}";
@@ -397,8 +399,8 @@ void ExtrusionPrinter::use(const ExtrusionEntityCollection &collection) {
void ExtrusionLength::default_use(const ExtrusionEntity& entity) { dist += entity.length(); };
void ExtrusionLength::use(const ExtrusionEntityCollection& collection) {
- for (int i = 0; i < collection.entities.size(); i++) {
- collection.entities[i]->visit(*this);
+ for (int i = 0; i < collection.entities().size(); i++) {
+ collection.entities()[i]->visit(*this);
}
}
@@ -419,7 +421,7 @@ void ExtrusionVisitorRecursiveConst::use(const ExtrusionLoop& loop) {
}
}
void ExtrusionVisitorRecursiveConst::use(const ExtrusionEntityCollection& collection) {
- for (const ExtrusionEntity* entity : collection.entities) {
+ for (const ExtrusionEntity* entity : collection.entities()) {
entity->visit(*this);
}
}
diff --git a/src/libslic3r/ExtrusionEntityCollection.cpp b/src/libslic3r/ExtrusionEntityCollection.cpp
index 1dd41f67f..3b6d7cf28 100644
--- a/src/libslic3r/ExtrusionEntityCollection.cpp
+++ b/src/libslic3r/ExtrusionEntityCollection.cpp
@@ -28,27 +28,27 @@ ExtrusionEntityCollection& ExtrusionEntityCollection::operator= (const Extrusion
{
this->no_sort = other.no_sort;
clear();
- this->append(other.entities);
+ this->append(other.m_entities);
return *this;
}
void ExtrusionEntityCollection::swap(ExtrusionEntityCollection &c)
{
- std::swap(this->entities, c.entities);
+ std::swap(this->m_entities, c.m_entities);
std::swap(this->no_sort, c.no_sort);
}
void ExtrusionEntityCollection::clear()
{
- for (size_t i = 0; i < this->entities.size(); ++i)
- delete this->entities[i];
- this->entities.clear();
+ for (size_t i = 0; i < this->m_entities.size(); ++i)
+ delete this->m_entities[i];
+ this->m_entities.clear();
}
ExtrusionEntityCollection::operator ExtrusionPaths() const
{
ExtrusionPaths paths;
- for (const ExtrusionEntity *ptr : this->entities) {
+ for (const ExtrusionEntity *ptr : this->entities()) {
if (const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ptr))
paths.push_back(*path);
}
@@ -57,26 +57,26 @@ ExtrusionEntityCollection::operator ExtrusionPaths() const
void ExtrusionEntityCollection::reverse()
{
- for (ExtrusionEntity *ptr : this->entities)
+ for (ExtrusionEntity *ptr : this->m_entities)
{
// Don't reverse it if it's a loop, as it doesn't change anything in terms of elements ordering
// and caller might rely on winding order
if (ptr->can_reverse() && !ptr->is_loop())
ptr->reverse();
}
- std::reverse(this->entities.begin(), this->entities.end());
+ std::reverse(this->m_entities.begin(), this->m_entities.end());
}
void ExtrusionEntityCollection::replace(size_t i, const ExtrusionEntity &entity)
{
- delete this->entities[i];
- this->entities[i] = entity.clone();
+ delete this->m_entities[i];
+ this->m_entities[i] = entity.clone();
}
void ExtrusionEntityCollection::remove(size_t i)
{
- delete this->entities[i];
- this->entities.erase(this->entities.begin() + i);
+ delete this->m_entities[i];
+ this->m_entities.erase(this->m_entities.begin() + i);
}
ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(const ExtrusionEntitiesPtr& extrusion_entities, const Point &start_near, ExtrusionRole role)
@@ -89,7 +89,7 @@ ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(const Ext
// if (role == erMixed)
// out = *this;
// else {
- // for (const ExtrusionEntity *ee : this->entities) {
+ // for (const ExtrusionEntity *ee : this->entities()) {
// if (role != erMixed) {
// // The caller wants only paths with a specific extrusion role.
// auto role2 = ee->role();
@@ -99,31 +99,31 @@ ExtrusionEntityCollection ExtrusionEntityCollection::chained_path_from(const Ext
// continue;
// }
// }
- // out.entities.emplace_back(ee->clone());
+ // out.entities().emplace_back(ee->clone());
// }
// }
- // chain_and_reorder_extrusion_entities(out.entities, &start_near);
+ // chain_and_reorder_extrusion_entities(out.entities(), &start_near);
//}
//return out;
// Return a filtered copy of the collection.
ExtrusionEntityCollection out;
- out.entities = filter_by_extrusion_role(extrusion_entities, role);
+ out.m_entities = filter_by_extrusion_role(extrusion_entities, role);
// Clone the extrusion entities.
- for (ExtrusionEntity* &ptr : out.entities)
+ for (ExtrusionEntity* &ptr : out.m_entities)
ptr = ptr->clone();
- chain_and_reorder_extrusion_entities(out.entities, &start_near);
+ chain_and_reorder_extrusion_entities(out.m_entities, &start_near);
return out;
}
void ExtrusionEntityCollection::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{
- for (const ExtrusionEntity *entity : this->entities)
+ for (const ExtrusionEntity *entity : this->entities())
entity->polygons_covered_by_width(out, scaled_epsilon);
}
void ExtrusionEntityCollection::polygons_covered_by_spacing(Polygons &out, const float spacing_ratio, const float scaled_epsilon) const
{
- for (const ExtrusionEntity *entity : this->entities)
+ for (const ExtrusionEntity *entity : this->entities())
entity->polygons_covered_by_spacing(out, spacing_ratio, scaled_epsilon);
}
@@ -135,7 +135,7 @@ size_t ExtrusionEntityCollection::items_count() const
void
CountEntities::use(const ExtrusionEntityCollection &coll) {
- for (const ExtrusionEntity* entity : coll.entities) {
+ for (const ExtrusionEntity* entity : coll.entities()) {
entity->visit(*this);
}
}
@@ -153,12 +153,12 @@ void
FlatenEntities::use(const ExtrusionEntityCollection &coll) {
if ((!coll.can_sort() || !this->to_fill.can_sort()) && preserve_ordering) {
FlatenEntities unsortable(coll, preserve_ordering);
- for (const ExtrusionEntity* entity : coll.entities) {
+ for (const ExtrusionEntity* entity : coll.entities()) {
entity->visit(unsortable);
}
to_fill.append(std::move(unsortable.to_fill));
} else {
- for (const ExtrusionEntity* entity : coll.entities) {
+ for (const ExtrusionEntity* entity : coll.entities()) {
entity->visit(*this);
}
}
diff --git a/src/libslic3r/ExtrusionEntityCollection.hpp b/src/libslic3r/ExtrusionEntityCollection.hpp
index 1274768cb..ac21bba48 100644
--- a/src/libslic3r/ExtrusionEntityCollection.hpp
+++ b/src/libslic3r/ExtrusionEntityCollection.hpp
@@ -29,6 +29,7 @@ private:
bool no_sort;
// even if no_sort, allow to reverse() us (and our entities if they allow it, but they should)
bool no_reverse;
+ ExtrusionEntitiesPtr m_entities; // we own these entities
public:
virtual ExtrusionEntityCollection* clone() const override { return new ExtrusionEntityCollection(*this); }
// Create a new object, initialize it with this object using the move semantics.
@@ -37,14 +38,15 @@ public:
/// Owned ExtrusionEntities and descendent ExtrusionEntityCollections.
/// Iterating over this needs to check each child to see if it, too is a collection.
- ExtrusionEntitiesPtr entities; // we own these entities
+ const ExtrusionEntitiesPtr& entities() const { return m_entities; }
+ ExtrusionEntitiesPtr& set_entities() { return m_entities; }
ExtrusionEntityCollection(): no_sort(false), no_reverse(false) {}
- ExtrusionEntityCollection(const ExtrusionEntityCollection &other) : no_sort(other.no_sort), no_reverse(other.no_reverse) { this->append(other.entities); }
- ExtrusionEntityCollection(ExtrusionEntityCollection &&other) : entities(std::move(other.entities)), no_sort(other.no_sort), no_reverse(other.no_reverse) {}
+ ExtrusionEntityCollection(const ExtrusionEntityCollection &other) : no_sort(other.no_sort), no_reverse(other.no_reverse) { this->append(other.entities()); }
+ ExtrusionEntityCollection(ExtrusionEntityCollection &&other) : m_entities(std::move(other.m_entities)), no_sort(other.no_sort), no_reverse(other.no_reverse) {}
explicit ExtrusionEntityCollection(const ExtrusionPaths &paths);
ExtrusionEntityCollection& operator=(const ExtrusionEntityCollection &other);
ExtrusionEntityCollection& operator=(ExtrusionEntityCollection &&other)
- { this->entities = std::move(other.entities); this->no_sort = other.no_sort; this->no_reverse = other.no_reverse; return *this; }
+ { this->m_entities = std::move(other.m_entities); this->no_sort = other.no_sort; this->no_reverse = other.no_reverse; return *this; }
~ExtrusionEntityCollection() { clear(); }
/// Operator to convert and flatten this collection to a single vector of ExtrusionPaths.
@@ -53,7 +55,7 @@ public:
bool is_collection() const override { return true; }
ExtrusionRole role() const override {
ExtrusionRole out = erNone;
- for (const ExtrusionEntity *ee : entities) {
+ for (const ExtrusionEntity *ee : m_entities) {
ExtrusionRole er = ee->role();
out = (out == erNone || out == er) ? er : erMixed;
}
@@ -62,33 +64,33 @@ public:
void set_can_sort_reverse(bool sort, bool reverse) { this->no_sort = !sort; this->no_reverse = !reverse; }
bool can_sort() const { return !this->no_sort; }
bool can_reverse() const override { return can_sort() || !this->no_reverse; }
- bool empty() const { return this->entities.empty(); }
+ bool empty() const { return this->m_entities.empty(); }
void clear();
void swap (ExtrusionEntityCollection &c);
- void append(const ExtrusionEntity &entity) { this->entities.emplace_back(entity.clone()); }
- void append(ExtrusionEntity &&entity) { this->entities.emplace_back(entity.clone_move()); }
+ void append(const ExtrusionEntity &entity) { this->m_entities.emplace_back(entity.clone()); }
+ void append(ExtrusionEntity &&entity) { this->m_entities.emplace_back(entity.clone_move()); }
void append(const ExtrusionEntitiesPtr &entities) {
- this->entities.reserve(this->entities.size() + entities.size());
+ this->m_entities.reserve(this->m_entities.size() + entities.size());
for (const ExtrusionEntity *ptr : entities)
- this->entities.emplace_back(ptr->clone());
+ this->m_entities.emplace_back(ptr->clone());
}
void append(ExtrusionEntitiesPtr &&src) {
- if (entities.empty())
- entities = std::move(src);
+ if (m_entities.empty())
+ m_entities = std::move(src);
else {
- std::move(std::begin(src), std::end(src), std::back_inserter(entities));
+ std::move(std::begin(src), std::end(src), std::back_inserter(m_entities));
src.clear();
}
}
void append(const ExtrusionPaths &paths) {
- this->entities.reserve(this->entities.size() + paths.size());
+ this->m_entities.reserve(this->m_entities.size() + paths.size());
for (const ExtrusionPath &path : paths)
- this->entities.emplace_back(path.clone());
+ this->m_entities.emplace_back(path.clone());
}
void append(ExtrusionPaths &&paths) {
- this->entities.reserve(this->entities.size() + paths.size());
+ this->m_entities.reserve(this->m_entities.size() + paths.size());
for (ExtrusionPath &path : paths)
- this->entities.emplace_back(new ExtrusionPath(std::move(path)));
+ this->m_entities.emplace_back(new ExtrusionPath(std::move(path)));
}
void replace(size_t i, const ExtrusionEntity &entity);
void remove(size_t i);
@@ -98,11 +100,11 @@ public:
if( this->no_sort || (role == erMixed) )
return *this;
else
- return chained_path_from(this->entities, start_near, role);
+ return chained_path_from(this->m_entities, start_near, role);
}
void reverse() override;
- const Point& first_point() const override { return this->entities.front()->first_point(); }
- const Point& last_point() const override { return this->entities.back()->last_point(); }
+ const Point& first_point() const override { return this->entities().front()->first_point(); }
+ const Point& last_point() const override { return this->entities().back()->last_point(); }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;
@@ -117,11 +119,11 @@ public:
/// Recursively count paths and loops contained in this collection
size_t items_count() const;
- /// Returns a flattened copy of this ExtrusionEntityCollection. That is, all of the items in its entities vector are not collections.
- /// You should be iterating over flatten().entities if you are interested in the underlying ExtrusionEntities (and don't care about hierarchy).
+ /// Returns a flattened copy of this ExtrusionEntityCollection. That is, all of the items in its entities() vector are not collections.
+ /// You should be iterating over flatten().entities() if you are interested in the underlying ExtrusionEntities (and don't care about hierarchy).
/// \param preserve_ordering Flag to method that will flatten if and only if the underlying collection is sortable when True (default: False).
ExtrusionEntityCollection flatten(bool preserve_ordering = false) const;
- double total_volume() const override { double volume=0.; for (const auto& ent : entities) volume+=ent->total_volume(); return volume; }
+ double total_volume() const override { double volume=0.; for (const auto& ent : entities()) volume+=ent->total_volume(); return volume; }
// Following methods shall never be called on an ExtrusionEntityCollection.
Polyline as_polyline() const override {
@@ -130,12 +132,12 @@ public:
};
void collect_polylines(Polylines &dst) const override {
- for (ExtrusionEntity* extrusion_entity : this->entities)
+ for (const ExtrusionEntity* extrusion_entity : this->entities())
extrusion_entity->collect_polylines(dst);
}
void collect_points(Points &dst) const override {
- for (ExtrusionEntity* extrusion_entity : this->entities)
+ for (ExtrusionEntity* extrusion_entity : this->entities())
extrusion_entity->collect_points(dst);
}
diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp
index d7ecef23a..c601a4342 100644
--- a/src/libslic3r/Fill/Fill.cpp
+++ b/src/libslic3r/Fill/Fill.cpp
@@ -423,19 +423,19 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
std::vector<ExtrusionEntityCollection*> fills_by_priority;
auto store_fill = [&fills_by_priority, this](size_t region_id) {
if (fills_by_priority.size() == 1) {
- m_regions[region_id]->fills.append(fills_by_priority[0]->entities);
+ m_regions[region_id]->fills.append(fills_by_priority[0]->entities());
delete fills_by_priority[0];
} else {
m_regions[region_id]->fills.set_can_sort_reverse(false, false);
ExtrusionEntityCollection* eec = new ExtrusionEntityCollection();
eec->set_can_sort_reverse(false, false);
- m_regions[region_id]->fills.entities.push_back(eec);
for (ExtrusionEntityCollection* per_priority : fills_by_priority) {
- if (!per_priority->entities.empty())
- eec->entities.push_back(per_priority);
+ if (!per_priority->entities().empty())
+ eec->set_entities().push_back(per_priority);
else
delete per_priority;
}
+ m_regions[region_id]->fills.append(ExtrusionEntitiesPtr{ eec });
}
fills_by_priority.clear();
};
@@ -506,6 +506,9 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
//union with safety offset to avoid separation from the appends of different surface with same settings.
surface_fill.expolygons = union_safety_offset_ex(surface_fill.expolygons);
+ //store default values, before modification.
+ bool dont_adjust = surface_fill.params.dont_adjust;
+ float density = surface_fill.params.density;
for (ExPolygon &expoly : surface_fill.expolygons) {
//set overlap polygons
f->no_overlap_expolygons.clear();
@@ -521,6 +524,11 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
f->no_overlap_expolygons.push_back(expoly);
}
+ //set default param (that can be modified by bridge thing)
+ surface_fill.params.dont_adjust = dont_adjust;
+ surface_fill.params.bridge_offset = 0;
+ surface_fill.params.density = density;
+
//init the surface with the current polygon
if (!expoly.contour.empty()) {
surface_fill.surface.expolygon = std::move(expoly);
@@ -543,6 +551,10 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
} else {
expolys = offset_ex(ExPolygon{surface_fill.surface.expolygon.contour}, -scale_t(surface_fill.params.spacing) / 2 - 10);
}
+ // if nothing after collapse, then go to next surface_fill.expolygon
+ if (expolys.empty())
+ continue;
+
BoundingBox bb;
bool first = true;
for (ExPolygon& expoly : expolys) {
@@ -589,7 +601,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
//make fill
while ((size_t)surface_fill.params.priority >= fills_by_priority.size())
fills_by_priority.push_back(new ExtrusionEntityCollection());
- f->fill_surface_extrusion(&surface_fill.surface, surface_fill.params, fills_by_priority[(size_t)surface_fill.params.priority]->entities);
+ f->fill_surface_extrusion(&surface_fill.surface, surface_fill.params, fills_by_priority[(size_t)surface_fill.params.priority]->set_entities());
}
}
}
@@ -601,32 +613,32 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
// The path type could be ExtrusionPath, ExtrusionLoop or ExtrusionEntityCollection.
// Why the paths are unpacked?
for (LayerRegion *layerm : m_regions)
- for (const ExtrusionEntity *thin_fill : layerm->thin_fills.entities) {
+ for (const ExtrusionEntity *thin_fill : layerm->thin_fills.entities()) {
ExtrusionEntityCollection *collection = new ExtrusionEntityCollection();
- if (!layerm->fills.can_sort() && layerm->fills.entities.size() > 0 && layerm->fills.entities[0]->is_collection()) {
- ExtrusionEntityCollection* no_sort_fill = static_cast<ExtrusionEntityCollection*>(layerm->fills.entities[0]);
- if (!no_sort_fill->can_sort() && no_sort_fill->entities.size() > 0 && no_sort_fill->entities[0]->is_collection())
- static_cast<ExtrusionEntityCollection*>(no_sort_fill->entities[0])->entities.push_back(collection);
+ if (!layerm->fills.can_sort() && layerm->fills.entities().size() > 0 && layerm->fills.entities()[0]->is_collection()) {
+ ExtrusionEntityCollection* no_sort_fill = static_cast<ExtrusionEntityCollection*>(layerm->fills.entities()[0]);
+ if (!no_sort_fill->can_sort() && no_sort_fill->entities().size() > 0 && no_sort_fill->entities()[0]->is_collection())
+ static_cast<ExtrusionEntityCollection*>(no_sort_fill->entities()[0])->append(ExtrusionEntitiesPtr{ collection });
} else
- layerm->fills.entities.push_back(collection);
- collection->entities.push_back(thin_fill->clone());
+ layerm->fills.append(ExtrusionEntitiesPtr{ collection });
+ collection->append(*thin_fill);
}
#ifndef NDEBUG
for (LayerRegion *layerm : m_regions)
- for (size_t i1 = 0; i1 < layerm->fills.entities.size(); ++i1) {
- assert(dynamic_cast<ExtrusionEntityCollection*>(layerm->fills.entities[i1]) != nullptr);
- if (!layerm->fills.can_sort() && layerm->fills.entities.size() > 0 && i1 == 0){
- ExtrusionEntityCollection* no_sort_fill = static_cast<ExtrusionEntityCollection*>(layerm->fills.entities[0]);
+ for (size_t i1 = 0; i1 < layerm->fills.entities().size(); ++i1) {
+ assert(dynamic_cast<ExtrusionEntityCollection*>(layerm->fills.entities()[i1]) != nullptr);
+ if (!layerm->fills.can_sort() && layerm->fills.entities().size() > 0 && i1 == 0){
+ ExtrusionEntityCollection* no_sort_fill = static_cast<ExtrusionEntityCollection*>(layerm->fills.entities()[0]);
assert(no_sort_fill != nullptr);
assert(!no_sort_fill->empty());
- for (size_t i2 = 0; i2 < no_sort_fill->entities.size(); ++i2) {
- ExtrusionEntityCollection* priority_fill = dynamic_cast<ExtrusionEntityCollection*>(no_sort_fill->entities[i2]);
+ for (size_t i2 = 0; i2 < no_sort_fill->entities().size(); ++i2) {
+ ExtrusionEntityCollection* priority_fill = dynamic_cast<ExtrusionEntityCollection*>(no_sort_fill->entities()[i2]);
assert(priority_fill != nullptr);
assert(!priority_fill->empty());
if (!no_sort_fill->can_sort()) {
- for (size_t i3 = 0; i3 < priority_fill->entities.size(); ++i3)
- assert(dynamic_cast<ExtrusionEntityCollection*>(priority_fill->entities[i3]) != nullptr);
+ for (size_t i3 = 0; i3 < priority_fill->entities().size(); ++i3)
+ assert(dynamic_cast<ExtrusionEntityCollection*>(priority_fill->entities()[i3]) != nullptr);
}
}
}
@@ -833,11 +845,11 @@ void Layer::make_ironing()
if (! polylines.empty()) {
// Save into layer.
ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
- ironing_params.layerm->ironings.entities.push_back(eec);
+ ironing_params.layerm->ironings.append(ExtrusionEntitiesPtr{ eec });
// Don't sort the ironing infill lines as they are monotonicly ordered.
eec->set_can_sort_reverse(false, false);
extrusion_entities_append_paths(
- eec->entities, std::move(polylines),
+ eec->set_entities(), std::move(polylines),
erIroning,
//FIXME FLOW decide if it's good
flow_mm3_per_mm, extrusion_width/*float(flow.width())*/, extrusion_height/*float(height)*/);
diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp
index 7c4dccf14..a3e237135 100644
--- a/src/libslic3r/Fill/FillBase.cpp
+++ b/src/libslic3r/Fill/FillBase.cpp
@@ -227,7 +227,7 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams &para
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
/// push the path
extrusion_entities_append_paths(
- eec->entities, std::move(polylines),
+ eec->set_entities(), std::move(polylines),
good_role,
params.flow.mm3_per_mm() * params.flow_mult * mult_flow,
(float)(params.flow.width() * params.flow_mult * mult_flow),
@@ -278,17 +278,18 @@ Fill::do_gap_fill(const ExPolygons& gapfill_areas, const FillParams& params, Ext
}
#endif
- ExtrusionEntityCollection gap_fill = Geometry::thin_variable_width(polylines_gapfill, erGapFill, params.flow, scale_t(params.config->get_computed_value("resolution_internal")));
- //set role if needed
- /*if (params.role != erSolidInfill) {
- ExtrusionSetRole set_good_role(params.role);
- gap_fill.visit(set_good_role);
- }*/
+ ExtrusionEntitiesPtr gap_fill_entities = Geometry::thin_variable_width(polylines_gapfill, erGapFill, params.flow, scale_t(params.config->get_computed_value("resolution_internal")));
+ ////set role if needed
+ //if (params.role != erSolidInfill) {
+ // ExtrusionSetRole set_good_role(params.role);
+ // for(ExtrusionEntity *ptr : gap_fill_entities)
+ // ptr->visit(set_good_role);
+ //}
//move them into the collection
- if (!gap_fill.entities.empty()) {
+ if (!gap_fill_entities.empty()) {
ExtrusionEntityCollection* coll_gapfill = new ExtrusionEntityCollection();
coll_gapfill->set_can_sort_reverse(!this->no_sort(), !this->no_sort());
- coll_gapfill->append(std::move(gap_fill.entities));
+ coll_gapfill->append(std::move(gap_fill_entities));
coll_out.push_back(coll_gapfill);
}
}
diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp
index 0f64a64d3..fe1ea4c7c 100644
--- a/src/libslic3r/Fill/FillBase.hpp
+++ b/src/libslic3r/Fill/FillBase.hpp
@@ -218,7 +218,7 @@ public:
void use(ExtrusionMultiPath &multipath) override { for (ExtrusionPath path : multipath.paths) path.set_role(new_role); }
void use(ExtrusionMultiPath3D &multipath) override { for (ExtrusionPath path : multipath.paths) path.set_role(new_role); }
void use(ExtrusionLoop &loop) override { for (ExtrusionPath path : loop.paths) path.set_role(new_role); }
- void use(ExtrusionEntityCollection &collection) override { for (ExtrusionEntity *entity : collection.entities) entity->visit(*this); }
+ void use(ExtrusionEntityCollection &collection) override { for (ExtrusionEntity *entity : collection.entities()) entity->visit(*this); }
};
} // namespace Slic3r
diff --git a/src/libslic3r/Fill/FillConcentric.cpp b/src/libslic3r/Fill/FillConcentric.cpp
index 7899f545d..d3ce85bf4 100644
--- a/src/libslic3r/Fill/FillConcentric.cpp
+++ b/src/libslic3r/Fill/FillConcentric.cpp
@@ -132,7 +132,7 @@ FillConcentricWGapFill::fill_surface_extrusion(
ExtrusionEntityCollection *coll_nosort = new ExtrusionEntityCollection();
coll_nosort->set_can_sort_reverse(false, false); //can be sorted inside the pass
extrusion_entities_append_loops(
- coll_nosort->entities, loops,
+ coll_nosort->set_entities(), loops,
good_role,
params.flow.mm3_per_mm() * params.flow_mult,
params.flow.width() * params.flow_mult,
@@ -156,18 +156,21 @@ FillConcentricWGapFill::fill_surface_extrusion(
}
}
if (!polylines.empty() && !is_bridge(good_role)) {
- ExtrusionEntityCollection gap_fill = Geometry::thin_variable_width(polylines, erGapFill, params.flow, scale_t(params.config->get_computed_value("resolution_internal")));
- //set role if needed
- if (good_role != erSolidInfill) {
- ExtrusionSetRole set_good_role(good_role);
- gap_fill.visit(set_good_role);
+ ExtrusionEntitiesPtr gap_fill_entities = Geometry::thin_variable_width(polylines, erGapFill, params.flow, scale_t(params.config->get_computed_value("resolution_internal")));
+ if (!gap_fill_entities.empty()) {
+ //set role if needed
+ if (good_role != erSolidInfill) {
+ ExtrusionSetRole set_good_role(good_role);
+ for (ExtrusionEntity* ptr : gap_fill_entities)
+ ptr->visit(set_good_role);
+ }
+ //move them into the collection
+ coll_nosort->append(std::move(gap_fill_entities));
}
- //move them into the collection
- coll_nosort->append(std::move(gap_fill.entities));
}
}
- if (!coll_nosort->entities.empty())
+ if (!coll_nosort->entities().empty())
out.push_back(coll_nosort);
else delete coll_nosort;
}
diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp
index 27acd2b4c..e04c63d8c 100644
--- a/src/libslic3r/Fill/FillRectilinear.cpp
+++ b/src/libslic3r/Fill/FillRectilinear.cpp
@@ -3277,12 +3277,12 @@ FillRectilinearPeri::fill_surface_extrusion(const Surface *surface, const FillPa
/// pass the no_sort attribute to the extrusion path
eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort());
/// add it into the collection
- eecroot->entities.push_back(eec);
+ eecroot->append(ExtrusionEntitiesPtr{ eec });
//get the role
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
/// push the path
extrusion_entities_append_paths(
- eec->entities,
+ eec->set_entities(),
polylines_1,
good_role,
params.flow.mm3_per_mm() * params.flow_mult,
@@ -3309,12 +3309,12 @@ FillRectilinearPeri::fill_surface_extrusion(const Surface *surface, const FillPa
/// pass the no_sort attribute to the extrusion path
eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort());
/// add it into the collection
- eecroot->entities.push_back(eec);
+ eecroot->append(ExtrusionEntitiesPtr{ eec });
//get the role
ExtrusionRole good_role = getRoleFromSurfaceType(params, surface);
/// push the path
extrusion_entities_append_paths(
- eec->entities,
+ eec->set_entities(),
polylines_2,
good_role,
params.flow.mm3_per_mm() * params.flow_mult,
@@ -3499,7 +3499,7 @@ FillRectilinearSawtooth::fill_surface_extrusion(const Surface *surface, const Fi
idx++;
}
if (current_extrusion->size() < 2) extrusions->paths.pop_back();
- if (!extrusions->paths.empty()) eec->entities.push_back(extrusions);
+ if (!extrusions->paths.empty()) eec->append(ExtrusionEntitiesPtr{ extrusions });
else delete extrusions;
}
// === end ===
@@ -3607,13 +3607,13 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi
eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort());
extrusion_entities_append_paths(
- eec->entities, polylines_rectilinear,
+ eec->set_entities(), polylines_rectilinear,
good_role,
params.flow.mm3_per_mm() * params.flow_mult * flow_mult_exact_volume,
params.flow.width() * params.flow_mult * float(flow_mult_exact_volume),
params.flow.height());
- coll_nosort->entities.push_back(eec);
+ coll_nosort->append(ExtrusionEntitiesPtr{ eec });
unextruded_areas = diff_ex(rectilinear_areas, union_safety_offset_ex(eec->polygons_covered_by_spacing(params.flow.spacing_ratio(), 10)));
}
@@ -3634,7 +3634,7 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi
FillParams params2{ params };
params2.role = good_role;
- do_gap_fill(intersection_ex(gapfill_areas, no_overlap_expolygons), params2, coll_nosort->entities);
+ do_gap_fill(intersection_ex(gapfill_areas, no_overlap_expolygons), params2, coll_nosort->set_entities());
}
// === end ===
diff --git a/src/libslic3r/Fill/FillSmooth.cpp b/src/libslic3r/Fill/FillSmooth.cpp
index e9e3d2700..e09f6fe84 100644
--- a/src/libslic3r/Fill/FillSmooth.cpp
+++ b/src/libslic3r/Fill/FillSmooth.cpp
@@ -56,8 +56,8 @@ namespace Slic3r {
}
}
- if (eec->entities.empty()) delete eec;
- else eecroot.entities.push_back(eec);
+ if (eec->entities().empty()) delete eec;
+ else eecroot.append(ExtrusionEntitiesPtr{ eec });
}
void FillSmooth::fill_expolygon(const int idx, ExtrusionEntityCollection &eec, const Surface &srf_to_fill,
@@ -115,7 +115,7 @@ namespace Slic3r {
}
extrusion_entities_append_paths(
- eec.entities, std::move(polylines_layer),
+ eec.set_entities(), std::move(polylines_layer),
good_role,
params.flow.mm3_per_mm() * params.flow_mult * mult_flow,
//min-reduced flow width for a better view (it's mostly a gui thing, but some support code can want to mess with it)
@@ -153,7 +153,7 @@ namespace Slic3r {
perform_single_fill(2, *eecroot, *surface, monotonic_params);
}
- if (!eecroot->entities.empty())
+ if (!eecroot->entities().empty())
out.push_back(eecroot);
else delete eecroot;
diff --git a/src/libslic3r/Format/AMF.cpp b/src/libslic3r/Format/AMF.cpp
index 25f8a34d8..d737dc463 100644
--- a/src/libslic3r/Format/AMF.cpp
+++ b/src/libslic3r/Format/AMF.cpp
@@ -115,17 +115,27 @@ struct AMFParserContext
ctx->characters(s, len);
}
- static const char* get_attribute(const char **atts, const char *id) {
+ static const char* get_attribute(const char** atts, const char* id) {
if (atts == nullptr)
return nullptr;
while (*atts != nullptr) {
- if (strcmp(*(atts ++), id) == 0)
+ if (strcmp(*(atts++), id) == 0)
return *atts;
- ++ atts;
+ ++atts;
}
return nullptr;
}
+ static const char* get_not_null_attribute(const char** atts, const char* id) {
+ const char* str = get_attribute(atts, id);
+ if (str == nullptr) {
+ char error_buf[1024];
+ ::sprintf(error_buf, "Error, missing tag %s", id);
+ throw Slic3r::FileIOError(error_buf);
+ }
+ return str;
+ }
+
enum AMFNodeType {
NODE_TYPE_INVALID = 0,
NODE_TYPE_UNKNOWN,
@@ -306,7 +316,7 @@ void AMFParserContext::startElement(const char *name, const char **atts)
case 2:
if (strcmp(name, "metadata") == 0) {
if (m_path[1] == NODE_TYPE_MATERIAL || m_path[1] == NODE_TYPE_OBJECT) {
- m_value[0] = get_attribute(atts, "type");
+ m_value[0] = get_not_null_attribute(atts, "type");
node_type_new = NODE_TYPE_METADATA;
}
} else if (strcmp(name, "layer_config_ranges") == 0 && m_path[1] == NODE_TYPE_OBJECT)
@@ -331,19 +341,19 @@ void AMFParserContext::startElement(const char *name, const char **atts)
else if (m_path[1] == NODE_TYPE_CUSTOM_GCODE) {
if (strcmp(name, "code") == 0) {
node_type_new = NODE_TYPE_GCODE_PER_HEIGHT;
- m_value[0] = get_attribute(atts, "print_z");
- m_value[1] = get_attribute(atts, "extruder");
- m_value[2] = get_attribute(atts, "color");
+ m_value[0] = get_not_null_attribute(atts, "print_z");
+ m_value[1] = get_not_null_attribute(atts, "extruder");
+ m_value[2] = get_not_null_attribute(atts, "color");
if (get_attribute(atts, "type"))
{
- m_value[3] = get_attribute(atts, "type");
- m_value[4] = get_attribute(atts, "extra");
+ m_value[3] = get_not_null_attribute(atts, "type");
+ m_value[4] = get_not_null_attribute(atts, "extra");
}
else
{
// It means that data was saved in old version (2.2.0 and older) of PrusaSlicer
// read old data ...
- std::string gcode = get_attribute(atts, "gcode");
+ std::string gcode = get_not_null_attribute(atts, "gcode");
// ... and interpret them to the new data
CustomGCode::Type type= gcode == "M600" ? CustomGCode::ColorChange :
gcode == "M601" ? CustomGCode::PausePrint :
@@ -355,7 +365,7 @@ void AMFParserContext::startElement(const char *name, const char **atts)
}
else if (strcmp(name, "mode") == 0) {
node_type_new = NODE_TYPE_CUSTOM_GCODE_MODE;
- m_value[0] = get_attribute(atts, "value");
+ m_value[0] = get_not_null_attribute(atts, "value");
}
}
break;
@@ -423,7 +433,7 @@ void AMFParserContext::startElement(const char *name, const char **atts)
node_type_new = NODE_TYPE_TRIANGLE;
}
else if (m_path[3] == NODE_TYPE_RANGE && strcmp(name, "metadata") == 0) {
- m_value[0] = get_attribute(atts, "type");
+ m_value[0] = get_not_null_attribute(atts, "type");
node_type_new = NODE_TYPE_METADATA;
}
break;
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 97a6a8906..9908ec315 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -996,7 +996,7 @@ namespace DoExport {
use(path);
}
virtual void use(const ExtrusionEntityCollection& collection) override {
- for (const ExtrusionEntity* entity : collection.entities)
+ for (const ExtrusionEntity* entity : collection.entities())
entity->visit(*this);
}
double reset_use_get(const ExtrusionEntityCollection entity) { reset(); use(entity); return get(); }
@@ -1069,7 +1069,7 @@ namespace DoExport {
// Calculate wiping points if needed
if (print.config().ooze_prevention.value && ! print.config().single_extruder_multi_material) {
Points skirt_points;
- for (const ExtrusionEntity *ee : print.skirt().entities)
+ for (const ExtrusionEntity *ee : print.skirt().entities())
for (const ExtrusionPath &path : dynamic_cast<const ExtrusionLoop*>(ee)->paths)
append(skirt_points, path.polyline.points);
if (! skirt_points.empty()) {
@@ -1571,7 +1571,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
m_placeholder_parser.set("print_bed_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() }));
m_placeholder_parser.set("print_bed_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() }));
}
- {
+ if(!print.config().complete_objects.value){
// Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
// It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
// It does NOT encompass user extrusions generated by custom G-code,
@@ -1586,6 +1586,68 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
m_placeholder_parser.set("first_layer_print_min", new ConfigOptionFloats({ bbox.min.x(), bbox.min.y() }));
m_placeholder_parser.set("first_layer_print_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() }));
m_placeholder_parser.set("first_layer_print_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() }));
+ } else {
+ //have to compute it ourself :-/
+ class BoundingBoxVisitor : public ExtrusionVisitorRecursiveConst {
+ public:
+ Point offset;
+ Points hull;
+ virtual void use(const ExtrusionPath& path) override {
+ for (Point pt : path.polyline.points) {
+ pt += offset;
+ hull.emplace_back(std::move(pt));
+ }
+ }
+ virtual void use(const ExtrusionPath3D& path3D) override {
+ for (Point pt : path3D.polyline.points) {
+ pt += offset;
+ hull.emplace_back(std::move(pt));
+ }
+ }
+ BoundingBoxf get_bb() {
+ BoundingBox bbox(hull);
+ return BoundingBoxf(unscaled(bbox.min), unscaled(bbox.max));
+ }
+ Polygon get_hull() { return Geometry::convex_hull(hull); }
+ } bbvisitor;
+ if (print.skirt_first_layer().has_value()) {
+ print.skirt_first_layer()->visit(bbvisitor);
+ } else if (print.skirt().entities().size() > 0) {
+ print.skirt().visit(bbvisitor);
+ } else if (print.config().complete_objects_one_brim.value && !print.brim().empty()) {
+ print.brim().visit(bbvisitor);
+ } else {
+ print.brim().visit(bbvisitor);
+ for (const PrintObject* po : print.objects()) {
+ for (const PrintInstance& inst : po->instances()) {
+ bbvisitor.offset = inst.shift;
+ if (po->skirt_first_layer().has_value()) {
+ po->skirt_first_layer()->visit(bbvisitor);
+ } else if (po->skirt().entities().size() > 0) {
+ po->skirt().visit(bbvisitor);
+ } else {
+ po->brim().visit(bbvisitor);
+ if (po->layers().empty()) continue;
+ const Layer* l = po->layers().front();
+ if (l->id() != 0) continue;
+ for (const LayerRegion* lr : l->regions()) {
+ lr->perimeters.visit(bbvisitor);
+ lr->fills.visit(bbvisitor);
+ }
+ }
+ }
+ }
+ }
+ BoundingBoxf bbox = bbvisitor.get_bb();
+ Polygon first_layer_hull = bbvisitor.get_hull();
+ auto pts = std::make_unique<ConfigOptionPoints>();
+ pts->values.reserve(first_layer_hull.size());
+ for (const Point& pt : first_layer_hull.points)
+ pts->values.emplace_back(unscale(pt));
+ m_placeholder_parser.set("first_layer_print_convex_hull", pts.release());
+ m_placeholder_parser.set("first_layer_print_min", new ConfigOptionFloats({ bbox.min.x(), bbox.min.y() }));
+ m_placeholder_parser.set("first_layer_print_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() }));
+ m_placeholder_parser.set("first_layer_print_size", new ConfigOptionFloats({ bbox.size().x(), bbox.size().y() }));
}
//misc
if (config().thumbnails_color.value.length() == 7) {
@@ -1692,7 +1754,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
}
// ensure the first tool doesn't "extra_retract"
- m_writer.unretract();
+ m_writer.tool()->reset_retract();
//write temps after custom gcodes to ensure the temperature are good. (after tool selection)
if ((initial_extruder_id != (uint16_t)-1) && !this->config().start_gcode_manual && print.config().first_layer_temperature.get_at(initial_extruder_id) != 0)
@@ -2419,7 +2481,8 @@ std::string emit_custom_gcode_per_print_z(
//FIXME Tell G-code writer that M600 filled the extruder, thus the G-code writer shall reset the extruder to unretracted state after
// return from M600. Thus the G-code generated by the following line is ignored.
// see GH issue #6362
- gcodegen.writer().unretract();
+ // merill: don't unretract, as it create problem on absolute position. Clear the retraction properley, plz.
+ gcodegen.writer().tool()->reset_retract();
}
}
else {
@@ -2453,7 +2516,7 @@ namespace Skirt {
static void skirt_loops_per_extruder_all_printing(const Print &print, const LayerTools &layer_tools, std::map<uint16_t, std::pair<size_t, size_t>> &skirt_loops_per_extruder_out)
{
// Prime all extruders printing over the 1st layer over the skirt lines.
- size_t n_loops = print.skirt().entities.size();
+ size_t n_loops = print.skirt().entities().size();
size_t n_tools = layer_tools.extruders.size();
size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
for (size_t i = 0; i < n_loops; i += lines_per_extruder)
@@ -2471,9 +2534,9 @@ namespace Skirt {
std::map<uint16_t, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
//For sequential print, the following test may fail when extruding the 2nd and other objects.
// assert(skirt_done.empty());
- if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt) {
+ if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities().empty() && layer_tools.has_skirt) {
if (print.skirt_first_layer()) {
- size_t n_loops = print.skirt_first_layer()->entities.size();
+ size_t n_loops = print.skirt_first_layer()->entities().size();
size_t n_tools = layer_tools.extruders.size();
size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
for (size_t i = 0; i < n_loops; i += lines_per_extruder)
@@ -2494,7 +2557,7 @@ namespace Skirt {
// Extrude skirt at the print_z of the raft layers and normal object layers
// not at the print_z of the interlaced support material layers.
std::map<uint16_t, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
- if (print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt &&
+ if (print.has_skirt() && ! print.skirt().entities().empty() && layer_tools.has_skirt &&
// infinite or high skirt does not make sense for sequential print here
//(if it is selected, it's done in the "extrude object-only skirt" in process_layer)
// Not enough skirt layers printed yet.
@@ -2689,7 +2752,7 @@ GCode::LayerResult GCode::process_layer(
if (layer_to_print.support_layer != nullptr) {
const SupportLayer &support_layer = *layer_to_print.support_layer;
const PrintObject &object = *support_layer.object();
- if (! support_layer.support_fills.entities.empty()) {
+ if (! support_layer.support_fills.entities().empty()) {
ExtrusionRole role = support_layer.support_fills.role();
bool has_support = role == erMixed || role == erSupportMaterial;
bool has_interface = role == erMixed || role == erSupportMaterialInterface;
@@ -2781,7 +2844,7 @@ GCode::LayerResult GCode::process_layer(
// extrusions represents infill or perimeter extrusions of a single island.
assert(dynamic_cast<const ExtrusionEntityCollection*>(ee) != nullptr);
const auto* extrusions = static_cast<const ExtrusionEntityCollection*>(ee);
- if (extrusions->entities.empty()) // This shouldn't happen but first_point() would fail.
+ if (extrusions->entities().empty()) // This shouldn't happen but first_point() would fail.
continue;
// This extrusion is part of certain Region, which tells us which extruder should be used for it:
@@ -2836,9 +2899,9 @@ GCode::LayerResult GCode::process_layer(
}
}
};
- process_entities(ObjectByExtruder::Island::Region::INFILL, layerm->fills.entities);
- process_entities(ObjectByExtruder::Island::Region::PERIMETERS, layerm->perimeters.entities);
- process_entities(ObjectByExtruder::Island::Region::IRONING, layerm->ironings.entities);
+ process_entities(ObjectByExtruder::Island::Region::INFILL, layerm->fills.entities());
+ process_entities(ObjectByExtruder::Island::Region::PERIMETERS, layerm->perimeters.entities());
+ process_entities(ObjectByExtruder::Island::Region::IRONING, layerm->ironings.entities());
} // for regions
}
} // for objects
@@ -2870,7 +2933,7 @@ GCode::LayerResult GCode::process_layer(
const ExtrusionEntityCollection& coll = first_layer && print.skirt_first_layer() ? *print.skirt_first_layer() : print.skirt();
for (size_t i = loops.first; i < loops.second; ++i) {
// Adjust flow according to this layer's layer height.
- ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(coll.entities[i]);
+ ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(coll.entities()[i]);
for (ExtrusionPath &path : loop.paths) {
assert(!std::isnan(layer_skirt_flow.height()));
assert(!std::isnan(mm3_per_mm));
@@ -2892,7 +2955,7 @@ GCode::LayerResult GCode::process_layer(
if (! m_brim_done) {
this->set_origin(0., 0.);
m_avoid_crossing_perimeters.use_external_mp();
- for (const ExtrusionEntity* brim_entity : print.brim().entities) {
+ for (const ExtrusionEntity* brim_entity : print.brim().entities()) {
//if first layer, ask for a bigger lift for travel to each brim, to be on the safe side
set_extra_lift(m_last_layer_z, layer.id(), print.config(), m_writer, extruder_id);
gcode += this->extrude_entity(*brim_entity, "Brim", m_config.support_material_speed.value);
@@ -2913,10 +2976,10 @@ GCode::LayerResult GCode::process_layer(
this->set_origin(unscale(print_object->instances()[single_object_instance_idx].shift));
if (this->m_layer != nullptr && (this->m_layer->id() < m_config.skirt_height || print.has_infinite_skirt() )) {
if(first_layer && print.skirt_first_layer())
- for (const ExtrusionEntity* ee : print_object->skirt_first_layer()->entities)
+ for (const ExtrusionEntity* ee : print_object->skirt_first_layer()->entities())
gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value);
else
- for (const ExtrusionEntity *ee : print_object->skirt().entities)
+ for (const ExtrusionEntity *ee : print_object->skirt().entities())
gcode += this->extrude_entity(*ee, "", m_config.support_material_speed.value);
}
}
@@ -2928,7 +2991,7 @@ GCode::LayerResult GCode::process_layer(
this->set_origin(unscale(print_object->instances()[single_object_instance_idx].shift));
if (this->m_layer != nullptr && this->m_layer->id() == 0) {
m_avoid_crossing_perimeters.use_external_mp(true);
- for (const ExtrusionEntity *ee : print_object->brim().entities)
+ for (const ExtrusionEntity *ee : print_object->brim().entities())
gcode += this->extrude_entity(*ee, "brim", m_config.support_material_speed.value);
m_avoid_crossing_perimeters.use_external_mp(false);
m_avoid_crossing_perimeters.disable_once();
@@ -3908,19 +3971,19 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, const std::stri
void GCode::use(const ExtrusionEntityCollection &collection) {
if (!collection.can_sort() || collection.role() == erMixed) {
- for (const ExtrusionEntity* next_entity : collection.entities) {
+ for (const ExtrusionEntity* next_entity : collection.entities()) {
next_entity->visit(*this);
}
} else {
ExtrusionEntityCollection chained = collection.chained_path_from(m_last_pos);
- for (const ExtrusionEntity* next_entity : chained.entities) {
+ for (const ExtrusionEntity* next_entity : chained.entities()) {
next_entity->visit(*this);
}
}
}
std::string GCode::extrude_path(const ExtrusionPath &path, const std::string &description, double speed_mm_per_sec) {
-
+ std::string gcode;
ExtrusionPath simplifed_path = path;
const coordf_t scaled_min_length = scale_d(this->config().min_length.value);
const double max_gcode_per_second = this->config().max_gcode_per_second.value;
@@ -3929,17 +3992,20 @@ std::string GCode::extrude_path(const ExtrusionPath &path, const std::string &de
current_scaled_min_length = std::max(current_scaled_min_length, scale_(_compute_speed_mm_per_sec(path, speed_mm_per_sec)) / max_gcode_per_second);
}
if (current_scaled_min_length > 0 && !m_last_too_small.empty()) {
- //descr += " trys fusion " + std::to_string(unscaled(m_last_too_small.last_point().x())) + " , " + std::to_string(unscaled(path.first_point().x()));
- //ensure that it's a continous thing
- if (m_last_too_small.last_point().distance_to_square(path.first_point()) < current_scaled_min_length * current_scaled_min_length /*&& m_last_too_small.first_point().distance_to_square(path.first_point()) > EPSILON*/) {
- //descr += " ! fusion " + std::to_string(simplifed_path.polyline.points.size());
+ //ensure that it's a continous thing of the same type
+ if (m_last_too_small.last_point().distance_to_square(path.first_point()) < EPSILON * EPSILON * 4 && path.role() == m_last_too_small.role()){
simplifed_path.height = float(m_last_too_small.height * m_last_too_small.length() + simplifed_path.height * simplifed_path.length()) / float(m_last_too_small.length() + simplifed_path.length());
simplifed_path.mm3_per_mm = (m_last_too_small.mm3_per_mm * m_last_too_small.length() + simplifed_path.mm3_per_mm * simplifed_path.length()) / (m_last_too_small.length() + simplifed_path.length());
simplifed_path.polyline.points.insert(simplifed_path.polyline.points.begin(), m_last_too_small.polyline.points.begin(), m_last_too_small.polyline.points.end()-1);
assert(simplifed_path.height == simplifed_path.height);
assert(simplifed_path.mm3_per_mm == simplifed_path.mm3_per_mm);
+ m_last_too_small.polyline.points.clear();
+ } else {
+ //finish extrude the little thing that was left before us and incompatible with our next extrusion.
+ ExtrusionPath to_finish = m_last_too_small;
+ m_last_too_small.polyline.points.clear();
+ gcode += extrude_path(m_last_too_small, m_last_description, m_last_speed_mm_per_sec);
}
- m_last_too_small.polyline.points.clear();
}
if (current_scaled_min_length > 0) {
// it's an alternative to simplifed_path.simplify(scale_(this->config().min_length)); with more enphasis ont he segment length that on the feature detail.
@@ -3950,10 +4016,12 @@ std::string GCode::extrude_path(const ExtrusionPath &path, const std::string &de
simplifed_path.simplify(m_scaled_resolution); //should already be simplified, but maybe not with gcode_resolution
if (scaled_min_length > 0 && simplifed_path.length() < scaled_min_length) {
m_last_too_small = simplifed_path;
- return "";
+ m_last_description = description;
+ m_last_speed_mm_per_sec = speed_mm_per_sec;
+ return gcode;
}
- std::string gcode = this->_extrude(simplifed_path, description, speed_mm_per_sec);
+ gcode += this->_extrude(simplifed_path, description, speed_mm_per_sec);
if (m_wipe.enable) {
m_wipe.path = std::move(simplifed_path.polyline);
@@ -4084,10 +4152,10 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
static constexpr const char *support_interface_label = "support material interface";
std::string gcode;
- if (! support_fills.entities.empty()) {
+ if (! support_fills.entities().empty()) {
const double support_speed = m_config.support_material_speed.value;
const double support_interface_speed = m_config.support_material_interface_speed.get_abs_value(support_speed);
- for (const ExtrusionEntity *ee : support_fills.entities) {
+ for (const ExtrusionEntity *ee : support_fills.entities()) {
ExtrusionRole role = ee->role();
assert(role == erSupportMaterial || role == erSupportMaterialInterface || role == erMixed);
if (const ExtrusionEntityCollection* coll = dynamic_cast<const ExtrusionEntityCollection*>(ee)) {
@@ -4835,6 +4903,7 @@ Polyline GCode::travel_to(std::string &gcode, const Point &point, ExtrusionRole
Polyline travel { this->last_pos(), point };
// check whether wipe could be disabled without causing visible stringing
+ //not used anymore, not reliable
bool could_be_wipe_disabled = false;
// Save state of use_external_mp_once for the case that will be needed to call twice m_avoid_crossing_perimeters.travel_to.
const bool used_external_mp_once = m_avoid_crossing_perimeters.used_external_mp_once();
@@ -4867,8 +4936,15 @@ Polyline GCode::travel_to(std::string &gcode, const Point &point, ExtrusionRole
// generate G-code for the travel move
if (needs_retraction) {
- if (m_config.avoid_crossing_perimeters && could_be_wipe_disabled && EXTRUDER_CONFIG_WITH_DEFAULT(wipe_only_crossing, true))
- m_wipe.reset_path();
+ if (m_config.avoid_crossing_perimeters && EXTRUDER_CONFIG_WITH_DEFAULT(wipe_only_crossing, true)) {
+ //if (could_be_wipe_disabled) {
+ // m_wipe.reset_path();
+ //} else {
+ auto result = diff_pl(Polylines{ travel }, to_polygons(m_layer->lslices));
+ if (result.empty())
+ m_wipe.reset_path();
+ //}
+ }
Point last_post_before_retract = this->last_pos();
gcode += this->retract();
@@ -5232,7 +5308,7 @@ Point GCode::gcode_to_point(const Vec2d &point) const
scale_(point(1) - m_origin(1) + extruder_offset(1)));
}
-// Goes through by_region std::vector and returns reference to a subvector of entities, that are to be printed
+// Goes through by_region std::vector and returns reference to a subvector of entities(), that are to be printed
// during infill/perimeter wiping, or normally (depends on wiping_entities parameter)
// Fills in by_region_per_copy_cache and returns its reference.
const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtruder::Island::by_region_per_copy(std::vector<Region> &by_region_per_copy_cache, unsigned int copy, uint16_t extruder, bool wiping_entities) const
@@ -5290,7 +5366,7 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
return by_region_per_copy_cache;
}
-// This function takes the eec and appends its entities to either perimeters or infills of this Region (depending on the first parameter)
+// This function takes the eec and appends its entities() to either perimeters or infills of this Region (depending on the first parameter)
// It also saves pointer to ExtruderPerCopy struct (for each entity), that holds information about which extruders should be used for which copy.
void GCode::ObjectByExtruder::Island::Region::append(const Type type, const ExtrusionEntityCollection* eec, const WipingExtrusions::ExtruderPerCopy* copies_extruder)
{
@@ -5315,15 +5391,17 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr
throw Slic3r::InvalidArgument("Unknown parameter!");
}
- // First we append the entities, there are eec->entities.size() of them:
- //don't do fill->entities because it will discard no_sort, we must use flatten(preserve_ordering = true)
- // this method will encapsulate every no_sort into an other collection, so we can get the entities directly.
- ExtrusionEntitiesPtr entities = eec->flatten(true).entities;
+ // First we append the entities, there are eec->entities().size() of them:
+ //don't do fill->entities() because it will discard no_sort, we must use flatten(preserve_ordering = true)
+ // this method will encapsulate every no_sort into an other collection, so we can get the entities() directly.
+ ExtrusionEntityCollection coll = eec->flatten(true);
size_t old_size = perimeters_or_infills->size();
- size_t new_size = old_size + entities.size();
+ size_t new_size = old_size + coll.entities().size();
perimeters_or_infills->reserve(new_size);
- for (auto* ee : entities)
- perimeters_or_infills->emplace_back(ee);
+ for (ExtrusionEntity* ee : coll.set_entities())
+ perimeters_or_infills->push_back(ee);
+ //hack for change of ownership
+ coll.set_entities().clear();
if (copies_extruder != nullptr) {
// Don't reallocate overrides if not needed.
diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp
index fa0fd1051..43455f099 100644
--- a/src/libslic3r/GCode.hpp
+++ b/src/libslic3r/GCode.hpp
@@ -304,12 +304,12 @@ private:
struct Island
{
struct Region {
- // Non-owned references to LayerRegion::perimeters::entities
+ // Non-owned references to LayerRegion::perimeters::entities()
// std::vector<const ExtrusionEntity*> would be better here, but there is no way in C++ to convert from std::vector<T*> std::vector<const T*> without copying.
ExtrusionEntitiesPtr perimeters;
- // Non-owned references to LayerRegion::fills::entities
+ // Non-owned references to LayerRegion::fills::entities()
ExtrusionEntitiesPtr infills;
- // Non-owned references to LayerRegion::ironing::entities
+ // Non-owned references to LayerRegion::ironing::entities()
ExtrusionEntitiesPtr ironings;
std::vector<const WipingExtrusions::ExtruderPerCopy*> infills_overrides;
@@ -322,7 +322,7 @@ private:
IRONING,
};
- // Appends perimeter/infill entities and writes don't indices of those that are not to be extruder as part of perimeter/infill wiping
+ // Appends perimeter/infill entities() and writes don't indices of those that are not to be extruder as part of perimeter/infill wiping
void append(const Type type, const ExtrusionEntityCollection* eec, const WipingExtrusions::ExtruderPerCopy* copy_extruders);
};
@@ -441,6 +441,8 @@ private:
// a previous extrusion path that is too small to be extruded, have to fusion it into the next call.
ExtrusionPath m_last_too_small;
+ std::string m_last_description;
+ double m_last_speed_mm_per_sec;
std::unique_ptr<CoolingBuffer> m_cooling_buffer;
std::unique_ptr<SpiralVase> m_spiral_vase;
diff --git a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
index 758fd7a5c..5f8c36604 100644
--- a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
+++ b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
@@ -1302,8 +1302,10 @@ Polyline AvoidCrossingPerimeters::travel_to(const GCode &gcodegen, const Point &
*could_be_wipe_disabled = false;
} else if (max_detour_length_exceeded) {
*could_be_wipe_disabled = false;
- } else
- *could_be_wipe_disabled = !need_wipe(gcodegen, m_grid_lslice, travel, result_pl, travel_intersection_count);
+ }
+ // Not reliable enough, now using diff_pl(Polylines{ travel }, to_polygons(m_layer->lslices)); by the caller. supermerill/SuperSlicer#2154
+// else
+// *could_be_wipe_disabled = !need_wipe(gcodegen, m_grid_lslice, travel, result_pl, travel_intersection_count);
return result_pl;
}
diff --git a/src/libslic3r/GCode/PrintExtents.cpp b/src/libslic3r/GCode/PrintExtents.cpp
index a86411519..42cdd6e13 100644
--- a/src/libslic3r/GCode/PrintExtents.cpp
+++ b/src/libslic3r/GCode/PrintExtents.cpp
@@ -73,7 +73,7 @@ static BoundingBoxf extrusionentity_extents(const ExtrusionEntity *extrusion_ent
static inline BoundingBoxf extrusionentity_extents(const ExtrusionEntityCollection &extrusion_entity_collection)
{
BoundingBoxf bbox;
- for (const ExtrusionEntity *extrusion_entity : extrusion_entity_collection.entities)
+ for (const ExtrusionEntity *extrusion_entity : extrusion_entity_collection.entities())
bbox.merge(extrusionentity_extents(extrusion_entity));
return bbox;
}
@@ -114,13 +114,13 @@ BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object
BoundingBoxf bbox_this;
for (const LayerRegion *layerm : layer->regions()) {
bbox_this.merge(extrusionentity_extents(layerm->perimeters));
- for (const ExtrusionEntity *ee : layerm->fills.entities)
+ for (const ExtrusionEntity *ee : layerm->fills.entities())
// fill represents infill extrusions of a single island.
bbox_this.merge(extrusionentity_extents(*dynamic_cast<const ExtrusionEntityCollection*>(ee)));
}
const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
if (support_layer)
- for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
+ for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities())
bbox_this.merge(extrusionentity_extents(extrusion_entity));
for (const PrintInstance &instance : print_object.instances()) {
BoundingBoxf bbox_translated(bbox_this);
diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp
index 6928daeec..ace59bc45 100644
--- a/src/libslic3r/GCode/ToolOrdering.cpp
+++ b/src/libslic3r/GCode/ToolOrdering.cpp
@@ -64,7 +64,7 @@ uint16_t LayerTools::extruder(const ExtrusionEntityCollection &extrusions, const
// 1 based extruder ID.
uint16_t extruder = ((this->extruder_override == 0) ?
(is_infill(extrusions.role()) ?
- (is_solid_infill(extrusions.entities.front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) :
+ (is_solid_infill(extrusions.entities().front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) :
region.config().perimeter_extruder.value) :
this->extruder_override);
return (extruder == 0) ? 0 : extruder - 1;
@@ -226,12 +226,12 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
for (const LayerRegion *layerm : layer->regions()) {
const PrintRegion &region = layerm->region();
- if (! layerm->perimeters.entities.empty()) {
+ if (! layerm->perimeters.entities().empty()) {
bool something_nonoverriddable = true;
if (m_print_config_ptr) { // in this case complete_objects is false (see ToolOrdering constructors)
something_nonoverriddable = false;
- for (const auto& eec : layerm->perimeters.entities) // let's check if there are nonoverriddable entities
+ for (const ExtrusionEntity* eec : layerm->perimeters.entities()) // let's check if there are nonoverriddable entities()
if (!layer_tools.wiping_extrusions().is_overriddable_and_mark(dynamic_cast<const ExtrusionEntityCollection&>(*eec), *m_print_config_ptr, object, region))
something_nonoverriddable = true;
}
@@ -245,10 +245,10 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
bool has_infill = false;
bool has_solid_infill = false;
bool something_nonoverriddable = false;
- for (const ExtrusionEntity *ee : layerm->fills.entities) {
+ for (const ExtrusionEntity *ee : layerm->fills.entities()) {
// fill represents infill extrusions of a single island.
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
- ExtrusionRole role = fill->entities.empty() ? erNone : fill->entities.front()->role();
+ ExtrusionRole role = fill->entities().empty() ? erNone : fill->entities().front()->role();
if (is_solid_infill(role))
has_solid_infill = true;
else if (role != erNone)
@@ -692,7 +692,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, uint16_t old_
bool wipe_into_infill_only = ! object->config().wipe_into_objects && region.config().wipe_into_infill;
if (region.config().infill_first != perimeters_done || wipe_into_infill_only) {
- for (const ExtrusionEntity* ee : layerm->fills.entities) { // iterate through all infill Collections
+ for (const ExtrusionEntity* ee : layerm->fills.entities()) { // iterate through all infill Collections
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
if (!is_overriddable(*fill, print.config(), *object, region))
@@ -716,7 +716,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, uint16_t old_
// Now the same for perimeters - see comments above for explanation:
if (object->config().wipe_into_objects && region.config().infill_first == perimeters_done)
{
- for (const ExtrusionEntity* ee : layerm->perimeters.entities) {
+ for (const ExtrusionEntity* ee : layerm->perimeters.entities()) {
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
if (is_overriddable(*fill, print.config(), *object, region) && !is_entity_overridden(fill, copy) && fill->total_volume() > min_infill_volume) {
set_extruder_override(fill, copy, new_extruder, num_of_copies);
@@ -736,7 +736,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, uint16_t old_
-// Called after all toolchanges on a layer were mark_infill_overridden. There might still be overridable entities,
+// Called after all toolchanges on a layer were mark_infill_overridden. There might still be overridable entities(),
// that were not actually overridden. If they are part of a dedicated object, printing them with the extruder
// they were initially assigned to might mean violating the perimeter-infill order. We will therefore go through
// them again and make sure we override it.
@@ -762,7 +762,7 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
if (!region.config().wipe_into_infill && !object->config().wipe_into_objects)
continue;
- for (const ExtrusionEntity* ee : layerm->fills.entities) { // iterate through all infill Collections
+ for (const ExtrusionEntity* ee : layerm->fills.entities()) { // iterate through all infill Collections
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
if (!is_overriddable(*fill, print.config(), *object, region)
@@ -785,7 +785,7 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
}
// Now the same for perimeters - see comments above for explanation:
- for (const ExtrusionEntity* ee : layerm->perimeters.entities) { // iterate through all perimeter Collections
+ for (const ExtrusionEntity* ee : layerm->perimeters.entities()) { // iterate through all perimeter Collections
auto* fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
if (is_overriddable(*fill, print.config(), *object, region) && ! is_entity_overridden(fill, copy))
set_extruder_override(fill, copy, (region.config().infill_first ? last_nonsoluble_extruder : first_nonsoluble_extruder), num_of_copies);
diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp
index 9431a2f77..9763f4c47 100644
--- a/src/libslic3r/GCode/ToolOrdering.hpp
+++ b/src/libslic3r/GCode/ToolOrdering.hpp
@@ -33,7 +33,7 @@ public:
// This is called from GCode::process_layer - see implementation for further comments:
const ExtruderPerCopy* get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies);
- // This function goes through all infill entities, decides which ones will be used for wiping and
+ // This function goes through all infill entities(), decides which ones will be used for wiping and
// marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower:
float mark_wiping_extrusions(const Print& print, uint16_t old_extruder, uint16_t new_extruder, float volume_to_wipe);
diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp
index e314bf2ac..b019fe43b 100644
--- a/src/libslic3r/GCode/WipeTower.cpp
+++ b/src/libslic3r/GCode/WipeTower.cpp
@@ -1216,7 +1216,7 @@ void WipeTower::toolchange_Wipe(
const float target_speed = is_first_layer() ? m_first_layer_speed * 60.f : 4800.f;
float wipe_speed = 0.33f * target_speed;
if (this->m_config->filament_max_speed.get_at(this->m_current_tool) > 0) {
- wipe_speed = std::min(wipe_speed, float(this->m_config->filament_max_speed.get_at(this->m_current_tool)) * 60.f);
+ wipe_speed = std::min(wipe_speed, float(this->m_config->filament_max_speed.get_at(this->m_current_tool)) * 60.f); // mm/s -> mm/min
}
// if there is less than 2.5*m_perimeter_width to the edge, advance straightaway (there is likely a blob anyway)
diff --git a/src/libslic3r/Geometry/MedialAxis.cpp b/src/libslic3r/Geometry/MedialAxis.cpp
index d6e0d75ce..02121b8d3 100644
--- a/src/libslic3r/Geometry/MedialAxis.cpp
+++ b/src/libslic3r/Geometry/MedialAxis.cpp
@@ -2760,7 +2760,7 @@ MedialAxis::build(ThickPolylines& polylines_out)
}
-ExtrusionEntityCollection
+ExtrusionEntitiesPtr
thin_variable_width(const ThickPolylines& polylines, const ExtrusionRole role, const Flow& flow, const coord_t resolution_internal)
{
assert(resolution_internal > SCALED_EPSILON);
@@ -2771,7 +2771,7 @@ thin_variable_width(const ThickPolylines& polylines, const ExtrusionRole role, c
const coord_t tolerance = flow.scaled_width() / 10;//scale_(0.05);
Flow current_flow = flow;
- ExtrusionEntityCollection coll;
+ ExtrusionEntitiesPtr coll;
for (const ThickPolyline& p : polylines) {
ExtrusionPaths paths;
ExtrusionPath path(role);
@@ -2924,23 +2924,23 @@ thin_variable_width(const ThickPolylines& polylines, const ExtrusionRole role, c
// Append paths to collection.
if (!paths.empty()) {
if (paths.front().first_point().coincides_with_epsilon(paths.back().last_point())) {
- coll.append(ExtrusionLoop(paths));
+ coll.push_back(new ExtrusionLoop(std::move(paths)));
} else {
if (role == erThinWall) {
//thin walls : avoid to cut them, please.
//also, keep the start, as the start should be already in a frontier where possible.
- ExtrusionEntityCollection unsortable_coll(paths);
- unsortable_coll.set_can_sort_reverse(false, false);
- coll.append(unsortable_coll);
+ ExtrusionEntityCollection* unsortable_coll = new ExtrusionEntityCollection(std::move(paths));
+ unsortable_coll->set_can_sort_reverse(false, false);
+ coll.push_back(unsortable_coll);
} else {
- if (paths.size() <= 1) {
- coll.append(paths);
+ if (paths.size() == 1) {
+ coll.push_back(paths.front().clone_move());
} else {
- ExtrusionEntityCollection unsortable_coll(paths);
+ ExtrusionEntityCollection* unsortable_coll = new ExtrusionEntityCollection(std::move(paths));
//gap fill : can reverse, but refrain from cutting them as it creates a mess.
// I say that, but currently (false, true) does bad things.
- unsortable_coll.set_can_sort_reverse(false, true);
- coll.append(unsortable_coll);
+ unsortable_coll->set_can_sort_reverse(false, true);
+ coll.push_back(unsortable_coll);
}
}
}
diff --git a/src/libslic3r/Geometry/MedialAxis.hpp b/src/libslic3r/Geometry/MedialAxis.hpp
index 234ec0757..4ea48de79 100644
--- a/src/libslic3r/Geometry/MedialAxis.hpp
+++ b/src/libslic3r/Geometry/MedialAxis.hpp
@@ -142,8 +142,8 @@ private:
void remove_bits(ThickPolylines& pp);
};
-/// create a ExtrusionEntityCollection from ThickPolylines, discretizing the variable width into little sections (of 4*SCALED_RESOLUTION length) where needed.
-ExtrusionEntityCollection thin_variable_width(const ThickPolylines& polylines, const ExtrusionRole role, const Flow& flow, const coord_t resolution_internal);
+/// create a ExtrusionEntitiesPtr from ThickPolylines, discretizing the variable width into little sections (of 4*SCALED_RESOLUTION length) where needed. Please delete all ptr if not used.
+ExtrusionEntitiesPtr thin_variable_width(const ThickPolylines& polylines, const ExtrusionRole role, const Flow &flow, const coord_t resolution_internal);
} } // namespace Slicer::Geometry
diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp
index 6dcbad76c..befa3bf9c 100644
--- a/src/libslic3r/Layer.hpp
+++ b/src/libslic3r/Layer.hpp
@@ -45,6 +45,7 @@ public:
// and for re-starting of infills.
ExPolygons fill_expolygons;
// Unspecified fill polygons, used for interecting when we don't want the infill/perimeter overlap
+ // note: if empty, that means there is no overlap, so you don't need to intersect with it.
ExPolygons fill_no_overlap_expolygons;
// collection of surfaces for infill generation
SurfaceCollection fill_surfaces;
@@ -91,7 +92,7 @@ public:
void export_region_fill_surfaces_to_svg_debug(const char *name) const;
// Is there any valid extrusion assigned to this LayerRegion?
- bool has_extrusions() const { return !this->perimeters.entities.empty() || !this->fills.entities.empty() || !this->ironings.entities.empty() || !this->thin_fills.entities.empty(); }
+ bool has_extrusions() const { return !this->perimeters.entities().empty() || !this->fills.entities().empty() || !this->ironings.entities().empty() || !this->thin_fills.entities().empty(); }
protected:
friend class Layer;
diff --git a/src/libslic3r/MedialAxis.cpp b/src/libslic3r/MedialAxis.cpp
index e9fc6ee4f..1e31c714f 100644
--- a/src/libslic3r/MedialAxis.cpp
+++ b/src/libslic3r/MedialAxis.cpp
@@ -2064,7 +2064,7 @@ MedialAxis::build(ThickPolylines &polylines_out)
}
-ExtrusionEntityCollection
+ExtrusionEntitiesPtr
thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow, coord_t resolution_internal)
{
assert(resolution_internal > SCALED_EPSILON);
@@ -2074,7 +2074,7 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl
// of segments, and any pruning shall be performed before we apply this tolerance
const coord_t tolerance = flow.scaled_width() / 10;//scale_(0.05);
- ExtrusionEntityCollection coll;
+ ExtrusionEntitiesPtr coll;
for (const ThickPolyline &p : polylines) {
ExtrusionPaths paths;
ExtrusionPath path(role);
@@ -2227,23 +2227,23 @@ thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow fl
// Append paths to collection.
if (!paths.empty()) {
if (paths.front().first_point().coincides_with_epsilon(paths.back().last_point())) {
- coll.append(ExtrusionLoop(paths));
+ coll.push_back(new ExtrusionLoop(std::move(paths)));
} else {
if (role == erThinWall){
//thin walls : avoid to cut them, please.
//also, keep the start, as the start should be already in a frontier where possible.
- ExtrusionEntityCollection unsortable_coll(paths);
- unsortable_coll.set_can_sort_reverse(false, false);
- coll.append(unsortable_coll);
+ ExtrusionEntityCollection *unsortable_coll = new ExtrusionEntityCollection(std::move(paths));
+ unsortable_coll->set_can_sort_reverse(false, false);
+ coll.push_back(unsortable_coll);
} else {
- if (paths.size() <= 1) {
- coll.append(paths);
+ if (paths.size() == 1) {
+ coll.push_back(paths.front().clone_move());
} else {
- ExtrusionEntityCollection unsortable_coll(paths);
+ ExtrusionEntityCollection *unsortable_coll = new ExtrusionEntityCollection(std::move(paths));
//gap fill : can reverse, but refrain from cutting them as it creates a mess.
// I say that, but currently (false, true) does bad things.
- unsortable_coll.set_can_sort_reverse(false, true);
- coll.append(unsortable_coll);
+ unsortable_coll->set_can_sort_reverse(false, true);
+ coll.push_back(unsortable_coll);
}
}
}
diff --git a/src/libslic3r/MedialAxis.hpp b/src/libslic3r/MedialAxis.hpp
index 18a7eb2f0..e8614c5ba 100644
--- a/src/libslic3r/MedialAxis.hpp
+++ b/src/libslic3r/MedialAxis.hpp
@@ -114,8 +114,8 @@ class MedialAxis {
void remove_bits(ThickPolylines& pp);
};
- /// create a ExtrusionEntityCollection from ThickPolylines, discretizing the variable width into little sections (of 4*SCALED_RESOLUTION length) where needed.
- ExtrusionEntityCollection thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow, coord_t resolution_internal);
+ /// create a ExtrusionEntitiesPtr from ThickPolylines, discretizing the variable width into little sections (of 4*SCALED_RESOLUTION length) where needed. Please delete all ptr if not used.
+ ExtrusionEntitiesPtr thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow, coord_t resolution_internal);
}
diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp
index 85d927187..6cd78df94 100644
--- a/src/libslic3r/PerimeterGenerator.cpp
+++ b/src/libslic3r/PerimeterGenerator.cpp
@@ -970,34 +970,36 @@ void PerimeterGenerator::process()
}
// at this point, all loops should be in contours[0] (= contours.front() )
// collection of loops to add into loops
- ExtrusionEntityCollection entities;
+ ExtrusionEntityCollection peri_entities;
if (config->perimeter_loop.value) {
- //onlyone_perimter = >fusion all perimeterLoops
+ //onlyone_perimeter = >fusion all perimeterLoops
for (PerimeterGeneratorLoop& loop : contours.front()) {
ExtrusionLoop extr_loop = this->_traverse_and_join_loops(loop, get_all_Childs(loop), loop.polygon.points.front());
//ExtrusionLoop extr_loop = this->_traverse_and_join_loops_old(loop, loop.polygon.points.front(), true);
extr_loop.paths.back().polyline.points.push_back(extr_loop.paths.front().polyline.points.front());
- entities.append(extr_loop);
+ peri_entities.append(extr_loop);
}
// append thin walls
if (!thin_walls_thickpolys.empty()) {
if (this->object_config->thin_walls_merge) {
- _merge_thin_walls(entities, thin_walls_thickpolys);
+ _merge_thin_walls(peri_entities, thin_walls_thickpolys);
} else {
- ExtrusionEntityCollection tw = Geometry::thin_variable_width
- (thin_walls_thickpolys, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_width / 4, scale_t(this->print_config->resolution)));
- entities.append(tw.entities);
+ peri_entities.append(Geometry::thin_variable_width(
+ thin_walls_thickpolys,
+ erThinWall,
+ this->ext_perimeter_flow,
+ std::max(ext_perimeter_width / 4, scale_t(this->print_config->resolution))));
}
thin_walls_thickpolys.clear();
}
} else {
if (this->object_config->thin_walls_merge) {
ThickPolylines no_thin_walls;
- entities = this->_traverse_loops(contours.front(), no_thin_walls);
- _merge_thin_walls(entities, thin_walls_thickpolys);
+ peri_entities = this->_traverse_loops(contours.front(), no_thin_walls);
+ _merge_thin_walls(peri_entities, thin_walls_thickpolys);
} else {
- entities = this->_traverse_loops(contours.front(), thin_walls_thickpolys);
+ peri_entities = this->_traverse_loops(contours.front(), thin_walls_thickpolys);
}
}
@@ -1012,68 +1014,62 @@ void PerimeterGenerator::process()
if (this->config->external_perimeters_hole.value || brim_first_layer) {
//reverse only not-thin wall
ExtrusionEntityCollection coll2;
- for (const auto loop : entities.entities) {
+ for (const ExtrusionEntity* loop : peri_entities.entities()) {
if ( (loop->is_loop() && loop->role() != erThinWall)) {
- coll2.entities.push_back(loop);
+ coll2.append(*loop);
}
}
coll2.reverse();
- for (const auto loop : entities.entities) {
+ for (const ExtrusionEntity* loop : peri_entities.entities()) {
if (!((loop->is_loop() && loop->role() != erThinWall))) {
- coll2.entities.push_back(loop);
+ coll2.append(*loop);
}
}
- //note: this hacky thing is possible because coll2.entities contains in fact entities's entities
- //if you does entities = coll2, you'll delete entities's entities and then you have nothing.
- entities.entities = coll2.entities;
- //and you have to empty coll2 or it will delete his content, hence crashing our hack
- coll2.entities.clear();
+ //note: this hacky thing is possible because coll2.entities contains in fact peri_entities's entities
+ //if you does peri_entities = coll2, you'll delete peri_entities's entities() and then you have nothing.
+ peri_entities = std::move(coll2);
} else {
//reverse only not-hole perimeters
ExtrusionEntityCollection coll2;
- for (const auto loop : entities.entities) {
+ for (const ExtrusionEntity* loop : peri_entities.entities()) {
if ((loop->is_loop() && loop->role() != erThinWall) && !(((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0) {
- coll2.entities.push_back(loop);
+ coll2.append(*loop);
}
}
coll2.reverse();
- for (const auto loop : entities.entities) {
- if (!((loop->is_loop() && loop->role() != erThinWall) && (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0)) {
- coll2.entities.push_back(loop);
+ for (const ExtrusionEntity* loop : peri_entities.entities()) {
+ if (!((loop->is_loop() && loop->role() != erThinWall) && !(((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0)) {
+ coll2.append(*loop);
}
}
//note: this hacky thing is possible because coll2.entities contains in fact entities's entities
- //if you does entities = coll2, you'll delete entities's entities and then you have nothing.
- entities.entities = coll2.entities;
- //and you have to empty coll2 or it will delete his content, hence crashing our hack
- coll2.entities.clear();
+ //if you does peri_entities = coll2, you'll delete peri_entities's entities and then you have nothing.
+ peri_entities = std::move(coll2);
}
} else if (this->config->external_perimeters_hole.value) {
//reverse the hole, and put them in first place.
ExtrusionEntityCollection coll2;
- for (const auto loop : entities.entities) {
+ for (const ExtrusionEntity* loop : peri_entities.entities()) {
if ((loop->is_loop() && loop->role() != erThinWall) && (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0) {
- coll2.entities.push_back(loop);
+ coll2.append(*loop);
}
}
coll2.reverse();
- for (const auto loop : entities.entities) {
+ for (const ExtrusionEntity* loop : peri_entities.entities()) {
if (!((loop->is_loop() && loop->role() != erThinWall) && (((ExtrusionLoop*)loop)->loop_role() & ExtrusionLoopRole::elrHole) != 0)) {
- coll2.entities.push_back(loop);
+ coll2.append(*loop);
}
}
- //note: this hacky thing is possible because coll2.entities contains in fact entities's entities
- //if you does entities = coll2, you'll delete entities's entities and then you have nothing.
- entities.entities = coll2.entities;
- //and you have to empty coll2 or it will delete his content, hence crashing our hack
- coll2.entities.clear();
+ //note: this hacky thing is possible because coll2.entities contains in fact peri_entities's entities
+ //if you does peri_entities = coll2, you'll delete peri_entities's entities and then you have nothing.
+ peri_entities = std::move(coll2);
}
}
// append perimeters for this slice as a collection
- if (!entities.empty()) {
+ if (!peri_entities.empty()) {
//move it, to avoid to clone evrything and then delete it
- this->loops->entities.emplace_back(new ExtrusionEntityCollection(std::move(entities)));
+ this->loops->append(peri_entities);
}
} // for each loop of an island
@@ -1148,19 +1144,11 @@ void PerimeterGenerator::process()
}
// create extrusion from lines
if (!polylines.empty()) {
- ExtrusionEntityCollection gap_fill = Geometry::thin_variable_width(polylines,
- erGapFill, this->solid_infill_flow, scale_t(this->print_config->resolution_internal));
-
- //{
- // static int isaqsdsdfsdfqzfn = 0;
- // std::stringstream stri;
- // stri << this->layer->id() << "_gapfill_" << isaqsdsdfsdfqzfn++ << ".svg";
- // SVG svg(stri.str());
- // svg.draw((surface.expolygon), "grey");
- // svg.draw(polylines, "blue");
- // svg.Close();
- //}
- this->gap_fill->append(gap_fill.entities);
+ this->gap_fill->append(Geometry::thin_variable_width(
+ polylines,
+ erGapFill,
+ this->solid_infill_flow,
+ scale_t(this->print_config->resolution_internal)));
/* Make sure we don't infill narrow parts that are already gap-filled
(we only consider this surface's gaps to reduce the diff() complexity).
Growing actual extrusions ensures that gaps not filled by medial axis
@@ -1168,13 +1156,12 @@ void PerimeterGenerator::process()
that medial axis skips but infill might join with other infill regions
and use zigzag). */
// get clean surface of gap
- gap_srf = union_ex(offset(gap_fill.polygons_covered_by_width(float(SCALED_EPSILON) / 10), float(SCALED_EPSILON / 2)));
+ gap_srf = union_ex(offset(this->gap_fill->polygons_covered_by_width(float(SCALED_EPSILON) / 10), float(SCALED_EPSILON / 2)));
// intersection to ignore the bits of gapfill tha may be over infill, as it's epsilon and there may be some voids here anyway.
gap_srf = intersection_ex(gap_srf, gaps_ex);
// the diff(last, gap) will be done after, as we have to keep the last un-gapped to avoid unneeded gap/infill offset
}
}
- //TODO: if a gapfill extrusion is a loop and with width always >= perimeter width then change the type to perimeter and put it at the right place in the loops vector.
// create one more offset to be used as boundary for fill
// we offset by half the perimeter spacing (to get to the actual infill boundary)
@@ -1555,7 +1542,7 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
{
// loops is an arrayref of ::Loop objects
// turn each one into an ExtrusionLoop object
- ExtrusionEntityCollection coll;
+ ExtrusionEntitiesPtr coll;
for (const PerimeterGeneratorLoop &loop : loops) {
bool is_external = loop.is_external();
@@ -1607,20 +1594,20 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
fuzzy_polygon(paths, scale_d(fuzzy_skin_thickness), scale_d(fuzzy_skin_point_dist));
}
- coll.append(ExtrusionLoop(paths, loop_role));
+ coll.push_back(new ExtrusionLoop(paths, loop_role));
}
// append thin walls to the nearest-neighbor search (only for first iteration)
if (!thin_walls.empty()) {
- ExtrusionEntityCollection tw = Geometry::thin_variable_width(thin_walls, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)));
- coll.append(tw.entities);
+ ExtrusionEntitiesPtr tw = Geometry::thin_variable_width(thin_walls, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)));
+ coll.insert(coll.end(), tw.begin(), tw.end());
+ //don't add again
thin_walls.clear();
}
-
// traverse children and build the final collection
Point zero_point(0, 0);
//result is [idx, needReverse] ?
- std::vector<std::pair<size_t, bool>> chain = chain_extrusion_entities(coll.entities, &zero_point);
+ std::vector<std::pair<size_t, bool>> chain = chain_extrusion_entities(coll, &zero_point);
ExtrusionEntityCollection coll_out;
if (chain.empty()) return coll_out;
@@ -1648,34 +1635,34 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
if (idx.first >= loops.size()) {
// this is a thin wall
// let's get it from the sorted collection as it might have been reversed
- coll_out.entities.reserve(coll_out.entities.size() + 1);
- coll_out.entities.emplace_back(coll.entities[idx.first]);
- coll.entities[idx.first] = nullptr;
+ coll_out.set_entities().reserve(coll_out.entities().size() + 1);
+ coll_out.set_entities().emplace_back(coll[idx.first]);
+ coll[idx.first] = nullptr;
if (idx.second)
- coll_out.entities.back()->reverse();
+ coll_out.entities().back()->reverse();
//if thin extrusion is a loop, make it ccw like a normal contour.
- if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(coll_out.entities.back())) {
+ if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(coll_out.entities().back())) {
loop->make_counter_clockwise();
}
} else {
const PerimeterGeneratorLoop &loop = loops[idx.first];
assert(thin_walls.empty());
ExtrusionEntityCollection children = this->_traverse_loops(loop.children, thin_walls);
- coll_out.entities.reserve(coll_out.entities.size() + children.entities.size() + 1);
- ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll.entities[idx.first]);
- coll.entities[idx.first] = nullptr;
+ coll_out.set_entities().reserve(coll_out.entities().size() + children.entities().size() + 1);
+ ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll[idx.first]);
+ coll[idx.first] = nullptr;
if (loop.is_contour) {
//note: this->layer->id() % 2 == 1 already taken into account in the is_steep_overhang compute (to save time).
if (loop.is_steep_overhang && this->layer->id() % 2 == 1)
eloop->make_clockwise();
else
eloop->make_counter_clockwise();
- coll_out.append(std::move(children.entities));
+ coll_out.append(std::move(children.entities()));
coll_out.append(*eloop);
} else {
eloop->make_clockwise();
coll_out.append(*eloop);
- coll_out.append(std::move(children.entities));
+ coll_out.append(std::move(children.entities()));
}
}
}
@@ -1683,6 +1670,7 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
}
void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions, ThickPolylines &thin_walls) const {
+ //TODO: find a way to avoid double copy (from EntityCollection to ChangeFlow to searcher.search_result.loop
class ChangeFlow : public ExtrusionVisitor {
public:
float percent_extrusion;
@@ -1690,7 +1678,7 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
virtual void use(ExtrusionPath &path) override {
path.mm3_per_mm *= percent_extrusion;
path.width *= percent_extrusion;
- paths.emplace_back(std::move(path));
+ paths.push_back(path);
}
virtual void use(ExtrusionPath3D &path3D) override { /*shouldn't happen*/ }
virtual void use(ExtrusionMultiPath &multipath) override { /*shouldn't happen*/ }
@@ -1700,7 +1688,7 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
this->use(path);
}
virtual void use(ExtrusionEntityCollection &collection) override {
- for (ExtrusionEntity *entity : collection.entities)
+ for (ExtrusionEntity *entity : collection.entities())
entity->visit(*this);
}
};
@@ -1767,7 +1755,7 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
virtual void use(ExtrusionEntityCollection &collection) override {
collection.set_can_sort_reverse(true, true);
//for each loop? (or other collections)
- for (ExtrusionEntity *entity : collection.entities)
+ for (ExtrusionEntity *entity : collection.entities())
entity->visit(*this);
}
};
@@ -1806,9 +1794,10 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
searcher.search_result.loop->paths.insert(searcher.search_result.loop->paths.begin() + 1 + searcher.search_result.idx_path,
ExtrusionPath(poly_after, *searcher.search_result.path));
//create thin wall path exttrusion
- ExtrusionEntityCollection tws = Geometry::thin_variable_width({ tw }, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)));
+ ExtrusionEntityCollection tws;
+ tws.append(Geometry::thin_variable_width({ tw }, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution))));
ChangeFlow change_flow;
- if (tws.entities.size() == 1 && tws.entities[0]->is_loop()) {
+ if (tws.entities().size() == 1 && tws.entities()[0]->is_loop()) {
//loop, just add it
change_flow.percent_extrusion = 1;
change_flow.use(tws);
@@ -1820,9 +1809,9 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
} else {
//first add the return path
- ExtrusionEntityCollection tws_second = tws;
+ //ExtrusionEntityCollection tws_second = tws; // this does a deep copy
change_flow.percent_extrusion = 0.1f;
- change_flow.use(tws_second);
+ change_flow.use(tws); // tws_second); //does not need the deep copy if the change_flow copy the content instead of re-using it.
//force reverse
for (ExtrusionPath &path : change_flow.paths)
path.reverse();
@@ -1843,8 +1832,7 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
}
//now add thinwalls that have no anchor (make them reversable)
- ExtrusionEntityCollection tws = Geometry::thin_variable_width(not_added, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution)));
- extrusions.append(tws.entities);
+ extrusions.append(Geometry::thin_variable_width(not_added, erThinWall, this->ext_perimeter_flow, std::max(ext_perimeter_flow.scaled_width() / 4, scale_t(this->print_config->resolution))));
}
PerimeterIntersectionPoint
diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp
index 1e48a96d4..de2249a9f 100644
--- a/src/libslic3r/PlaceholderParser.cpp
+++ b/src/libslic3r/PlaceholderParser.cpp
@@ -690,6 +690,7 @@ namespace client
// If false, the macro_processor will evaluate a full macro.
// If true, the macro processor will evaluate just a boolean condition using the full expressive power of the macro processor.
bool just_boolean_expression = false;
+ inline static bool ignore_legacy = false;
std::string error_message;
static std::map<t_config_option_key, std::unique_ptr<ConfigOption>> checked_vars;
@@ -804,6 +805,10 @@ namespace client
std::string &output)
{
std::string opt_key_str(opt_key.begin(), opt_key.end());
+ if (ignore_legacy) {
+ output = "[" + opt_key_str + "]";
+ return;
+ }
const ConfigOption *opt = ctx->resolve_symbol(opt_key_str);
size_t idx = ctx->current_extruder_id;
if (opt == nullptr) {
@@ -841,6 +846,10 @@ namespace client
std::string &output)
{
std::string opt_key_str(opt_key.begin(), opt_key.end());
+ if (ignore_legacy) {
+ output = "[" + opt_key_str + "]";
+ return;
+ }
const ConfigOption *opt = ctx->resolve_symbol(opt_key_str);
if (opt == nullptr) {
// Check whether the opt_key ends with '_'.
@@ -916,7 +925,7 @@ namespace client
}
}
//return
- out = expr<Iterator>(opt != nullptr, out.it_range.begin(), end_pos);
+ //out = expr<Iterator>(opt != nullptr, out.it_range.begin(), end_pos);
}
template <typename Iterator>
@@ -1287,6 +1296,10 @@ namespace client
text_block = *(
text [_val+=_1]
+ // escape character: can escape '[' and '{' or is printed as-is.
+ | (no_skip[raw["\\["]] [_val = _val + "["])
+ | (no_skip[raw["\\{"]] [_val = _val + "{"])
+ | (no_skip[raw["\\"]] [_val = _val + "\\"])
// Allow back tracking after '{' in case of a text_block embedded inside a condition.
// In that case the inner-most {else} wins and the {if}/{elsif}/{else} shall be paired.
// {elsif}/{else} without an {if} will be allowed to back track from the embedded text_block.
@@ -1297,7 +1310,7 @@ namespace client
// Free-form text up to a first brace, including spaces and newlines.
// The free-form text will be inserted into the processed text without a modification.
- text = no_skip[raw[+(utf8char - char_('[') - char_('{'))]];
+ text = no_skip[raw[+(utf8char - char_('[') - char_('{') - char_('\\'))]];
text.name("text");
// New style of macro expansion.
@@ -1330,10 +1343,12 @@ namespace client
*/
// Legacy variable expansion of the original Slic3r, in the form of [scalar_variable] or [vector_variable_index].
+ // note: should use 'identifier' instead of 'raw[lexeme[*((utf8char - char_('\\') - char_(']')) | ('\\' > char_))]]'
+ // but it's that way to allow to ignore the legacy_variable_expansion is disabled, witout outputting an exception
legacy_variable_expansion =
- (identifier >> &lit(']'))
+ ((raw[lexeme[*((utf8char - char_('\\') - char_(']')) | ('\\' > char_))]] >> &lit(']')) >> &lit(']'))
[ px::bind(&MyContext::legacy_variable_expansion<Iterator>, _r1, _1, _val) ]
- | (identifier > lit('[') > identifier > ']')
+ | ((raw[lexeme[*((utf8char - char_('\\') - char_(']')) | ('\\' > char_))]] >> &lit(']')) > lit('[') > (raw[lexeme[*((utf8char - char_('\\') - char_(']')) | ('\\' > char_))]] >> &lit(']')) > ']')
[ px::bind(&MyContext::legacy_variable_expansion2<Iterator>, _r1, _1, _2, _val) ]
;
legacy_variable_expansion.name("legacy_variable_expansion");
@@ -1430,6 +1445,10 @@ namespace client
{ MyContext::check_variable<Iterator>(ctx, opt_key, end_pos, out, new ConfigOptionFloat(value)); }
static void default_string_(boost::iterator_range<Iterator>& it_range, const MyContext* ctx, boost::iterator_range<Iterator>& opt_key, Iterator& end_pos, expr<Iterator>& out)
{ MyContext::check_variable<Iterator>(ctx, opt_key, end_pos, out, new ConfigOptionString(std::string(it_range.begin() + 1, it_range.end() - 1))); }
+ static void set_ignore_legacy_(bool& value)
+ {
+ MyContext::ignore_legacy = value;
+ }
};
unary_expression = iter_pos[px::bind(&FactorActions::set_start_pos, _1, _val)] >> (
scalar_variable_reference(_r1) [ _val = _1 ]
@@ -1450,14 +1469,15 @@ namespace client
| (kw["int"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::to_int, _1, _val) ]
| (kw["round"] > '(' > conditional_expression(_r1) > ')') [ px::bind(&FactorActions::round, _1, _val) ]
| (kw["exists"] > '(' > identifier > ')' > iter_pos) [ px::bind(&MyContext::check_variable<Iterator>, _r1, _1, _2, _val, nullptr) ]
- | (kw["default"] > '(' > identifier > ',' > strict_double > ')' > iter_pos)
+ | (kw["default_double"] > '(' > identifier > ',' > strict_double > ')' > iter_pos)
[px::bind(&FactorActions::default_double_, _2, _r1, _1, _3, _val)]
- | (kw["default"] > '(' > identifier > ',' > int_ > ')' > iter_pos)
+ | (kw["default_int"] > '(' > identifier > ',' > int_ > ')' > iter_pos)
[px::bind(&FactorActions::default_int_, _2, _r1, _1, _3, _val)]
- | (kw["default"] > '(' > identifier > ',' > kw[bool_] > ')' > iter_pos)
+ | (kw["default_bool"] > '(' > identifier > ',' > kw[bool_] > ')' > iter_pos)
[ px::bind(&FactorActions::default_bool_, _2, _r1, _1, _3, _val) ]
- | (kw["default"] > '(' > identifier > ',' > raw[lexeme['"' > *((utf8char - char_('\\') - char_('"')) | ('\\' > char_)) > '"']] > ')' > iter_pos)
+ | (kw["default_string"] > '(' > identifier > ',' > raw[lexeme['"' > *((utf8char - char_('\\') - char_('"')) | ('\\' > char_)) > '"']] > ')' > iter_pos)
[px::bind(&FactorActions::default_string_, _2, _r1, _1, _3, _val)]
+ | (kw["ignore_legacy"] > '(' > kw[bool_] > ')') [px::bind(&FactorActions::set_ignore_legacy_, _1)]
| (strict_double > iter_pos) [ px::bind(&FactorActions::double_, _1, _2, _val) ]
| (int_ > iter_pos) [ px::bind(&FactorActions::int_, _1, _2, _val) ]
| (kw[bool_] > iter_pos) [ px::bind(&FactorActions::bool_, _1, _2, _val) ]
@@ -1507,7 +1527,11 @@ namespace client
("or")
("true")
("exists")
- ("default");
+ ("default_double")
+ ("default_int")
+ ("default_bool")
+ ("default_string")
+ ("ignore_legacy");
if (0) {
debug(start);
diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp
index 9991e9d7a..439ef852c 100644
--- a/src/libslic3r/Print.cpp
+++ b/src/libslic3r/Print.cpp
@@ -1201,7 +1201,7 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
// get first layer support
if (!object->support_layers().empty() && object->support_layers().front()->print_z == object->m_layers[0]->print_z) {
Points support_points;
- for (const ExtrusionEntity* extrusion_entity : object->support_layers().front()->support_fills.entities) {
+ for (const ExtrusionEntity* extrusion_entity : object->support_layers().front()->support_fills.entities()) {
Polylines poly;
extrusion_entity->collect_polylines(poly);
for (const Polyline& polyline : poly)
@@ -1312,10 +1312,10 @@ void Print::_make_skirt(const PrintObjectPtrs &objects, ExtrusionEntityCollectio
out_first_layer->append(eloop);
if (m_config.min_skirt_length.value > 0 && !first_layer_only) {
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
- extruded_length[extruder_idx] += unscale<double>(loop.length()) * extruders_e_per_mm[extruder_idx];
+ extruded_length[extruder_idx] += unscale<double>(loop.length());// *extruders_e_per_mm[extruder_idx];
if (extruded_length[extruder_idx] < m_config.min_skirt_length.value) {
// Not extruded enough yet with the current extruder. Add another loop.
- if (i == 1)
+ if (i == 1 && extruded_length[extruder_idx] > 0)
++ i;
} else {
assert(extruded_length[extruder_idx] >= m_config.min_skirt_length.value);
diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp
index 877e99c07..dc760ae6b 100644
--- a/src/libslic3r/Print.hpp
+++ b/src/libslic3r/Print.hpp
@@ -391,6 +391,7 @@ private:
void clip_fill_surfaces();
void tag_under_bridge();
void discover_horizontal_shells();
+ void clean_surfaces();
void combine_infill();
void _generate_support_material();
std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> prepare_adaptive_infill_data();
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index 4e9c4d4be..996f44831 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -576,7 +576,7 @@ void PrintConfigDef::init_fff_params()
def->category = OptionCategory::customgcode;
def->tooltip = L("This custom code is inserted at every layer change, right before the Z move. "
"Note that you can use placeholder variables for all Slic3r settings as well "
- "as [layer_num] and [layer_z].");
+ "as {layer_num} and {layer_z}.");
def->multiline = true;
def->full_width = true;
def->height = 5;
@@ -586,7 +586,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("between_objects_gcode", coString);
def->label = L("Between objects G-code");
def->category = OptionCategory::customgcode;
- def->tooltip = L("This code is inserted between objects when using sequential printing. By default extruder and bed temperature are reset using non-wait command; however if M104, M109, M140 or M190 are detected in this custom code, Slic3r will not add temperature commands. Note that you can use placeholder variables for all Slic3r settings, so you can put a \"M109 S[first_layer_temperature]\" command wherever you want.");
+ def->tooltip = L("This code is inserted between objects when using sequential printing. By default extruder and bed temperature are reset using non-wait command; however if M104, M109, M140 or M190 are detected in this custom code, Slic3r will not add temperature commands. Note that you can use placeholder variables for all Slic3r settings, so you can put a \"M109 S{first_layer_temperature}\" command wherever you want.");
def->multiline = true;
def->full_width = true;
def->height = 12;
@@ -1151,7 +1151,7 @@ void PrintConfigDef::init_fff_params()
def->category = OptionCategory::perimeter;
def->tooltip = L("Add solid infill near sloping surfaces to guarantee the vertical shell thickness "
"(top+bottom solid layers)."
- "\n!! solid_over_perimeters may erase these surfaces !! So you should deactivate it if you want to use this.");
+ "\n!! solid_over_perimeters may erase these surfaces !!");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
@@ -1551,8 +1551,8 @@ void PrintConfigDef::init_fff_params()
def->label = L("Extruder temp offset");
def->category = OptionCategory::extruders;
def->tooltip = L("This offset will be added to all extruder temperatures set in the filament settings."
- "\nNote that you should set 'M104 S{first_layer_temperature[initial_extruder] + extruder_temperature_offset[initial_extruder]}'"
- "\ninstead of 'M104 S[first_layer_temperature]' in the start_gcode");
+ "\nNote that you should set 'M104 S{first_layer_temperature{initial_extruder} + extruder_temperature_offset{initial_extruder}}'"
+ "\ninstead of 'M104 S{first_layer_temperature}' in the start_gcode");
def->sidetext = L("°C");
def->mode = comExpert;
def->is_vector_extruder = true;
@@ -1679,7 +1679,7 @@ void PrintConfigDef::init_fff_params()
"\nA value that is enclosed by double-quotes will be available as a string (without the quotes)"
"\nA value that only takes values as 'true' or 'false' will be a boolean)"
"\nEvery other value will be parsed as a string as-is."
- "\nThese varibles will be available as an array in the custom gcode (one item per extruder), don't forget to use them with the [current_extruder] index to get the current value."
+ "\nThese varibles will be available as an array in the custom gcode (one item per extruder), don't forget to use them with the {current_extruder} index to get the current value."
" If a filament has a typo on the variable that change its type, then the parser will convert evrything to strings.");
def->multiline = true;
def->full_width = true;
@@ -3001,7 +3001,7 @@ void PrintConfigDef::init_fff_params()
def->category = OptionCategory::customgcode;
def->tooltip = L("This custom code is inserted at every layer change, right after the Z move "
"and before the extruder moves to the first layer point. Note that you can use "
- "placeholder variables for all Slic3r settings as well as [layer_num] and [layer_z].");
+ "placeholder variables for all Slic3r settings as well as {layer_num} and {layer_z}.");
def->cli = "after-layer-gcode|layer-gcode";
def->multiline = true;
def->full_width = true;
@@ -3013,7 +3013,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("After layer change G-code");
def->category = OptionCategory::customgcode;
def->tooltip = L("This custom code is inserted at every extrusion type change."
- "Note that you can use placeholder variables for all Slic3r settings as well as [last_extrusion_role], [extrusion_role], [layer_num] and [layer_z]."
+ "Note that you can use placeholder variables for all Slic3r settings as well as {last_extrusion_role}, {extrusion_role}, {layer_num} and {layer_z}."
" The 'extrusion_role' strings can take these string values:"
" { Perimeter, ExternalPerimeter, OverhangPerimeter, InternalInfill, SolidInfill, TopSolidInfill, BridgeInfill, GapFill, Skirt, SupportMaterial, SupportMaterialInterface, WipeTower, Mixed }."
" Mixed is only used when the role of the extrusion is not unique, not exactly inside another category or not known.");
@@ -3042,7 +3042,7 @@ void PrintConfigDef::init_fff_params()
def->label = L("Method");
def->full_label = L("Supports remaining times method");
def->category = OptionCategory::firmware;
- def->tooltip = L("M73: Emit M73 P[percent printed] R[remaining time in minutes] at 1 minute"
+ def->tooltip = L("M73: Emit M73 P{percent printed} R{remaining time in minutes} at 1 minute"
" intervals into the G-code to let the firmware show accurate remaining time."
" As of now only the Prusa i3 MK3 firmware recognizes M73."
" Also the i3 MK3 firmware supports M73 Qxx Sxx for the silent mode."
@@ -3545,12 +3545,12 @@ void PrintConfigDef::init_fff_params()
def->label = L("Output filename format");
def->category = OptionCategory::output;
def->tooltip = L("You can use all configuration options as variables inside this template. "
- "For example: [layer_height], [fill_density] etc. You can also use [timestamp], "
- "[year], [month], [day], [hour], [minute], [second], [version], [input_filename], "
- "[input_filename_base].");
+ "For example: {layer_height}, {fill_density} etc. You can also use {timestamp}, "
+ "{year}, {month}, {day}, {hour}, {minute}, {second}, {version}, {input_filename}, "
+ "{input_filename_base}.");
def->full_width = true;
def->mode = comExpert;
- def->set_default_value(new ConfigOptionString("[input_filename_base].gcode"));
+ def->set_default_value(new ConfigOptionString("{input_filename_base}.gcode"));
def = this->add("overhangs_acceleration", coFloatOrPercent);
def->label = L("Overhangs");
@@ -4532,7 +4532,7 @@ void PrintConfigDef::init_fff_params()
"such commands will not be prepended automatically so you're free to customize "
"the order of heating commands and other custom actions. Note that you can use "
"placeholder variables for all Slic3r settings, so you can put "
- "a \"M109 S[first_layer_temperature]\" command wherever you want."
+ "a \"M109 S{first_layer_temperature}\" command wherever you want."
"\n placeholders: initial_extruder, total_layer_count, has_wipe_tower, has_single_extruder_multi_material_priming, total_toolchanges, bounding_box[minx,miny,maxx,maxy]");
def->multiline = true;
def->full_width = true;
@@ -4558,7 +4558,7 @@ void PrintConfigDef::init_fff_params()
"M104, M109, M140 or M190 in your custom codes, such commands will "
"not be prepended automatically so you're free to customize the order "
"of heating commands and other custom actions. Note that you can use placeholder variables "
- "for all Slic3r settings, so you can put a \"M109 S[first_layer_temperature]\" command "
+ "for all Slic3r settings, so you can put a \"M109 S{first_layer_temperature}\" command "
"wherever you want. If you have multiple extruders, the gcode is processed "
"in extruder order.");
def->multiline = true;
@@ -4660,7 +4660,7 @@ void PrintConfigDef::init_fff_params()
" the top/bottom solid layer count, it won't do anything. If this setting is set to 1, it will evict "
" all solid fill above/below perimeters. "
"\nSet zero to disable."
- "\n!! ensure_vertical_shell_thickness may be erased by this setting !!.");
+ "\n!! ensure_vertical_shell_thickness needs to be activated so this algorithm can work !!.");
def->min = 0;
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(2));
@@ -5163,7 +5163,7 @@ void PrintConfigDef::init_fff_params()
def->tooltip = L("This custom code is inserted at every extruder change. If you don't leave this empty, you are "
"expected to take care of the toolchange yourself - Slic3r will not output any other G-code to "
"change the filament. You can use placeholder variables for all Slic3r settings as well as {toolchange_z}, {layer_z}, {layer_num}, {max_layer_z}, {previous_extruder} "
- "and {next_extruder}, so e.g. the standard toolchange command can be scripted as T[next_extruder]."
+ "and {next_extruder}, so e.g. the standard toolchange command can be scripted as T{next_extruder}."
"!! Warning !!: if any character is written here, Slic3r won't output any toochange command by itself.");
def->multiline = true;
def->full_width = true;
@@ -5329,7 +5329,7 @@ void PrintConfigDef::init_fff_params()
def->category = OptionCategory::general;
def->tooltip = L("This experimental setting uses outputs the E values in cubic millimeters "
"instead of linear millimeters. If your firmware doesn't already know "
- "filament diameter(s), you can put commands like 'M200 D[filament_diameter_0] T0' "
+ "filament diameter(s), you can put commands like 'M200 D{filament_diameter_0} T0' "
"in your start G-code in order to turn volumetric mode on and use the filament "
"diameter associated to the filament selected in Slic3r. This is only supported "
"in recent Marlin.");
@@ -5788,10 +5788,10 @@ void PrintConfigDef::init_milling_params()
def = this->add("milling_toolchange_start_gcode", coStrings);
def->label = L("G-Code to switch to this toolhead");
def->category = OptionCategory::milling_extruders;
- def->tooltip = L("Put here the gcode to change the toolhead (called after the g-code T[next_extruder]). You have access to [next_extruder] and [previous_extruder]."
+ def->tooltip = L("Put here the gcode to change the toolhead (called after the g-code T{next_extruder}). You have access to {next_extruder} and {previous_extruder}."
" next_extruder is the 'extruder number' of the new milling tool, it's equal to the index (begining at 0) of the milling tool plus the number of extruders."
" previous_extruder is the 'extruder number' of the previous tool, it may be a normal extruder, if it's below the number of extruders."
- " The number of extruder is available at [extruder] and the number of milling tool is available at [milling_cutter].");
+ " The number of extruder is available at {extruder} and the number of milling tool is available at {milling_cutter}.");
def->multiline = true;
def->full_width = true;
def->height = 12;
@@ -5802,10 +5802,10 @@ void PrintConfigDef::init_milling_params()
def = this->add("milling_toolchange_end_gcode", coStrings);
def->label = L("G-Code to switch from this toolhead");
def->category = OptionCategory::milling_extruders;
- def->tooltip = L("Enter here the gcode to end the toolhead action, like stopping the spindle. You have access to [next_extruder] and [previous_extruder]."
+ def->tooltip = L("Enter here the gcode to end the toolhead action, like stopping the spindle. You have access to {next_extruder} and {previous_extruder}."
" previous_extruder is the 'extruder number' of the current milling tool, it's equal to the index (begining at 0) of the milling tool plus the number of extruders."
" next_extruder is the 'extruder number' of the next tool, it may be a normal extruder, if it's below the number of extruders."
- " The number of extruder is available at [extruder]and the number of milling tool is available at [milling_cutter].");
+ " The number of extruder is available at {extruder}and the number of milling tool is available at {milling_cutter}.");
def->multiline = true;
def->full_width = true;
def->height = 12;
@@ -6776,8 +6776,8 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
std::map<std::string,std::string> PrintConfigDef::from_prusa(t_config_option_key& opt_key, std::string& value, const DynamicConfig& all_conf) {
std::map<std::string, std::string> output;
if ("toolchange_gcode" == opt_key) {
- if (!value.empty() && value.find("T[next_extruder]") == std::string::npos) {
- value = "T[next_extruder]\n" + value;
+ if (!value.empty() && value.find("T{next_extruder}") == std::string::npos && value.find("T[next_extruder]") == std::string::npos) {
+ value = "T{next_extruder}\n" + value;
}
}
if ("xy_size_compensation" == opt_key) {
diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp
index 79b83bb8c..698bf4677 100644
--- a/src/libslic3r/PrintObject.cpp
+++ b/src/libslic3r/PrintObject.cpp
@@ -462,10 +462,12 @@ std::vector<std::reference_wrapper<const PrintRegion>> PrintObject::all_regions(
// to close these surfaces reliably.
//FIXME Vojtech: Is this a good place to add supporting infills below sloping perimeters?
//note: only if not "ensure vertical shell"
- //TODO merill: as "ensure_vertical_shell_thickness" is innefective, this should be simplified / streamlined / deleted?
this->discover_horizontal_shells();
m_print->throw_if_canceled();
+ //as there is some too thin solid surface, please deleted them and merge all of the surfacesthat are contigous.
+ this->clean_surfaces();
+
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
for (size_t region_id = 0; region_id < this->num_printing_regions(); ++ region_id) {
for (const Layer* layer : m_layers) {
@@ -1341,7 +1343,9 @@ bool PrintObject::invalidate_state_by_config_options(
for (int idx_dense = 0; idx_dense < dense_polys.size(); idx_dense++) {
ExPolygon dense_poly = dense_polys[idx_dense];
//remove overlap with perimeter
- ExPolygons offseted_dense_polys = intersection_ex(ExPolygons{ dense_poly }, layerm->fill_no_overlap_expolygons);
+ ExPolygons offseted_dense_polys = layerm->fill_no_overlap_expolygons.empty()
+ ? ExPolygons{dense_poly}
+ : intersection_ex(ExPolygons{ dense_poly }, layerm->fill_no_overlap_expolygons);
//add overlap with everything
offseted_dense_polys = offset_ex(offseted_dense_polys, overlap);
for (ExPolygon offseted_dense_poly : offseted_dense_polys) {
@@ -2203,32 +2207,34 @@ bool PrintObject::invalidate_state_by_config_options(
{
to_bridge.clear();
- //choose betweent two offset the one that split the less the surface.
+ //choose between two offsets the one that split the less the surface.
float min_width = float(bridge_flow.scaled_width()) * 3.f;
- for (Polygon& poly_to_check_for_thin : to_bridge_pp) {
- ExPolygons expolys_to_check_for_thin{ ExPolygon{poly_to_check_for_thin} };
- ExPolygons collapsed = offset2_ex(expolys_to_check_for_thin, -min_width, +min_width * 1.25f);
- ExPolygons bridge = intersection_ex(collapsed, expolys_to_check_for_thin);
- ExPolygons not_bridge = diff_ex(expolys_to_check_for_thin, collapsed);
+ // opening : offset2-+
+ ExPolygons to_bridgeOK = opening_ex(to_bridge_pp, min_width, min_width);
+ for (ExPolygon& expolys_to_check_for_thin : union_ex(to_bridge_pp)) {
+ ExPolygons collapsed = offset2_ex(ExPolygons{ expolys_to_check_for_thin }, -min_width, +min_width * 1.25f);
+ ExPolygons bridge = intersection_ex(collapsed, ExPolygons{ expolys_to_check_for_thin });
+ ExPolygons not_bridge = diff_ex(ExPolygons{ expolys_to_check_for_thin }, collapsed);
int try1_count = bridge.size() + not_bridge.size();
if (try1_count > 1) {
min_width = float(bridge_flow.scaled_width()) * 1.5f;
- collapsed = offset2_ex(expolys_to_check_for_thin, -min_width, +min_width * 1.5f);
- ExPolygons bridge2 = intersection_ex(collapsed, expolys_to_check_for_thin);
- not_bridge = diff_ex(expolys_to_check_for_thin, collapsed);
+ collapsed = offset2_ex(ExPolygons{ expolys_to_check_for_thin }, -min_width, +min_width * 1.5f);
+ ExPolygons bridge2 = intersection_ex(collapsed, ExPolygons{ expolys_to_check_for_thin });
+ not_bridge = diff_ex(ExPolygons{ expolys_to_check_for_thin }, collapsed);
int try2_count = bridge2.size() + not_bridge.size();
if(try2_count < try1_count)
to_bridge.insert(to_bridge.begin(), bridge2.begin(), bridge2.end());
else
to_bridge.insert(to_bridge.begin(), bridge.begin(), bridge.end());
- } else if (!bridge.empty())
- to_bridge.push_back(bridge.front());
+ } else {
+ to_bridge.insert(to_bridge.begin(), bridge.begin(), bridge.end());
+ }
}
}
if (to_bridge.empty()) continue;
- // union
- to_bridge = union_ex(to_bridge);
+ // union not needed as we already did one for polygon->expoly conversion, and there was only collapse (no grow) after that.
+ //to_bridge = union_ex(to_bridge);
}
#ifdef SLIC3R_DEBUG
printf("Bridging %zu internal areas at layer %zu\n", to_bridge.size(), layer->id());
@@ -2841,6 +2847,65 @@ PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &defau
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
}
+ void merge_surfaces(LayerRegion* lregion) {
+ //merge regions with same type (other things are all the same anyway)
+ std::map< SurfaceType, std::vector< Surface*>> type2srfs;
+ for (Surface& surface : lregion->fill_surfaces.surfaces) {
+ type2srfs[surface.surface_type].push_back(&surface);
+ }
+ bool changed = false;
+ std::map< SurfaceType, ExPolygons> type2newpolys;
+ for (auto& entry : type2srfs) {
+ if (entry.second.size() > 2) {
+ ExPolygons merged = union_safety_offset_ex(to_expolygons(entry.second));
+ if (merged.size() < entry.second.size()) {
+ changed = true;
+ type2newpolys[entry.first] = std::move(merged);
+ }
+ }
+ }
+ if (changed) {
+ Surfaces newSrfs;
+ for (auto& entry : type2srfs) {
+ if (type2newpolys.find(entry.first) == type2newpolys.end()) {
+ for (Surface* srfPtr : entry.second) {
+ newSrfs.emplace_back(*srfPtr);
+ }
+ } else {
+ for (ExPolygon& expoly : type2newpolys[entry.first]) {
+ newSrfs.emplace_back(*entry.second.front(), expoly);
+ }
+ }
+ }
+ lregion->fill_surfaces.surfaces = std::move(newSrfs);
+ }
+ }
+
+ void PrintObject::clean_surfaces() {
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, this->layers().size() - 1),
+ [this](const tbb::blocked_range<size_t>& range) {
+ for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
+ for (LayerRegion* lregion : this->layers()[idx_layer]->regions()) {
+ coord_t extrusion_width = lregion->flow(frInfill).scaled_width();
+ merge_surfaces(lregion);
+ // collapse too thin solid surfaces.
+ bool changed_type = false;
+ for (Surface& surface : lregion->fill_surfaces.surfaces) {
+ if (surface.has_fill_solid() && surface.has_pos_internal()) {
+ if (offset2_ex(ExPolygons{ surface.expolygon }, -extrusion_width / 2, extrusion_width / 2).empty()) {
+ //convert to sparse
+ surface.surface_type = (surface.surface_type ^ SurfaceType::stDensSolid) | SurfaceType::stDensSparse;
+ changed_type = true;
+ }
+ }
+ }
+ merge_surfaces(lregion);
+
+ }
+ }
+ });
+
+ }
// combine fill surfaces across layers to honor the "infill every N layers" option
// Idempotence of this method is guaranteed by the fact that we don't remove things from
// fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries.
diff --git a/src/libslic3r/SLA/SupportTree.cpp b/src/libslic3r/SLA/SupportTree.cpp
index a0f88ed60..0d2ea4ace 100644
--- a/src/libslic3r/SLA/SupportTree.cpp
+++ b/src/libslic3r/SLA/SupportTree.cpp
@@ -3,6 +3,7 @@
*
*/
+#include <mutex>
#include <numeric>
#include <libslic3r/SLA/SupportTree.hpp>
#include <libslic3r/SLA/SpatIndex.hpp>
diff --git a/src/libslic3r/Semver.hpp b/src/libslic3r/Semver.hpp
index 45d2bac1c..8e21cffdc 100644
--- a/src/libslic3r/Semver.hpp
+++ b/src/libslic3r/Semver.hpp
@@ -20,33 +20,43 @@ class Semver
public:
struct Major { const int i; Major(int i) : i(i) {} };
struct Minor { const int i; Minor(int i) : i(i) {} };
+ struct Counter { const int i; Counter(int i) : i(i) {} }; //for SuSi
struct Patch { const int i; Patch(int i) : i(i) {} };
Semver() : ver(semver_zero()) {}
- Semver(int major, int minor, int patch,
+ Semver(int major, int minor, int counter, int patch,
boost::optional<const std::string&> metadata, boost::optional<const std::string&> prerelease)
: ver(semver_zero())
{
- ver.major = major;
- ver.minor = minor;
- ver.patch = patch;
+ semver_free(&ver);
+ ver.counter_size = 4;
+ ver.counters = new int[4];
+ ver.counters[0] = major;
+ ver.counters[1] = minor;
+ ver.counters[2] = counter;
+ ver.counters[3] = patch;
set_metadata(metadata);
set_prerelease(prerelease);
}
- Semver(int major, int minor, int patch, const char *metadata = nullptr, const char *prerelease = nullptr)
+ Semver(int major, int minor, int counter, int patch, const char *metadata = nullptr, const char *prerelease = nullptr)
: ver(semver_zero())
{
- ver.major = major;
- ver.minor = minor;
- ver.patch = patch;
+ semver_free(&ver);
+ ver.counter_size = 4;
+ ver.counters = new int[4];
+ ver.counters[0] = major;
+ ver.counters[1] = minor;
+ ver.counters[2] = counter;
+ ver.counters[3] = patch;
set_metadata(metadata);
set_prerelease(prerelease);
}
Semver(const std::string &str) : ver(semver_zero())
{
+
auto parsed = parse(str);
if (! parsed) {
throw Slic3r::RuntimeError(std::string("Could not parse version string: ") + str);
@@ -69,13 +79,16 @@ public:
static const Semver inf()
{
- static semver_t ver = { std::numeric_limits<int>::max(), std::numeric_limits<int>::max(), std::numeric_limits<int>::max(), nullptr, nullptr };
+ semver_t ver = { new int[4], 4, nullptr, nullptr };
+ for (int i = 0; i < ver.counter_size; i++)
+ ver.counters[i] = std::numeric_limits<int>::max();
return Semver(ver);
}
static const Semver invalid()
{
- static semver_t ver = { -1, 0, 0, nullptr, nullptr };
+ semver_t ver = { new int[1], 1, nullptr, nullptr };
+ ver.counters[0] = -1;
return Semver(ver);
}
@@ -100,16 +113,18 @@ public:
~Semver() { ::semver_free(&ver); }
// const accessors
- int maj() const { return ver.major; }
- int min() const { return ver.minor; }
- int patch() const { return ver.patch; }
+ //int maj() const { return ver.counter_size > 0 ? ver.counters[0] : 0; }
+ //int min() const { return ver.counter_size > 1 ? ver.counters[1] : 0; }
+ //int counter() const { return ver.counter_size > 2 ? ver.counters[2] : 0; }
+ //int patch() const { return ver.counter_size > 3 ? ver.counters[3] : 0; }
const char* prerelease() const { return ver.prerelease; }
const char* metadata() const { return ver.metadata; }
// Setters
- void set_maj(int maj) { ver.major = maj; }
- void set_min(int min) { ver.minor = min; }
- void set_patch(int patch) { ver.patch = patch; }
+ //void set_maj(int maj) { if(ver.counter_size > 0) ver.counters[0] = maj; }
+ //void set_min(int min) { if (ver.counter_size > 1) ver.counters[1] = min; }
+ //void set_counter(int count) { if (ver.counter_size > 2) ver.counters[2] = count; }
+ //void set_patch(int patch) { if (ver.counter_size > 3) ver.counters[3] = patch; }
void set_metadata(boost::optional<const std::string&> meta) { ver.metadata = meta ? strdup(*meta) : nullptr; }
void set_metadata(const char *meta) { ver.metadata = meta ? strdup(meta) : nullptr; }
void set_prerelease(boost::optional<const std::string&> pre) { ver.prerelease = pre ? strdup(*pre) : nullptr; }
@@ -131,25 +146,32 @@ public:
// Conversion
std::string to_string() const {
- auto res = (boost::format("%1%.%2%.%3%") % ver.major % ver.minor % ver.patch).str();
+ std::string res;
+ for (int i = 0; i < ver.counter_size; i++) {
+ res += ( (i==0 ? boost::format("%1%") : boost::format(".%1%")) % ver.counters[i]).str();
+ }
if (ver.prerelease != nullptr) { res += '-'; res += ver.prerelease; }
if (ver.metadata != nullptr) { res += '+'; res += ver.metadata; }
return res;
}
// Arithmetics
- Semver& operator+=(const Major &b) { ver.major += b.i; return *this; }
- Semver& operator+=(const Minor &b) { ver.minor += b.i; return *this; }
- Semver& operator+=(const Patch &b) { ver.patch += b.i; return *this; }
- Semver& operator-=(const Major &b) { ver.major -= b.i; return *this; }
- Semver& operator-=(const Minor &b) { ver.minor -= b.i; return *this; }
- Semver& operator-=(const Patch &b) { ver.patch -= b.i; return *this; }
- Semver operator+(const Major &b) const { Semver res(*this); return res += b; }
- Semver operator+(const Minor &b) const { Semver res(*this); return res += b; }
- Semver operator+(const Patch &b) const { Semver res(*this); return res += b; }
- Semver operator-(const Major &b) const { Semver res(*this); return res -= b; }
- Semver operator-(const Minor &b) const { Semver res(*this); return res -= b; }
- Semver operator-(const Patch &b) const { Semver res(*this); return res -= b; }
+ //Semver& operator+=(const Major &b) { set_maj(maj()+b.i); return *this; }
+ //Semver& operator+=(const Minor &b) { set_min(min() + b.i); return *this; }
+ //Semver& operator+=(const Counter& b) { set_counter(counter() + b.i); return *this; }
+ //Semver& operator+=(const Patch &b) { set_patch(patch() + b.i); return *this; }
+ //Semver& operator-=(const Major& b) { set_maj(maj() - b.i); return *this; }
+ //Semver& operator-=(const Minor& b) { set_min(min() - b.i); return *this; }
+ //Semver& operator-=(const Counter& b) { set_counter(counter() - b.i); return *this; }
+ //Semver& operator-=(const Patch& b) { set_patch(patch() - b.i); return *this; }
+ //Semver operator+(const Major &b) const { Semver res(*this); return res += b; }
+ //Semver operator+(const Minor &b) const { Semver res(*this); return res += b; }
+ //Semver operator+(const Counter& b) const { Semver res(*this); return res += b; }
+ //Semver operator+(const Patch& b) const { Semver res(*this); return res += b; }
+ //Semver operator-(const Major &b) const { Semver res(*this); return res -= b; }
+ //Semver operator-(const Minor &b) const { Semver res(*this); return res -= b; }
+ //Semver operator-(const Counter& b) const { Semver res(*this); return res -= b; }
+ //Semver operator-(const Patch& b) const { Semver res(*this); return res -= b; }
// Stream output
friend std::ostream& operator<<(std::ostream& os, const Semver &self) {
@@ -159,9 +181,10 @@ public:
private:
semver_t ver;
+
Semver(semver_t ver) : ver(ver) {}
- static semver_t semver_zero() { return { 0, 0, 0, nullptr, nullptr }; }
+ static semver_t semver_zero() { return { nullptr, 0, nullptr, nullptr }; }
static char * strdup(const std::string &str) { return ::semver_strdup(str.data()); }
};
diff --git a/src/libslic3r/ShortestPath.cpp b/src/libslic3r/ShortestPath.cpp
index 19caf12e2..aae443395 100644
--- a/src/libslic3r/ShortestPath.cpp
+++ b/src/libslic3r/ShortestPath.cpp
@@ -1979,7 +1979,7 @@ template<class T> static inline T chain_path_items(const Points &points, const T
return out;
}
-ClipperLib::PolyNodes chain_clipper_polynodes(const Points &points, const ClipperLib::PolyNodes &items)
+std::vector<ClipperLib::PolyNode*> chain_clipper_polynodes(const Points &points, const std::vector<ClipperLib::PolyNode*> &items)
{
return chain_path_items(points, items);
}
diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp
index 4e53a46ca..d1bfa9a4a 100644
--- a/src/libslic3r/SupportMaterial.cpp
+++ b/src/libslic3r/SupportMaterial.cpp
@@ -11,6 +11,8 @@
#include <cmath>
#include <memory>
+#include <atomic>
+#include <thread>
#include <boost/log/trivial.hpp>
#include <boost/container/static_vector.hpp>
@@ -1236,9 +1238,9 @@ namespace SupportMaterialInternal {
}
static bool has_bridging_perimeters(const ExtrusionEntityCollection &perimeters)
{
- for (const ExtrusionEntity *ee : perimeters.entities) {
+ for (const ExtrusionEntity *ee : perimeters.entities()) {
if (ee->is_collection()) {
- for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities) {
+ for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities()) {
//assert(! ee2->is_collection()); // there are loops for perimeters and collections for thin walls !!
if (ee2->is_loop())
if (has_bridging_perimeters(*static_cast<const ExtrusionLoop*>(ee2)))
@@ -1251,7 +1253,7 @@ namespace SupportMaterialInternal {
}
static bool has_bridging_fills(const ExtrusionEntityCollection &fills)
{
- for (const ExtrusionEntity *ee : fills.entities) {
+ for (const ExtrusionEntity *ee : fills.entities()) {
if (ee->is_collection()) {
if(has_bridging_fills(*static_cast<const ExtrusionEntityCollection*>(ee)))
return true;
@@ -1304,7 +1306,7 @@ namespace SupportMaterialInternal {
{
for (const ExtrusionEntity *ee : perimeters) {
if (ee->is_collection()) {
- collect_bridging_perimeter_areas(static_cast<const ExtrusionEntityCollection*>(ee)->entities, expansion_scaled, out);
+ collect_bridging_perimeter_areas(static_cast<const ExtrusionEntityCollection*>(ee)->entities(), expansion_scaled, out);
} else if (ee->is_loop())
collect_bridging_perimeter_areas(*static_cast<const ExtrusionLoop*>(ee), expansion_scaled, out);
}
@@ -2925,7 +2927,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
if (region->region().config().overhangs_width.value > 0)
// Add bridging perimeters.
- SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters.entities, gap_xy_scaled, polygons_trimming);
+ SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters.entities(), gap_xy_scaled, polygons_trimming);
}
if (! some_region_overlaps)
break;
@@ -3337,7 +3339,7 @@ static inline void fill_expolygons_with_sheath_generate_paths(
eec = std::make_unique<ExtrusionEntityCollection>();
eec->set_can_sort_reverse(false, true);
}
- ExtrusionEntitiesPtr &out = no_sort ? eec->entities : dst;
+ ExtrusionEntitiesPtr &out = no_sort ? eec->set_entities() : dst;
// Draw the perimeters.
Polylines polylines;
polylines.reserve(expoly.holes.size() + 1);
@@ -3406,8 +3408,8 @@ struct MyLayerExtruded
*m_polygons_to_extrude = union_safety_offset(*m_polygons_to_extrude);
}
// 2) Merge the extrusions.
- this->extrusions.entities.insert(this->extrusions.entities.end(), other.extrusions.entities.begin(), other.extrusions.entities.end());
- other.extrusions.entities.clear();
+ this->extrusions.set_entities().insert(this->extrusions.entities().end(), other.extrusions.entities().begin(), other.extrusions.entities().end());
+ other.extrusions.set_entities().clear();
// 3) Merge the infill polygons.
Slic3r::polygons_append(this->layer->polygons, std::move(other.layer->polygons));
this->layer->polygons = union_safety_offset(this->layer->polygons);
@@ -3657,7 +3659,7 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
// Transform loops into ExtrusionPath objects.
extrusion_entities_append_paths(
- top_contact_layer.extrusions.entities,
+ top_contact_layer.extrusions.set_entities(),
std::move(loop_lines),
erSupportMaterialInterface, flow.mm3_per_mm(), flow.width(), flow.height());
}
@@ -3685,8 +3687,8 @@ public:
virtual void use(const ExtrusionMultiPath3D &multipath) override { if (!multipath.paths.empty()) extrusion_path_template = &multipath.paths.front(); }
virtual void use(const ExtrusionLoop &loop) override { if (!loop.paths.empty()) extrusion_path_template = &loop.paths.front(); }
virtual void use(const ExtrusionEntityCollection &collection) override {
- auto it = collection.entities.begin();
- while (extrusion_path_template == nullptr && it != collection.entities.end()) {
+ auto it = collection.entities().begin();
+ while (extrusion_path_template == nullptr && it != collection.entities().end()) {
(*it)->visit(*this);
++it;
}
@@ -3719,7 +3721,7 @@ void modulate_extrusion_by_overlapping_layers(
// Get the initial extrusion parameters.
GetFirstPath getFirstPathVisitor;
- flatten_extrusions_in_out.entities.front()->visit(getFirstPathVisitor);
+ flatten_extrusions_in_out.entities().front()->visit(getFirstPathVisitor);
const ExtrusionPath *extrusion_path_template = getFirstPathVisitor.extrusion_path_template;
assert(extrusion_path_template != nullptr);
ExtrusionRole extrusion_role = extrusion_path_template->role();
@@ -3795,7 +3797,7 @@ void modulate_extrusion_by_overlapping_layers(
// Collect the paths of this_layer.
{
Polylines &polylines = path_fragments.back().polylines;
- for (const ExtrusionEntity *ee : flatten_extrusions_in_out.entities) {
+ for (const ExtrusionEntity *ee : flatten_extrusions_in_out.entities()) {
for (Polyline &polyline : ee->as_polylines()) {
polylines.emplace_back(std::move(polyline));
}
@@ -3935,18 +3937,18 @@ void modulate_extrusion_by_overlapping_layers(
if (!multipath.paths.empty()) {
if (multipath.paths.size() == 1) {
// This path was not fragmented.
- extrusions_in_out.entities.push_back(new ExtrusionPath(std::move(multipath.paths.front())));
+ extrusions_in_out.append(ExtrusionEntitiesPtr{ new ExtrusionPath(std::move(multipath.paths.front())) });
} else {
// This path was fragmented. Copy the collection as a whole object, so the order inside the collection will not be changed
// during the chaining of extrusions_in_out.
- extrusions_in_out.entities.push_back(new ExtrusionMultiPath(std::move(multipath)));
+ extrusions_in_out.append(ExtrusionEntitiesPtr{ new ExtrusionMultiPath(std::move(multipath)) });
}
}
}
// If there are any non-consumed fragments, add them separately.
//FIXME this shall not happen, if the Clipper works as expected and all paths split to fragments could be re-connected.
for (auto it_fragment = path_fragments.begin(); it_fragment != path_fragments.end(); ++ it_fragment)
- extrusion_entities_append_paths(extrusions_in_out.entities, std::move(it_fragment->polylines), extrusion_role, it_fragment->mm3_per_mm, it_fragment->width, it_fragment->height);
+ extrusion_entities_append_paths(extrusions_in_out.set_entities(), std::move(it_fragment->polylines), extrusion_role, it_fragment->mm3_per_mm, it_fragment->width, it_fragment->height);
}
void PrintObjectSupportMaterial::generate_toolpaths(
@@ -4008,7 +4010,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
{
assert(support_layer_id < raft_layers.size());
SupportLayer &support_layer = *support_layers[support_layer_id];
- assert(support_layer.support_fills.entities.empty());
+ assert(support_layer.support_fills.entities().empty());
MyLayer &raft_layer = *raft_layers[support_layer_id];
std::unique_ptr<Fill> filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(m_support_params.contact_fill_pattern)); //m_support_params.interface_fill_pattern)); FIXME choose
@@ -4031,7 +4033,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
filler->link_max_length = scale_t(m_support_params.support_material_flow.spacing() * link_max_length_factor / m_support_params.support_density);
fill_expolygons_with_sheath_generate_paths(
// Destination
- support_layer.support_fills.entities,
+ support_layer.support_fills.set_entities(),
// Regions to fill
to_infill_polygons,
// Filler and its parameters
@@ -4074,7 +4076,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
filler->link_max_length = coord_t(scale_(spacing * link_max_length_factor / density));
fill_expolygons_with_sheath_generate_paths(
// Destination
- support_layer.support_fills.entities,
+ support_layer.support_fills.set_entities(),
// Regions to fill
raft_layer.polygons,
// Filler and its parameters
@@ -4250,7 +4252,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
fill_expolygons_generate_paths(
// Destination
- layer_ex.extrusions.entities,
+ layer_ex.extrusions.set_entities(),
// Regions to fill
union_safety_offset_ex(layer_ex.polygons_to_extrude()),
// Filler and its parameters
@@ -4273,7 +4275,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
filler->link_max_length = scale_t(filler_spacing * link_max_length_factor / m_support_params.interface_density);
fill_expolygons_generate_paths(
// Destination
- base_interface_layer.extrusions.entities,
+ base_interface_layer.extrusions.set_entities(),
//base_layer_interface.extrusions,
// Regions to fill
union_safety_offset_ex(base_interface_layer.polygons_to_extrude()),
@@ -4318,7 +4320,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
}
fill_expolygons_with_sheath_generate_paths(
// Destination
- base_layer.extrusions.entities,
+ base_layer.extrusions.set_entities(),
// Regions to fill
base_layer.polygons_to_extrude(),
// Filler and its parameters
@@ -4393,7 +4395,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
#ifndef NDEBUG
struct Test {
static bool verify_nonempty(const ExtrusionEntityCollection *collection) {
- for (const ExtrusionEntity *ee : collection->entities) {
+ for (const ExtrusionEntity *ee : collection->entities()) {
if (const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ee))
assert(! path->empty());
else if (const ExtrusionMultiPath *multipath = dynamic_cast<const ExtrusionMultiPath*>(ee))
diff --git a/src/libslic3r/Surface.hpp b/src/libslic3r/Surface.hpp
index ac2feb222..e12e15056 100644
--- a/src/libslic3r/Surface.hpp
+++ b/src/libslic3r/Surface.hpp
@@ -35,7 +35,10 @@ inline SurfaceType operator|(SurfaceType a, SurfaceType b) {
return static_cast<SurfaceType>(static_cast<uint16_t>(a) | static_cast<uint16_t>(b));
}
inline SurfaceType operator&(SurfaceType a, SurfaceType b) {
- return static_cast<SurfaceType>(static_cast<uint16_t>(a)& static_cast<uint16_t>(b));
+ return static_cast<SurfaceType>(static_cast<uint16_t>(a) & static_cast<uint16_t>(b));
+}
+inline SurfaceType operator^(SurfaceType a, SurfaceType b) {
+ return static_cast<SurfaceType>(static_cast<uint16_t>(a) ^ static_cast<uint16_t>(b));
}
inline SurfaceType operator|=(SurfaceType& a, SurfaceType b) {
a = a | b; return a;
diff --git a/src/libslic3r/pchheader.hpp b/src/libslic3r/pchheader.hpp
index e6591f574..7317eb6c2 100644
--- a/src/libslic3r/pchheader.hpp
+++ b/src/libslic3r/pchheader.hpp
@@ -35,6 +35,7 @@
#include <locale>
#include <map>
#include <memory>
+#include <mutex>
#include <numeric>
#include <ostream>
#include <queue>
diff --git a/src/platform/unix/BuildLinuxImage.sh.in b/src/platform/unix/BuildLinuxImage.sh.in
index 168e8c7a0..4b5457a0d 100644
--- a/src/platform/unix/BuildLinuxImage.sh.in
+++ b/src/platform/unix/BuildLinuxImage.sh.in
@@ -1,7 +1,13 @@
#!/bin/bash
+# Our sysctl call may be run as normal user,
+# but /sbin is not always in normal users' PATH.
+if [[ -f /sbin/sysctl && -x /sbin/sysctl ]]; then sysctl_bin=/sbin/sysctl
+else sysctl_bin=sysctl # If not found in sbin, hope
+fi
+
export ROOT=`pwd`
-export NCORES=`sysctl -n hw.ncpu`
+export NCORES=`"$sysctl_bin" -n hw.ncpu`
while getopts ":ih" opt; do
case ${opt} in
diff --git a/src/platform/unix/build_appimage.sh.in b/src/platform/unix/build_appimage.sh.in
index 953fe4af6..305a6c796 100644
--- a/src/platform/unix/build_appimage.sh.in
+++ b/src/platform/unix/build_appimage.sh.in
@@ -14,7 +14,7 @@ chmod +x AppRun
cp resources/icons/@SLIC3R_APP_KEY@_192px.png @SLIC3R_APP_KEY@.png
cat <<EOF > Slic3r.desktop
[Desktop Entry]
-Name=@SLIC3R_APP_NAME@
+Name=@SLIC3R_APP_KEY@
Exec=AppRun %F
Icon=@SLIC3R_APP_KEY@
Type=Application
diff --git a/src/semver/semver.c b/src/semver/semver.c
index e8bd6edcf..9ffaaf2ee 100644
--- a/src/semver/semver.c
+++ b/src/semver/semver.c
@@ -163,6 +163,40 @@ semver_parse (const char *str, semver_t *ver) {
}
/**
+ * count he numbezr of int
+ */
+int
+semver_count_version(const char* str) {
+ size_t len;
+ int index, value;
+ char* slice, * next, * endptr;
+ slice = (char*)str;
+ index = 0;
+
+ while (slice != NULL && index++ < 4) {
+ next = strchr(slice, DELIMITER[0]);
+ if (next == NULL)
+ len = strlen(slice);
+ else
+ len = next - slice;
+ if (len > SLICE_SIZE) return -1;
+
+ /* Cast to integer and store */
+ value = strtol(slice, &endptr, 10);
+ if (endptr != next && *endptr != '\0') return -1;
+
+ /* Continue with the next slice */
+ if (next == NULL)
+ slice = NULL;
+ else
+ slice = next + 1;
+ }
+
+ // Major and minor versions are mandatory, patch version is not mandatory.
+ return index;
+}
+
+/**
* Parses a given string as semver expression.
*
* Returns:
@@ -178,37 +212,37 @@ semver_parse_version (const char *str, semver_t *ver) {
char *slice, *next, *endptr;
slice = (char *) str;
index = 0;
-
- // non mandatory
- ver->patch = 0;
-
- while (slice != NULL && index++ < 4) {
- next = strchr(slice, DELIMITER[0]);
- if (next == NULL)
- len = strlen(slice);
- else
- len = next - slice;
- if (len > SLICE_SIZE) return -1;
-
- /* Cast to integer and store */
- value = strtol(slice, &endptr, 10);
- if (endptr != next && *endptr != '\0') return -1;
-
- switch (index) {
- case 1: ver->major = value; break;
- case 2: ver->minor = value; break;
- case 3: ver->patch = value; break;
- }
-
- /* Continue with the next slice */
- if (next == NULL)
- slice = NULL;
- else
- slice = next + 1;
+ if (ver->counters) {
+ free(ver->counters);
+ ver->counters = NULL;
+ }
+ ver->counter_size = semver_count_version(str);
+ if (ver->counter_size != 0) {
+ ver->counters = malloc(ver->counter_size * sizeof(int));
+
+ while (slice != NULL && index++ < 4) {
+ next = strchr(slice, DELIMITER[0]);
+ if (next == NULL)
+ len = strlen(slice);
+ else
+ len = next - slice;
+ if (len > SLICE_SIZE) return -1;
+
+ /* Cast to integer and store */
+ value = strtol(slice, &endptr, 10);
+ if (endptr != next && *endptr != '\0') return -1;
+
+ ver->counters[index - 1] = value;
+
+ /* Continue with the next slice */
+ if (next == NULL)
+ slice = NULL;
+ else
+ slice = next + 1;
+ }
}
-
// Major and minor versions are mandatory, patch version is not mandatory.
- return (index == 2 || index == 3) ? 0 : -1;
+ return (index >= 2) ? 0 : -1;
}
static int
@@ -280,12 +314,11 @@ semver_compare_prerelease (semver_t x, semver_t y) {
int
semver_compare_version (semver_t x, semver_t y) {
- int res;
+ int res = binary_comparison(x.counter_size, y.counter_size);
- if ((res = binary_comparison(x.major, y.major)) == 0) {
- if ((res = binary_comparison(x.minor, y.minor)) == 0) {
- return binary_comparison(x.patch, y.patch);
- }
+ for (int i = 0; i < x.counter_size && i < y.counter_size; i++) {
+ if ((res = binary_comparison(x.counters[i], y.counters[i])) != 0)
+ return res;
}
return res;
@@ -379,9 +412,9 @@ semver_lte (semver_t x, semver_t y) {
int
semver_satisfies_caret (semver_t x, semver_t y) {
- if (x.major == y.major) {
- if (x.major == 0) {
- return x.minor >= y.minor;
+ if (x.counter_size > 0 && y.counter_size > 0 && x.counters[0] == y.counters[0]) {
+ if (x.counters[0] == 0) {
+ return x.counter_size > 1 && y.counter_size > 1 && x.counters[1] >= y.counters[1];
}
return 1;
}
@@ -402,8 +435,8 @@ semver_satisfies_caret (semver_t x, semver_t y) {
int
semver_satisfies_patch (semver_t x, semver_t y) {
- return x.major == y.major
- && x.minor == y.minor;
+ return x.counter_size > 1 && y.counter_size > 1 && x.counters[0] == y.counters[0]
+ && x.counters[1] == y.counters[1];
}
/**
@@ -480,6 +513,11 @@ semver_free (semver_t *x) {
free(x->prerelease);
x->prerelease = NULL;
}
+ if (x->counters) {
+ x->counter_size = 0;
+ free(x->counters);
+ x->counters = NULL;
+ }
}
/**
@@ -507,9 +545,9 @@ concat_char (char * str, char * x, char * sep) {
void
semver_render (semver_t *x, char *dest) {
- if (x->major) concat_num(dest, x->major, NULL);
- if (x->minor) concat_num(dest, x->minor, DELIMITER);
- if (x->patch) concat_num(dest, x->patch, DELIMITER);
+ for (int i = 0; i < x->counter_size; ++i) {
+ concat_num(dest, x->counters[i], i==0 ? NULL : DELIMITER);
+ }
if (x->prerelease) concat_char(dest, x->prerelease, PR_DELIMITER);
if (x->metadata) concat_char(dest, x->metadata, MT_DELIMITER);
}
@@ -519,18 +557,21 @@ semver_render (semver_t *x, char *dest) {
*/
void
-semver_bump (semver_t *x) {
- x->major++;
+semver_bump_major (semver_t *x) {
+ if(x->counter_size > 0)
+ x->counters[0]++;
}
void
semver_bump_minor (semver_t *x) {
- x->minor++;
+ if (x->counter_size > 1)
+ x->counters[1]++;
}
void
-semver_bump_patch (semver_t *x) {
- x->patch++;
+semver_bump (semver_t *x, int idx) {
+ if (x->counter_size > idx)
+ x->counters[idx]++;
}
/**
@@ -612,9 +653,9 @@ semver_numeric (semver_t *x) {
char buf[SLICE_SIZE * 3];
memset(&buf, 0, SLICE_SIZE * 3);
- if (x->major) concat_num(buf, x->major, NULL);
- if (x->minor) concat_num(buf, x->minor, NULL);
- if (x->patch) concat_num(buf, x->patch, NULL);
+ for (int i = 0; i < x->counter_size; ++i) {
+ concat_num(buf, x->counters[i], NULL);
+ }
num = parse_int(buf);
if(num == -1) return -1;
@@ -625,11 +666,17 @@ semver_numeric (semver_t *x) {
return num;
}
-char *semver_strdup(const char *src) {
- if (src == NULL) return NULL;
- size_t len = strlen(src) + 1;
- char *res = malloc(len);
- return res != NULL ? (char *) memcpy(res, src, len) : NULL;
+char* semver_strdup(const char* src) {
+ if (src == NULL) return NULL;
+ size_t len = strlen(src) + 1;
+ char* res = malloc(len);
+ return res != NULL ? (char*)memcpy(res, src, len) : NULL;
+}
+
+int* semver_intdup(const int* src, int len) {
+ if (src == NULL) return NULL;
+ int* res = malloc(len * sizeof(int));
+ return res != NULL ? (int*)memcpy(res, src, len * sizeof(int)) : NULL;
}
semver_t
@@ -639,7 +686,10 @@ semver_copy(const semver_t *ver) {
res.metadata = strdup(ver->metadata);
}
if (ver->prerelease != NULL) {
- res.prerelease = strdup(ver->prerelease);
+ res.prerelease = strdup(ver->prerelease);
+ }
+ if (ver->counters) {
+ res.counters = semver_intdup(ver->counters, ver->counter_size);
}
return res;
}
diff --git a/src/semver/semver.h b/src/semver/semver.h
index 01a15fc43..e43f00463 100644
--- a/src/semver/semver.h
+++ b/src/semver/semver.h
@@ -21,9 +21,8 @@ extern "C" {
*/
typedef struct semver_version_s {
- int major;
- int minor;
- int patch;
+ int * counters;
+ int counter_size;
char * metadata;
char * prerelease;
} semver_t;
@@ -72,7 +71,10 @@ int
semver_parse (const char *str, semver_t *ver);
int
-semver_parse_version (const char *str, semver_t *ver);
+semver_count_version(const char* str);
+
+int
+semver_parse_version(const char* str, semver_t* ver);
void
semver_render (semver_t *x, char *dest);
@@ -81,13 +83,13 @@ int
semver_numeric (semver_t *x);
void
-semver_bump (semver_t *x);
+semver_bump_major (semver_t *x);
void
semver_bump_minor (semver_t *x);
void
-semver_bump_patch (semver_t *x);
+semver_bump (semver_t *x, int idx);
void
semver_free (semver_t *x);
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index 3026c987c..0f9294ece 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -1747,7 +1747,7 @@ void ExtrusionToVert::use(const ExtrusionPath3D &path3D) { _3DScene::extrusionen
void ExtrusionToVert::use(const ExtrusionMultiPath &multipath) { _3DScene::extrusionentity_to_verts(multipath, print_z, copy, volume); }
void ExtrusionToVert::use(const ExtrusionMultiPath3D &multipath3D) { _3DScene::extrusionentity_to_verts(multipath3D, print_z, copy, volume); }
void ExtrusionToVert::use(const ExtrusionLoop &loop) { _3DScene::extrusionentity_to_verts(loop, print_z, copy, volume); }
-void ExtrusionToVert::use(const ExtrusionEntityCollection &collection) { for (const ExtrusionEntity *extrusion_entity : collection.entities) extrusion_entity->visit(*this); }
+void ExtrusionToVert::use(const ExtrusionEntityCollection &collection) { for (const ExtrusionEntity *extrusion_entity : collection.entities()) extrusion_entity->visit(*this); }
void _3DScene::extrusionentity_to_verts(const ExtrusionEntity &extrusion_entity, float print_z, const Point &copy, GLVolume &volume)
{
diff --git a/src/slic3r/GUI/CalibrationOverBridgeDialog.cpp b/src/slic3r/GUI/CalibrationOverBridgeDialog.cpp
index 929e14f09..4d570f130 100644
--- a/src/slic3r/GUI/CalibrationOverBridgeDialog.cpp
+++ b/src/slic3r/GUI/CalibrationOverBridgeDialog.cpp
@@ -94,6 +94,7 @@ void CalibrationOverBridgeDialog::create_geometry(bool over_bridge) {
const ConfigOptionFloat* extruder_clearance_radius = print_config->option<ConfigOptionFloat>("extruder_clearance_radius");
const ConfigOptionPoints* bed_shape = printer_config->option<ConfigOptionPoints>("bed_shape");
const float brim_width = print_config->option<ConfigOptionFloat>("brim_width")->getFloat();
+ const float skirt_width = print_config->option("skirts")->getInt() == 0 ? 0 : print_config->option("skirt_distance")->getFloat() + print_config->option("skirts")->getInt() * nozzle_diameter * 2;
Vec2d bed_size = BoundingBoxf(bed_shape->values).size();
Vec2d bed_min = BoundingBoxf(bed_shape->values).min;
float offsetx = 3 + 30 * xyz_scale + extruder_clearance_radius->value + brim_width + (brim_width > extruder_clearance_radius->value ? brim_width - extruder_clearance_radius->value : 0);
@@ -106,7 +107,7 @@ void CalibrationOverBridgeDialog::create_geometry(bool over_bridge) {
model.objects[objs_idx[5]]->translate({ bed_min.x() + bed_size.x() / 2 + offsetx / 2, bed_min.y() + bed_size.y() / 2 + offsety, 0 });
// if not enough space, forget about complete_objects
- if (bed_size.y() < offsety * 2 + 30 * xyz_scale + brim_width || bed_size.x() < offsetx + 35 * xyz_scale + brim_width)
+ if (bed_size.y() < offsety * 2 + 30 * xyz_scale + brim_width * 2 + skirt_width * 2 + 5 || bed_size.x() < offsetx + 35 * xyz_scale + brim_width * 2 + skirt_width * 2 + 5)
has_to_arrange = true;
/// --- main config, please modify object config when possible ---
diff --git a/src/slic3r/GUI/CalibrationRetractionDialog.hpp b/src/slic3r/GUI/CalibrationRetractionDialog.hpp
index f916534bb..41ac4512a 100644
--- a/src/slic3r/GUI/CalibrationRetractionDialog.hpp
+++ b/src/slic3r/GUI/CalibrationRetractionDialog.hpp
@@ -10,7 +10,7 @@ class CalibrationRetractionDialog : public CalibrationAbstractDialog
{
public:
- CalibrationRetractionDialog(GUI_App* app, MainFrame* mainframe) : CalibrationAbstractDialog(app, mainframe, "Flow calibration") { create(boost::filesystem::path("calibration") / "retraction", "retraction.html", wxSize(900, 500)); }
+ CalibrationRetractionDialog(GUI_App* app, MainFrame* mainframe) : CalibrationAbstractDialog(app, mainframe, "Retraction calibration") { create(boost::filesystem::path("calibration") / "retraction", "retraction.html", wxSize(900, 500)); }
virtual ~CalibrationRetractionDialog() {}
protected:
diff --git a/src/slic3r/GUI/FreeCADDialog.cpp b/src/slic3r/GUI/FreeCADDialog.cpp
index f8602fe87..7e1e15cd3 100644
--- a/src/slic3r/GUI/FreeCADDialog.cpp
+++ b/src/slic3r/GUI/FreeCADDialog.cpp
@@ -736,7 +736,9 @@ void FreeCADDialog::createSTC()
m_text->Bind(wxEVT_STC_CHARADDED, &FreeCADDialog::on_char_add, this);
m_text->Bind(wxEVT_KEY_DOWN, &FreeCADDialog::on_key_type, this);
m_text->Bind(wxEVT_CHAR, &FreeCADDialog::on_char_type, this);
+#if (wxMAJOR_VERSION > 3) || (wxMAJOR_VERSION == 3 && wxMINOR_VERSION >= 1)
m_text->Bind(wxEVT_STC_AUTOCOMP_COMPLETED, &FreeCADDialog::on_autocomp_complete, this);
+#endif
m_text->Connect(wxID_ANY,
wxEVT_KEY_DOWN,
wxKeyEventHandler(FreeCADDialog::on_key_type),
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 7fa2081d0..67e32be03 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -6190,17 +6190,17 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
_3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
volume(idx_layer, layerm->region().config().perimeter_extruder.value, 0));
if (ctxt.has_infill) {
- for (const ExtrusionEntity *ee : layerm->fills.entities) {
+ for (const ExtrusionEntity *ee : layerm->fills.entities()) {
// fill represents infill extrusions of a single island.
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
- if (fill != nullptr && !fill->entities.empty())
+ if (fill != nullptr && !fill->entities().empty())
_3DScene::extrusionentity_to_verts(*fill,
float(layer->print_z),
copy,
volume(idx_layer,
- is_solid_infill(fill->entities.front()->role()) ?
- layerm->region().config().solid_infill_extruder :
- layerm->region().config().infill_extruder,
+ is_solid_infill(fill->entities().front()->role()) ?
+ layerm->region().config().solid_infill_extruder :
+ layerm->region().config().infill_extruder,
1));
}
}
@@ -6208,7 +6208,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c
if (ctxt.has_support) {
const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
if (support_layer) {
- for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
+ for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities())
if (extrusion_entity != nullptr)
_3DScene::extrusionentity_to_verts(*extrusion_entity, float(layer->print_z), copy,
volume(idx_layer,
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index fa5e7a0b5..2bedfb821 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -892,7 +892,14 @@ void GUI_App::init_app_config()
// Mac : "~/Library/Application Support/Slic3r"
if (data_dir().empty()) {
- //check if there is a "configuration" directory next to the resources
+ //check if there is a "configuration" directory
+#ifdef __APPLE__
+ //... next to the app bundle on MacOs
+ if (boost::filesystem::exists(boost::filesystem::path{ resources_dir() } / ".." / ".." / ".." / "configuration")) {
+ set_data_dir((boost::filesystem::path{ resources_dir() } / ".." / ".." / ".." / "configuration").string());
+ } else
+#endif
+ //... next to the resources directory
if (boost::filesystem::exists(boost::filesystem::path{ resources_dir() } / ".." / "configuration")) {
set_data_dir((boost::filesystem::path{ resources_dir() } / ".." / "configuration").string());
} else {
@@ -1176,7 +1183,7 @@ bool GUI_App::on_init_inner()
}
wxString artist;
if (!file_name.empty() && file_name != (std::string(SLIC3R_APP_NAME) + L(" icon"))) {
- wxString splash_screen_path = wxString::FromUTF8((boost::filesystem::path(Slic3r::resources_dir()) / "splashscreen" / file_name).string());
+ wxString splash_screen_path = wxString::FromUTF8((boost::filesystem::path(Slic3r::resources_dir()) / "splashscreen" / file_name).string().c_str());
// make a bitmap with dark grey banner on the left side
bmp = SplashScreen::MakeBitmap(wxBitmap(splash_screen_path, wxBITMAP_TYPE_JPEG));
diff --git a/src/slic3r/GUI/InstanceCheck.cpp b/src/slic3r/GUI/InstanceCheck.cpp
index a7937be0f..eba3bd0b9 100644
--- a/src/slic3r/GUI/InstanceCheck.cpp
+++ b/src/slic3r/GUI/InstanceCheck.cpp
@@ -24,6 +24,7 @@
#endif //WIN32
#if __linux__
+#include <mutex>
#include <dbus/dbus.h> /* Pull in all of D-Bus headers. */
#endif //__linux__
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index 2ae2c5059..35111c155 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -142,7 +142,7 @@ public:
Plater &operator=(const Plater &) = delete;
~Plater() = default;
- const ProjectDirtyStateManager& Plater::get_dirty() const;
+ const ProjectDirtyStateManager& get_dirty() const;
bool is_project_dirty() const;
bool is_presets_dirty() const;
void update_project_dirty_from_presets();
diff --git a/src/slic3r/GUI/RemovableDriveManager.hpp b/src/slic3r/GUI/RemovableDriveManager.hpp
index 29363647c..5456f45ec 100644
--- a/src/slic3r/GUI/RemovableDriveManager.hpp
+++ b/src/slic3r/GUI/RemovableDriveManager.hpp
@@ -3,9 +3,9 @@
#include <vector>
#include <string>
+#include <mutex>
#include <boost/thread.hpp>
-#include <mutex>
#include <condition_variable>
// Custom wxWidget events
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index eafafdffb..c47d928d5 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -3153,8 +3153,11 @@ void TabPrinter::toggle_options()
}
// wipe_only_crossing can only work if avoid_crossing_perimeters
- if (!full_print_config.opt_bool("avoid_crossing_perimeters"))
- get_field("wipe_only_crossing", i)->toggle(false);
+ if (!full_print_config.opt_bool("avoid_crossing_perimeters")) {
+ field = get_field("wipe_only_crossing", i);
+ if (field)
+ field->toggle(false);
+ }
if (use_firmware_retraction && wipe) {
//wxMessageDialog dialog(parent(),
diff --git a/src/slic3r/GUI/UnsavedChangesDialog.cpp b/src/slic3r/GUI/UnsavedChangesDialog.cpp
index 6a9c1b874..f2afccfd7 100644
--- a/src/slic3r/GUI/UnsavedChangesDialog.cpp
+++ b/src/slic3r/GUI/UnsavedChangesDialog.cpp
@@ -868,7 +868,9 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
}
if (!m_transfer_btn && (ActionButtons::KEEP & m_buttons))
add_btn(&m_transfer_btn, m_move_btn_id, "paste_menu", Action::Transfer, _L("Keep"));
-
+#ifdef __WXGTK__
+ ScalableButton* cancel_btn = new ScalableButton(this, wxID_ANY, "cross", _L("Cancel"), wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, true, 24);
+#else
{ // "Don't save" / "Discard" button
std::string btn_icon = (ActionButtons::DONT_SAVE & m_buttons) ? "" : (dependent_presets || (ActionButtons::KEEP & m_buttons)) ? "switch_presets" : "exit";
wxString btn_label = (ActionButtons::DONT_SAVE & m_buttons) ? _L("Don't save") : _L("Discard");
@@ -880,6 +882,7 @@ void UnsavedChangesDialog::build(Preset::Type type, PresetCollection* dependent_
add_btn(&m_save_btn, m_save_btn_id, "save", Action::Save, _L("Save"));
ScalableButton* cancel_btn = new ScalableButton(this, wxID_CANCEL, "cross", _L("Cancel"), wxDefaultSize, wxDefaultPosition, wxBORDER_DEFAULT, true, 24);
+#endif
buttons->Add(cancel_btn, 1, wxLEFT|wxRIGHT, 5);
cancel_btn->SetFont(btn_font);
cancel_btn->Bind(wxEVT_BUTTON, [this](wxEvent&) { this->EndModal(wxID_CANCEL); });
diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp
index 8d4c7e3f7..56c1ce20e 100644
--- a/src/slic3r/Utils/PresetUpdater.cpp
+++ b/src/slic3r/Utils/PresetUpdater.cpp
@@ -241,6 +241,19 @@ void PresetUpdater::priv::prune_tmps() const
}
}
+//parse the string, if it doesn't contain a valid version string, return invalid version.
+Semver get_version(const std::string &str, const std::regex &regexp) {
+ std::smatch match;
+ if (std::regex_match(str, match, regexp)) {
+ std::string version_cleaned = match[0];
+ const boost::optional<Semver> version = Semver::parse(version_cleaned);
+ if (version.has_value()) {
+ return *version;
+ }
+ }
+ return Semver::invalid();
+}
+
// Get Slic3rPE version available online, save in AppConfig.
void PresetUpdater::priv::sync_version() const
{
@@ -343,33 +356,49 @@ void PresetUpdater::priv::parse_version_string(const std::string& constbody) con
std::stringstream json_stream(constbody);
boost::property_tree::read_json(json_stream, root);
bool i_am_pre = false;
- std::string best_pre = "1";
- std::string best_release = "1";
+ //at least two number, use '.' as separator. can be followed by -Az23 for prereleased and +Az42 for metadata
+ std::regex matcher("[0-9]+\.[0-9]+(\.[0-9]+)*(-[A-Za-z0-9]+)?(\\+[A-Za-z0-9]+)?");
+
+ Semver current_version(SLIC3R_VERSION_FULL);
+ Semver best_pre(1,0,0,0);
+ Semver best_release(1, 0, 0, 0);
std::string best_pre_url;
std::string best_release_url;
+ const std::regex reg_num("([0-9]+)");
for (auto json_version : root) {
std::string tag = json_version.second.get<std::string>("tag_name");
- if (SLIC3R_VERSION_FULL == tag)
+ for (std::regex_iterator it = std::sregex_iterator(tag.begin(), tag.end(), reg_num); it != std::sregex_iterator(); ++it) {
+
+ }
+ Semver tag_version = get_version(tag, matcher);
+ if (current_version == tag_version)
i_am_pre = json_version.second.get<bool>("prerelease");
if (json_version.second.get<bool>("prerelease")) {
- if (best_pre < tag) {
- best_pre = tag;
+ if (best_pre < tag_version) {
+ best_pre = tag_version;
best_pre_url = json_version.second.get<std::string>("html_url");
}
} else {
- if (best_release < tag) {
- best_release = tag;
+ if (best_release < tag_version) {
+ best_release = tag_version;
best_release_url = json_version.second.get<std::string>("html_url");
}
}
}
- if ((i_am_pre ? best_pre : best_release) <= SLIC3R_VERSION_FULL)
+
+ //if release is more recent than beta, use release anyway
+ if (best_pre < best_release) {
+ best_pre = best_release;
+ best_pre_url = best_release_url;
+ }
+ //if we're the most recent, don't do anything
+ if ((i_am_pre ? best_pre : best_release) <= current_version)
return;
BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, i_am_pre? best_pre:best_release);
wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
- evt->SetString(i_am_pre ? best_pre : best_release);
+ evt->SetString((i_am_pre ? best_pre : best_release).to_string());
GUI::wxGetApp().QueueEvent(evt);
}
@@ -458,8 +487,8 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors)
// Download a fresh bundle
BOOST_LOG_TRIVIAL(info) << "Downloading new bundle for vendor: " << vendor.name;
- const auto bundle_url = format("%1%/%2%.ini", vendor.config_update_url, recommended.to_string());
- const auto bundle_path = cache_path / (vendor.id + ".ini");
+ const std::string bundle_url = format("%1%/%2%.ini", vendor.config_update_url, recommended.to_string());
+ const fs::path bundle_path = cache_path / (vendor.id + ".ini");
if (! get_file(bundle_url, bundle_path)) { continue; }
if (cancel) { return; }
}