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

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/admesh/stl.h2
-rw-r--r--src/libnest2d/include/libnest2d/placers/nfpplacer.hpp16
-rw-r--r--src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp11
-rw-r--r--src/libnest2d/include/libnest2d/selections/filler.hpp9
-rw-r--r--src/libnest2d/include/libnest2d/selections/firstfit.hpp13
-rw-r--r--src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp16
-rw-r--r--src/libslic3r/Arrange.cpp25
-rw-r--r--src/libslic3r/Config.hpp30
-rw-r--r--src/libslic3r/ExtrusionEntity.cpp138
-rw-r--r--src/libslic3r/ExtrusionEntity.hpp111
-rw-r--r--src/libslic3r/ExtrusionEntityCollection.cpp114
-rw-r--r--src/libslic3r/ExtrusionEntityCollection.hpp14
-rw-r--r--src/libslic3r/Fill/Fill.cpp581
-rw-r--r--src/libslic3r/Fill/FillBase.cpp20
-rw-r--r--src/libslic3r/Fill/FillBase.hpp1
-rw-r--r--src/libslic3r/Flow.hpp2
-rw-r--r--src/libslic3r/GCode.cpp70
-rw-r--r--src/libslic3r/GCode.hpp2
-rw-r--r--src/libslic3r/GCode/PreviewData.cpp36
-rw-r--r--src/libslic3r/GCode/PreviewData.hpp9
-rw-r--r--src/libslic3r/GCode/ToolOrdering.cpp36
-rw-r--r--src/libslic3r/GCode/ToolOrdering.hpp4
-rw-r--r--src/libslic3r/GCode/WipeTower.cpp167
-rw-r--r--src/libslic3r/GCode/WipeTower.hpp23
-rw-r--r--src/libslic3r/GCodeTimeEstimator.cpp178
-rw-r--r--src/libslic3r/GCodeTimeEstimator.hpp23
-rw-r--r--src/libslic3r/Layer.cpp28
-rw-r--r--src/libslic3r/Layer.hpp2
-rw-r--r--src/libslic3r/LayerRegion.cpp78
-rw-r--r--src/libslic3r/Model.hpp2
-rw-r--r--src/libslic3r/PerimeterGenerator.cpp491
-rw-r--r--src/libslic3r/PerimeterGenerator.hpp46
-rw-r--r--src/libslic3r/PlaceholderParser.cpp2
-rw-r--r--src/libslic3r/Print.cpp43
-rw-r--r--src/libslic3r/Print.hpp2
-rw-r--r--src/libslic3r/PrintConfig.cpp4
-rw-r--r--src/libslic3r/PrintConfig.hpp4
-rw-r--r--src/libslic3r/PrintObject.cpp111
-rw-r--r--src/libslic3r/PrintRegion.cpp40
-rw-r--r--src/libslic3r/SLA/SLAAutoSupports.hpp2
-rw-r--r--src/libslic3r/Surface.cpp58
-rw-r--r--src/libslic3r/Surface.hpp27
-rw-r--r--src/libslic3r/SurfaceCollection.hpp1
-rw-r--r--src/slic3r/Config/Snapshot.cpp8
-rw-r--r--src/slic3r/GUI/3DScene.cpp6
-rw-r--r--src/slic3r/GUI/BedShapeDialog.cpp2
-rw-r--r--src/slic3r/GUI/BitmapCache.cpp12
-rw-r--r--src/slic3r/GUI/BitmapCache.hpp4
-rw-r--r--src/slic3r/GUI/ConfigManipulation.cpp3
-rw-r--r--src/slic3r/GUI/Field.cpp23
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp58
-rw-r--r--src/slic3r/GUI/GLCanvas3D.hpp13
-rw-r--r--src/slic3r/GUI/GLCanvas3DManager.cpp2
-rw-r--r--src/slic3r/GUI/GLTexture.cpp6
-rw-r--r--src/slic3r/GUI/GLToolbar.cpp45
-rw-r--r--src/slic3r/GUI/GLToolbar.hpp14
-rw-r--r--src/slic3r/GUI/GUI.cpp2
-rw-r--r--src/slic3r/GUI/GUI_App.cpp16
-rw-r--r--src/slic3r/GUI/GUI_ObjectList.cpp133
-rw-r--r--src/slic3r/GUI/GUI_ObjectList.hpp6
-rw-r--r--src/slic3r/GUI/GUI_ObjectManipulation.cpp2
-rw-r--r--src/slic3r/GUI/GUI_ObjectSettings.cpp4
-rw-r--r--src/slic3r/GUI/GUI_ObjectSettings.hpp2
-rw-r--r--src/slic3r/GUI/GUI_Preview.cpp26
-rw-r--r--src/slic3r/GUI/GUI_Preview.hpp2
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoBase.hpp1
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp12
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp4
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoScale.cpp1
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp22
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp32
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmosManager.cpp541
-rw-r--r--src/slic3r/GUI/Gizmos/GLGizmosManager.hpp34
-rw-r--r--src/slic3r/GUI/MainFrame.hpp5
-rw-r--r--src/slic3r/GUI/OptionsGroup.cpp7
-rw-r--r--src/slic3r/GUI/Plater.cpp116
-rw-r--r--src/slic3r/GUI/Plater.hpp6
-rw-r--r--src/slic3r/GUI/PresetBundle.cpp14
-rw-r--r--src/slic3r/GUI/PresetHints.cpp4
-rw-r--r--src/slic3r/GUI/PrintHostDialogs.cpp6
-rw-r--r--src/slic3r/GUI/PrintHostDialogs.hpp1
-rw-r--r--src/slic3r/GUI/Selection.cpp25
-rw-r--r--src/slic3r/GUI/Tab.cpp337
-rw-r--r--src/slic3r/GUI/Tab.hpp1
-rw-r--r--src/slic3r/GUI/UpdateDialogs.cpp6
-rw-r--r--src/slic3r/GUI/UpdateDialogs.hpp2
-rw-r--r--src/slic3r/GUI/WipeTowerDialog.cpp58
-rw-r--r--src/slic3r/GUI/WipeTowerDialog.hpp5
-rw-r--r--src/slic3r/GUI/wxExtensions.cpp67
-rw-r--r--src/slic3r/GUI/wxExtensions.hpp16
-rw-r--r--src/slic3r/Utils/UndoRedo.cpp2
-rw-r--r--xs/xsp/Filler.xsp7
92 files changed, 2031 insertions, 2282 deletions
diff --git a/src/admesh/stl.h b/src/admesh/stl.h
index 9b1146f8d..117090dd8 100644
--- a/src/admesh/stl.h
+++ b/src/admesh/stl.h
@@ -247,7 +247,7 @@ extern void its_transform(indexed_triangle_set &its, T *trafo3x4)
template<typename T>
inline void its_transform(indexed_triangle_set &its, const Eigen::Transform<T, 3, Eigen::Affine, Eigen::DontAlign>& t)
{
- const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> r = t.matrix().template block<3, 3>(0, 0);
+ //const Eigen::Matrix<double, 3, 3, Eigen::DontAlign> r = t.matrix().template block<3, 3>(0, 0);
for (stl_vertex &v : its.vertices)
v = (t * v.template cast<T>()).template cast<float>().eval();
}
diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp
index 4ef1fe71d..1a341d691 100644
--- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp
+++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp
@@ -546,7 +546,12 @@ public:
inline explicit _NofitPolyPlacer(const BinType& bin):
Base(bin),
- norm_(std::sqrt(sl::area(bin))) {}
+ norm_(std::sqrt(sl::area(bin)))
+ {
+ // In order to not have items out of bin, it will be shrinked by an
+ // very little empiric offset value.
+ // sl::offset(bin_, 1e-5 * norm_);
+ }
_NofitPolyPlacer(const _NofitPolyPlacer&) = default;
_NofitPolyPlacer& operator=(const _NofitPolyPlacer&) = default;
@@ -1179,7 +1184,14 @@ private:
}
void setInitialPosition(Item& item) {
- Box&& bb = item.boundingBox();
+ auto sh = item.rawShape();
+ sl::translate(sh, item.translation());
+ sl::rotate(sh, item.rotation());
+
+ Box bb = sl::boundingBox(sh);
+ bb.minCorner() += item.translation();
+ bb.maxCorner() += item.translation();
+
Vertex ci, cb;
auto bbin = sl::boundingBox(bin_);
diff --git a/src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp b/src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp
index f904210aa..30ee7b627 100644
--- a/src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp
+++ b/src/libnest2d/include/libnest2d/selections/djd_heuristic.hpp
@@ -550,16 +550,7 @@ public:
return ret;
};
- // Safety test: try to pack each item into an empty bin. If it fails
- // then it should be removed from the not_packed list
- { auto it = store_.begin();
- while (it != store_.end() && !this->stopcond_()) {
- Placer p(bin); p.configure(pconfig);
- if(!p.pack(*it, rem(it, store_))) {
- it = store_.erase(it);
- } else it++;
- }
- }
+ this->template remove_unpackable_items<Placer>(store_, bin, pconfig);
int acounter = int(store_.size());
std::atomic_flag flg = ATOMIC_FLAG_INIT;
diff --git a/src/libnest2d/include/libnest2d/selections/filler.hpp b/src/libnest2d/include/libnest2d/selections/filler.hpp
index 19c44bfaa..3b6527d3e 100644
--- a/src/libnest2d/include/libnest2d/selections/filler.hpp
+++ b/src/libnest2d/include/libnest2d/selections/filler.hpp
@@ -30,7 +30,8 @@ public:
TBin&& bin,
PConfig&& pconfig = PConfig())
{
-
+ using Placer = PlacementStrategyLike<TPlacer>;
+
store_.clear();
auto total = last-first;
store_.reserve(total);
@@ -57,10 +58,12 @@ public:
auto sortfunc = [](Item& i1, Item& i2) {
return i1.area() > i2.area();
};
-
+
+ this->template remove_unpackable_items<Placer>(store_, bin, pconfig);
+
std::sort(store_.begin(), store_.end(), sortfunc);
- PlacementStrategyLike<TPlacer> placer(bin);
+ Placer placer(bin);
placer.configure(pconfig);
auto it = store_.begin();
diff --git a/src/libnest2d/include/libnest2d/selections/firstfit.hpp b/src/libnest2d/include/libnest2d/selections/firstfit.hpp
index 5585e565d..373e8b618 100644
--- a/src/libnest2d/include/libnest2d/selections/firstfit.hpp
+++ b/src/libnest2d/include/libnest2d/selections/firstfit.hpp
@@ -77,17 +77,8 @@ public:
};
auto& cancelled = this->stopcond_;
-
- // Safety test: try to pack each item into an empty bin. If it fails
- // then it should be removed from the list
- { auto it = store_.begin();
- while (it != store_.end() && !cancelled()) {
- Placer p(bin); p.configure(pconfig);
- if(!p.pack(*it)) {
- it = store_.erase(it);
- } else it++;
- }
- }
+
+ this->template remove_unpackable_items<Placer>(store_, bin, pconfig);
auto it = store_.begin();
diff --git a/src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp b/src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp
index 9ae92fe29..4bb2e72af 100644
--- a/src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp
+++ b/src/libnest2d/include/libnest2d/selections/selection_boilerplate.hpp
@@ -25,6 +25,22 @@ public:
inline void clear() { packed_bins_.clear(); }
protected:
+
+ template<class Placer, class Container, class Bin, class PCfg>
+ void remove_unpackable_items(Container &c, const Bin &bin, const PCfg& pcfg)
+ {
+ // Safety test: try to pack each item into an empty bin. If it fails
+ // then it should be removed from the list
+ auto it = c.begin();
+ while (it != c.end() && !stopcond_()) {
+ Placer p{bin};
+ p.configure(pcfg);
+ const Item& itm = *it;
+ Item cpy{itm};
+ if (!p.pack(cpy)) it = c.erase(it);
+ else it++;
+ }
+ }
PackGroup packed_bins_;
ProgressFunction progress_ = [](unsigned){};
diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp
index 34e07302a..52168c929 100644
--- a/src/libslic3r/Arrange.cpp
+++ b/src/libslic3r/Arrange.cpp
@@ -350,6 +350,12 @@ public:
m_pck.configure(m_pconf);
}
+ AutoArranger(const TBin & bin,
+ std::function<void(unsigned)> progressind,
+ std::function<bool(void)> stopcond)
+ : AutoArranger{bin, 0 /* no min distance */, progressind, stopcond}
+ {}
+
template<class It> inline void operator()(It from, It to) {
m_rtree.clear();
m_item_count += size_t(to - from);
@@ -553,13 +559,21 @@ BedShapeHint &BedShapeHint::operator=(const BedShapeHint &cpy)
return *this;
}
+template<class Bin> void remove_large_items(std::vector<Item> &items, Bin &&bin)
+{
+ auto it = items.begin();
+ while (it != items.end())
+ sl::isInside(it->transformedShape(), bin) ?
+ ++it : it = items.erase(it);
+}
+
template<class BinT> // Arrange for arbitrary bin type
void _arrange(
std::vector<Item> & shapes,
std::vector<Item> & excludes,
const BinT & bin,
coord_t minobjd,
- std::function<void(unsigned)> prind,
+ std::function<void(unsigned)> progressfn,
std::function<bool()> stopfn)
{
// Integer ceiling the min distance from the bed perimeters
@@ -569,16 +583,13 @@ void _arrange(
auto corrected_bin = bin;
sl::offset(corrected_bin, md);
- AutoArranger<BinT> arranger{corrected_bin, 0, prind, stopfn};
+ AutoArranger<BinT> arranger{corrected_bin, progressfn, stopfn};
auto infl = coord_t(std::ceil(minobjd / 2.0));
for (Item& itm : shapes) itm.inflate(infl);
for (Item& itm : excludes) itm.inflate(infl);
- auto it = excludes.begin();
- while (it != excludes.end())
- sl::isInside(it->transformedShape(), corrected_bin) ?
- ++it : it = excludes.erase(it);
+ remove_large_items(excludes, corrected_bin);
// If there is something on the plate
if (!excludes.empty()) arranger.preload(excludes);
@@ -674,7 +685,7 @@ void arrange(ArrangePolygons & arrangables,
_arrange(items, fixeditems, Box::infinite(), min_obj_dist, pri, cfn);
break;
}
- };
+ }
for(size_t i = 0; i < items.size(); ++i) {
clppr::IntPoint tr = items[i].translation();
diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp
index ff5563226..c349ad3e1 100644
--- a/src/libslic3r/Config.hpp
+++ b/src/libslic3r/Config.hpp
@@ -117,9 +117,9 @@ public:
virtual ConfigOption* clone() const = 0;
// Set a value from a ConfigOption. The two options should be compatible.
virtual void set(const ConfigOption *option) = 0;
- virtual int getInt() const { throw std::runtime_error("Calling ConfigOption::getInt on a non-int ConfigOption"); return 0; }
- virtual double getFloat() const { throw std::runtime_error("Calling ConfigOption::getFloat on a non-float ConfigOption"); return 0; }
- virtual bool getBool() const { throw std::runtime_error("Calling ConfigOption::getBool on a non-boolean ConfigOption"); return 0; }
+ virtual int getInt() const { throw std::runtime_error("Calling ConfigOption::getInt on a non-int ConfigOption"); }
+ virtual double getFloat() const { throw std::runtime_error("Calling ConfigOption::getFloat on a non-float ConfigOption"); }
+ virtual bool getBool() const { throw std::runtime_error("Calling ConfigOption::getBool on a non-boolean ConfigOption"); }
virtual void setInt(int /* val */) { throw std::runtime_error("Calling ConfigOption::setInt on a non-int ConfigOption"); }
virtual bool operator==(const ConfigOption &rhs) const = 0;
bool operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); }
@@ -204,6 +204,12 @@ public:
// Is the value nil? That should only be possible if this->nullable().
virtual bool is_nil(size_t idx) const = 0;
+ // We just overloaded and hid two base class virtual methods.
+ // Let's show it was intentional (warnings).
+ using ConfigOption::set;
+ using ConfigOption::is_nil;
+
+
protected:
// Used to verify type compatibility when assigning to / from a scalar ConfigOption.
ConfigOptionType scalar_type() const { return static_cast<ConfigOptionType>(this->type() - coVectorType); }
@@ -544,7 +550,7 @@ public:
static ConfigOptionType static_type() { return coInt; }
ConfigOptionType type() const override { return static_type(); }
int getInt() const override { return this->value; }
- void setInt(int val) { this->value = val; }
+ void setInt(int val) override { this->value = val; }
ConfigOption* clone() const override { return new ConfigOptionInt(*this); }
bool operator==(const ConfigOptionInt &rhs) const { return this->value == rhs.value; }
@@ -702,7 +708,7 @@ public:
ConfigOption* clone() const override { return new ConfigOptionStrings(*this); }
ConfigOptionStrings& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionStrings &rhs) const { return this->values == rhs.values; }
- bool is_nil(size_t idx) const override { return false; }
+ bool is_nil(size_t) const override { return false; }
std::string serialize() const override
{
@@ -917,7 +923,7 @@ public:
ConfigOption* clone() const override { return new ConfigOptionPoints(*this); }
ConfigOptionPoints& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionPoints &rhs) const { return this->values == rhs.values; }
- bool is_nil(size_t idx) const override { return false; }
+ bool is_nil(size_t) const override { return false; }
std::string serialize() const override
{
@@ -1502,7 +1508,7 @@ protected:
// Both opt_key and value may be modified by handle_legacy().
// If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by handle_legacy().
// handle_legacy() is called internally by set_deserialize().
- virtual void handle_legacy(t_config_option_key &opt_key, std::string &value) const {}
+ virtual void handle_legacy(t_config_option_key &/*opt_key*/, std::string &/*value*/) const {}
public:
// Non-virtual methods:
@@ -1576,7 +1582,7 @@ public:
DynamicConfig() {}
DynamicConfig(const DynamicConfig& other) { *this = other; }
DynamicConfig(DynamicConfig&& other) : options(std::move(other.options)) { other.options.clear(); }
- virtual ~DynamicConfig() { clear(); }
+ virtual ~DynamicConfig() override { clear(); }
// Copy a content of one DynamicConfig to another DynamicConfig.
// If rhs.def() is not null, then it has to be equal to this->def().
@@ -1697,14 +1703,14 @@ public:
const std::string& opt_string(const t_config_option_key &opt_key, unsigned int idx) const { return const_cast<DynamicConfig*>(this)->opt_string(opt_key, idx); }
double& opt_float(const t_config_option_key &opt_key) { return this->option<ConfigOptionFloat>(opt_key)->value; }
- const double opt_float(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionFloat*>(this->option(opt_key))->value; }
+ const double& opt_float(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionFloat*>(this->option(opt_key))->value; }
double& opt_float(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionFloats>(opt_key)->get_at(idx); }
- const double opt_float(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloats*>(this->option(opt_key))->get_at(idx); }
+ const double& opt_float(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionFloats*>(this->option(opt_key))->get_at(idx); }
int& opt_int(const t_config_option_key &opt_key) { return this->option<ConfigOptionInt>(opt_key)->value; }
- const int opt_int(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; }
+ int opt_int(const t_config_option_key &opt_key) const { return dynamic_cast<const ConfigOptionInt*>(this->option(opt_key))->value; }
int& opt_int(const t_config_option_key &opt_key, unsigned int idx) { return this->option<ConfigOptionInts>(opt_key)->get_at(idx); }
- const int opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
+ int opt_int(const t_config_option_key &opt_key, unsigned int idx) const { return dynamic_cast<const ConfigOptionInts*>(this->option(opt_key))->get_at(idx); }
template<typename ENUM>
ENUM opt_enum(const t_config_option_key &opt_key) const { return (ENUM)dynamic_cast<const ConfigOptionEnumGeneric*>(this->option(opt_key))->value; }
diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp
index 92f0d3669..7f57b78af 100644
--- a/src/libslic3r/ExtrusionEntity.cpp
+++ b/src/libslic3r/ExtrusionEntity.cpp
@@ -8,46 +8,39 @@
#include <limits>
#include <sstream>
+#define L(s) (s)
+
namespace Slic3r {
-void
-ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
+void ExtrusionPath::intersect_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{
this->_inflate_collection(intersection_pl(this->polyline, collection), retval);
}
-void
-ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
+void ExtrusionPath::subtract_expolygons(const ExPolygonCollection &collection, ExtrusionEntityCollection* retval) const
{
this->_inflate_collection(diff_pl(this->polyline, collection), retval);
}
-void
-ExtrusionPath::clip_end(double distance)
+void ExtrusionPath::clip_end(double distance)
{
this->polyline.clip_end(distance);
}
-void
-ExtrusionPath::simplify(double tolerance)
+void ExtrusionPath::simplify(double tolerance)
{
this->polyline.simplify(tolerance);
}
-double
-ExtrusionPath::length() const
+double ExtrusionPath::length() const
{
return this->polyline.length();
}
-void
-ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const
+void ExtrusionPath::_inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const
{
- for (Polylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it) {
- ExtrusionPath* path = this->clone();
- path->polyline = *it;
- collection->entities.push_back(path);
- }
+ for (const Polyline &polyline : polylines)
+ collection->entities.emplace_back(new ExtrusionPath(polyline, *this));
}
void ExtrusionPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
@@ -65,36 +58,36 @@ void ExtrusionPath::polygons_covered_by_spacing(Polygons &out, const float scale
void ExtrusionMultiPath::reverse()
{
- for (ExtrusionPaths::iterator path = this->paths.begin(); path != this->paths.end(); ++path)
- path->reverse();
+ for (ExtrusionPath &path : this->paths)
+ path.reverse();
std::reverse(this->paths.begin(), this->paths.end());
}
double ExtrusionMultiPath::length() const
{
double len = 0;
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
- len += path->polyline.length();
+ for (const ExtrusionPath &path : this->paths)
+ len += path.polyline.length();
return len;
}
void ExtrusionMultiPath::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
- path->polygons_covered_by_width(out, scaled_epsilon);
+ for (const ExtrusionPath &path : this->paths)
+ path.polygons_covered_by_width(out, scaled_epsilon);
}
void ExtrusionMultiPath::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
{
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
- path->polygons_covered_by_spacing(out, scaled_epsilon);
+ for (const ExtrusionPath &path : this->paths)
+ path.polygons_covered_by_spacing(out, scaled_epsilon);
}
double ExtrusionMultiPath::min_mm3_per_mm() const
{
double min_mm3_per_mm = std::numeric_limits<double>::max();
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
- min_mm3_per_mm = std::min(min_mm3_per_mm, path->mm3_per_mm);
+ for (const ExtrusionPath &path : this->paths)
+ min_mm3_per_mm = std::min(min_mm3_per_mm, path.mm3_per_mm);
return min_mm3_per_mm;
}
@@ -119,52 +112,46 @@ Polyline ExtrusionMultiPath::as_polyline() const
return out;
}
-bool
-ExtrusionLoop::make_clockwise()
+bool ExtrusionLoop::make_clockwise()
{
bool was_ccw = this->polygon().is_counter_clockwise();
if (was_ccw) this->reverse();
return was_ccw;
}
-bool
-ExtrusionLoop::make_counter_clockwise()
+bool ExtrusionLoop::make_counter_clockwise()
{
bool was_cw = this->polygon().is_clockwise();
if (was_cw) this->reverse();
return was_cw;
}
-void
-ExtrusionLoop::reverse()
+void ExtrusionLoop::reverse()
{
- for (ExtrusionPaths::iterator path = this->paths.begin(); path != this->paths.end(); ++path)
- path->reverse();
+ for (ExtrusionPath &path : this->paths)
+ path.reverse();
std::reverse(this->paths.begin(), this->paths.end());
}
-Polygon
-ExtrusionLoop::polygon() const
+Polygon ExtrusionLoop::polygon() const
{
Polygon polygon;
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
+ for (const ExtrusionPath &path : this->paths) {
// for each polyline, append all points except the last one (because it coincides with the first one of the next polyline)
- polygon.points.insert(polygon.points.end(), path->polyline.points.begin(), path->polyline.points.end()-1);
+ polygon.points.insert(polygon.points.end(), path.polyline.points.begin(), path.polyline.points.end()-1);
}
return polygon;
}
-double
-ExtrusionLoop::length() const
+double ExtrusionLoop::length() const
{
double len = 0;
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
- len += path->polyline.length();
+ for (const ExtrusionPath &path : this->paths)
+ len += path.polyline.length();
return len;
}
-bool
-ExtrusionLoop::split_at_vertex(const Point &point)
+bool ExtrusionLoop::split_at_vertex(const Point &point)
{
for (ExtrusionPaths::iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
int idx = path->polyline.find_point(point);
@@ -218,18 +205,18 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang)
Point p_non_overhang;
size_t path_idx_non_overhang = 0;
double min_non_overhang = std::numeric_limits<double>::max();
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
- Point p_tmp = point.projection_onto(path->polyline);
+ for (const ExtrusionPath &path : this->paths) {
+ Point p_tmp = point.projection_onto(path.polyline);
double dist = (p_tmp - point).cast<double>().norm();
if (dist < min) {
p = p_tmp;
min = dist;
- path_idx = path - this->paths.begin();
+ path_idx = &path - &this->paths.front();
}
- if (prefer_non_overhang && ! is_bridge(path->role()) && dist < min_non_overhang) {
+ if (prefer_non_overhang && ! is_bridge(path.role()) && dist < min_non_overhang) {
p_non_overhang = p_tmp;
min_non_overhang = dist;
- path_idx_non_overhang = path - this->paths.begin();
+ path_idx_non_overhang = &path - &this->paths.front();
}
}
if (prefer_non_overhang && min_non_overhang != std::numeric_limits<double>::max()) {
@@ -265,8 +252,7 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang)
this->split_at_vertex(p);
}
-void
-ExtrusionLoop::clip_end(double distance, ExtrusionPaths* paths) const
+void ExtrusionLoop::clip_end(double distance, ExtrusionPaths* paths) const
{
*paths = this->paths;
@@ -283,15 +269,14 @@ ExtrusionLoop::clip_end(double distance, ExtrusionPaths* paths) const
}
}
-bool
-ExtrusionLoop::has_overhang_point(const Point &point) const
+bool ExtrusionLoop::has_overhang_point(const Point &point) const
{
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
- int pos = path->polyline.find_point(point);
+ for (const ExtrusionPath &path : this->paths) {
+ int pos = path.polyline.find_point(point);
if (pos != -1) {
// point belongs to this path
// we consider it overhang only if it's not an endpoint
- return (is_bridge(path->role()) && pos > 0 && pos != (int)(path->polyline.points.size())-1);
+ return (is_bridge(path.role()) && pos > 0 && pos != (int)(path.polyline.points.size())-1);
}
}
return false;
@@ -299,23 +284,46 @@ ExtrusionLoop::has_overhang_point(const Point &point) const
void ExtrusionLoop::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
- path->polygons_covered_by_width(out, scaled_epsilon);
+ for (const ExtrusionPath &path : this->paths)
+ path.polygons_covered_by_width(out, scaled_epsilon);
}
void ExtrusionLoop::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
{
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
- path->polygons_covered_by_spacing(out, scaled_epsilon);
+ for (const ExtrusionPath &path : this->paths)
+ path.polygons_covered_by_spacing(out, scaled_epsilon);
}
-double
-ExtrusionLoop::min_mm3_per_mm() const
+double ExtrusionLoop::min_mm3_per_mm() const
{
double min_mm3_per_mm = std::numeric_limits<double>::max();
- for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path)
- min_mm3_per_mm = std::min(min_mm3_per_mm, path->mm3_per_mm);
+ for (const ExtrusionPath &path : this->paths)
+ min_mm3_per_mm = std::min(min_mm3_per_mm, path.mm3_per_mm);
return min_mm3_per_mm;
}
+
+std::string ExtrusionEntity::role_to_string(ExtrusionRole role)
+{
+ switch (role) {
+ case erNone : return L("None");
+ case erPerimeter : return L("Perimeter");
+ case erExternalPerimeter : return L("External perimeter");
+ case erOverhangPerimeter : return L("Overhang perimeter");
+ case erInternalInfill : return L("Internal infill");
+ case erSolidInfill : return L("Solid infill");
+ case erTopSolidInfill : return L("Top solid infill");
+ case erBridgeInfill : return L("Bridge infill");
+ case erGapFill : return L("Gap fill");
+ case erSkirt : return L("Skirt");
+ case erSupportMaterial : return L("Support material");
+ case erSupportMaterialInterface : return L("Support material interface");
+ case erWipeTower : return L("Wipe tower");
+ case erCustom : return L("Custom");
+ case erMixed : return L("Mixed");
+ default : assert(false);
+ }
+ return "";
+}
+
}
diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp
index b32943b7d..ce52ae152 100644
--- a/src/libslic3r/ExtrusionEntity.hpp
+++ b/src/libslic3r/ExtrusionEntity.hpp
@@ -11,7 +11,7 @@ class ExPolygonCollection;
class ExtrusionEntityCollection;
class Extruder;
-/* Each ExtrusionRole value identifies a distinct set of { extruder, speed } */
+// Each ExtrusionRole value identifies a distinct set of { extruder, speed }
enum ExtrusionRole {
erNone,
erPerimeter,
@@ -29,9 +29,17 @@ enum ExtrusionRole {
erCustom,
// Extrusion role for a collection with multiple extrusion roles.
erMixed,
- erCount,
+ erCount
};
+// Special flags describing loop
+enum ExtrusionLoopRole {
+ elrDefault,
+ elrContourInternalPerimeter,
+ elrSkirt,
+};
+
+
inline bool is_perimeter(ExtrusionRole role)
{
return role == erPerimeter
@@ -59,13 +67,6 @@ inline bool is_bridge(ExtrusionRole role) {
|| role == erOverhangPerimeter;
}
-/* Special flags describing loop */
-enum ExtrusionLoopRole {
- elrDefault,
- elrContourInternalPerimeter,
- elrSkirt,
-};
-
class ExtrusionEntity
{
public:
@@ -74,7 +75,9 @@ public:
virtual bool is_loop() const { return false; }
virtual bool can_reverse() const { return true; }
virtual ExtrusionEntity* clone() const = 0;
- virtual ~ExtrusionEntity() {};
+ // Create a new object, initialize it with this object using the move semantics.
+ virtual ExtrusionEntity* clone_move() = 0;
+ virtual ~ExtrusionEntity() {}
virtual void reverse() = 0;
virtual Point first_point() const = 0;
virtual Point last_point() const = 0;
@@ -96,6 +99,8 @@ public:
virtual Polylines as_polylines() const { Polylines dst; this->collect_polylines(dst); return dst; }
virtual double length() const = 0;
virtual double total_volume() const = 0;
+
+ static std::string role_to_string(ExtrusionRole role);
};
typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;
@@ -108,26 +113,30 @@ public:
double mm3_per_mm;
// Width of the extrusion, used for visualization purposes.
float width;
- // Height of the extrusion, used for visualization purposed.
+ // Height of the extrusion, used for visualization purposes.
float height;
- // Feedrate of the extrusion, used for visualization purposed.
+ // Feedrate of the extrusion, used for visualization purposes.
float feedrate;
- // Id of the extruder, used for visualization purposed.
+ // Id of the extruder, used for visualization purposes.
unsigned int extruder_id;
- // Id of the color, used for visualization purposed in the color printing case.
+ // Id of the color, used for visualization purposes in the color printing case.
unsigned int cp_color_id;
- ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {};
- ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {};
+ ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {}
+ ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), feedrate(0.0f), extruder_id(0), cp_color_id(0), m_role(role) {}
ExtrusionPath(const ExtrusionPath &rhs) : polyline(rhs.polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {}
- ExtrusionPath(ExtrusionPath &&rhs) : polyline(std::move(rhs.polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {}
+ ExtrusionPath(const Polyline &polyline, const ExtrusionPath &rhs) : polyline(polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {}
+ ExtrusionPath(ExtrusionPath &&rhs) : polyline(std::move(rhs.polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {}
+ ExtrusionPath(Polyline &&polyline, const ExtrusionPath &rhs) : polyline(std::move(polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), m_role(rhs.m_role) {}
// ExtrusionPath(ExtrusionRole role, const Flow &flow) : m_role(role), mm3_per_mm(flow.mm3_per_mm()), width(flow.width), height(flow.height), feedrate(0.0f), extruder_id(0) {};
- ExtrusionPath& operator=(const ExtrusionPath &rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->cp_color_id = rhs.cp_color_id, this->polyline = rhs.polyline; return *this; }
- ExtrusionPath& operator=(ExtrusionPath &&rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->cp_color_id = rhs.cp_color_id, this->polyline = std::move(rhs.polyline); return *this; }
+ ExtrusionPath& operator=(const ExtrusionPath &rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate; this->extruder_id = rhs.extruder_id; this->cp_color_id = rhs.cp_color_id; this->polyline = rhs.polyline; return *this; }
+ ExtrusionPath& operator=(ExtrusionPath &&rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate; this->extruder_id = rhs.extruder_id; this->cp_color_id = rhs.cp_color_id; this->polyline = std::move(rhs.polyline); return *this; }
- ExtrusionPath* clone() const { return new ExtrusionPath (*this); }
- void reverse() { this->polyline.reverse(); }
+ ExtrusionEntity* clone() const override { return new ExtrusionPath(*this); }
+ // Create a new object, initialize it with this object using the move semantics.
+ ExtrusionEntity* clone_move() override { return new ExtrusionPath(std::move(*this)); }
+ void reverse() override { this->polyline.reverse(); }
Point first_point() const override { return this->polyline.points.front(); }
Point last_point() const override { return this->polyline.points.back(); }
size_t size() const { return this->polyline.size(); }
@@ -145,18 +154,18 @@ public:
ExtrusionRole role() const override { return m_role; }
// 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;
+ void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
// Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill.
- void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const;
+ void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override;
Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; }
Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; }
// Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
- double min_mm3_per_mm() const { return this->mm3_per_mm; }
- Polyline as_polyline() const { return this->polyline; }
+ double min_mm3_per_mm() const override { return this->mm3_per_mm; }
+ Polyline as_polyline() const override { return this->polyline; }
void collect_polylines(Polylines &dst) const override { if (! this->polyline.empty()) dst.emplace_back(this->polyline); }
double total_volume() const override { return mm3_per_mm * unscale<double>(length()); }
@@ -174,37 +183,39 @@ class ExtrusionMultiPath : public ExtrusionEntity
public:
ExtrusionPaths paths;
- ExtrusionMultiPath() {};
+ ExtrusionMultiPath() {}
ExtrusionMultiPath(const ExtrusionMultiPath &rhs) : paths(rhs.paths) {}
ExtrusionMultiPath(ExtrusionMultiPath &&rhs) : paths(std::move(rhs.paths)) {}
- ExtrusionMultiPath(const ExtrusionPaths &paths) : paths(paths) {};
+ ExtrusionMultiPath(const ExtrusionPaths &paths) : paths(paths) {}
ExtrusionMultiPath(const ExtrusionPath &path) { this->paths.push_back(path); }
ExtrusionMultiPath& operator=(const ExtrusionMultiPath &rhs) { this->paths = rhs.paths; return *this; }
ExtrusionMultiPath& operator=(ExtrusionMultiPath &&rhs) { this->paths = std::move(rhs.paths); return *this; }
- bool is_loop() const { return false; }
- bool can_reverse() const { return true; }
- ExtrusionMultiPath* clone() const { return new ExtrusionMultiPath(*this); }
- void reverse();
+ bool is_loop() const override { return false; }
+ bool can_reverse() const override { return true; }
+ ExtrusionEntity* clone() const override { return new ExtrusionMultiPath(*this); }
+ // Create a new object, initialize it with this object using the move semantics.
+ ExtrusionEntity* clone_move() override { return new ExtrusionMultiPath(std::move(*this)); }
+ void reverse() override;
Point first_point() const override { return this->paths.front().polyline.points.front(); }
Point last_point() const override { return this->paths.back().polyline.points.back(); }
double length() const override;
ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); }
// 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;
+ void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
// Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill.
- void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const;
+ void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override;
Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; }
Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; }
// Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
- double min_mm3_per_mm() const;
- Polyline as_polyline() const;
+ double min_mm3_per_mm() const override;
+ Polyline as_polyline() const override;
void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); }
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
};
@@ -215,19 +226,21 @@ class ExtrusionLoop : public ExtrusionEntity
public:
ExtrusionPaths paths;
- ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {};
- ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {};
- ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {};
+ ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {}
+ ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {}
+ ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {}
ExtrusionLoop(const ExtrusionPath &path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
- { this->paths.push_back(path); };
+ { this->paths.push_back(path); }
ExtrusionLoop(const ExtrusionPath &&path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
- { this->paths.emplace_back(std::move(path)); };
- bool is_loop() const { return true; }
- bool can_reverse() const { return false; }
- ExtrusionLoop* clone() const { return new ExtrusionLoop (*this); }
+ { this->paths.emplace_back(std::move(path)); }
+ bool is_loop() const override{ return true; }
+ bool can_reverse() const override { return false; }
+ ExtrusionEntity* clone() const override{ return new ExtrusionLoop (*this); }
+ // Create a new object, initialize it with this object using the move semantics.
+ ExtrusionEntity* clone_move() override { return new ExtrusionLoop(std::move(*this)); }
bool make_clockwise();
bool make_counter_clockwise();
- void reverse();
+ void reverse() override;
Point first_point() const override { return this->paths.front().polyline.points.front(); }
Point last_point() const override { assert(first_point() == this->paths.back().polyline.points.back()); return first_point(); }
Polygon polygon() const;
@@ -242,21 +255,23 @@ public:
ExtrusionLoopRole loop_role() const { return m_loop_role; }
// 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;
+ void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
// Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill.
- void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const;
+ void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override;
Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; }
Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; }
// Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
- double min_mm3_per_mm() const;
- Polyline as_polyline() const { return this->polygon().split_at_first_point(); }
+ double min_mm3_per_mm() const override;
+ Polyline as_polyline() const override { return this->polygon().split_at_first_point(); }
void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); }
double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
+ //static inline std::string role_to_string(ExtrusionLoopRole role);
+
private:
ExtrusionLoopRole m_loop_role;
};
diff --git a/src/libslic3r/ExtrusionEntityCollection.cpp b/src/libslic3r/ExtrusionEntityCollection.cpp
index 7a086bcbf..9ae116c47 100644
--- a/src/libslic3r/ExtrusionEntityCollection.cpp
+++ b/src/libslic3r/ExtrusionEntityCollection.cpp
@@ -21,8 +21,7 @@ ExtrusionEntityCollection& ExtrusionEntityCollection::operator= (const Extrusion
return *this;
}
-void
-ExtrusionEntityCollection::swap(ExtrusionEntityCollection &c)
+void ExtrusionEntityCollection::swap(ExtrusionEntityCollection &c)
{
std::swap(this->entities, c.entities);
std::swap(this->orig_indices, c.orig_indices);
@@ -39,15 +38,14 @@ void ExtrusionEntityCollection::clear()
ExtrusionEntityCollection::operator ExtrusionPaths() const
{
ExtrusionPaths paths;
- for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) {
- if (const ExtrusionPath* path = dynamic_cast<const ExtrusionPath*>(*it))
+ for (const ExtrusionEntity *ptr : this->entities) {
+ if (const ExtrusionPath *path = dynamic_cast<const ExtrusionPath*>(ptr))
paths.push_back(*path);
}
return paths;
}
-ExtrusionEntityCollection*
-ExtrusionEntityCollection::clone() const
+ExtrusionEntity* ExtrusionEntityCollection::clone() const
{
ExtrusionEntityCollection* coll = new ExtrusionEntityCollection(*this);
for (size_t i = 0; i < coll->entities.size(); ++i)
@@ -55,41 +53,36 @@ ExtrusionEntityCollection::clone() const
return coll;
}
-void
-ExtrusionEntityCollection::reverse()
+void ExtrusionEntityCollection::reverse()
{
- for (ExtrusionEntitiesPtr::iterator it = this->entities.begin(); it != this->entities.end(); ++it) {
+ for (ExtrusionEntity *ptr : this->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 (!(*it)->is_loop()) (*it)->reverse();
- }
+ if (! ptr->is_loop())
+ ptr->reverse();
std::reverse(this->entities.begin(), this->entities.end());
}
-void
-ExtrusionEntityCollection::replace(size_t i, const ExtrusionEntity &entity)
+void ExtrusionEntityCollection::replace(size_t i, const ExtrusionEntity &entity)
{
delete this->entities[i];
this->entities[i] = entity.clone();
}
-void
-ExtrusionEntityCollection::remove(size_t i)
+void ExtrusionEntityCollection::remove(size_t i)
{
delete this->entities[i];
this->entities.erase(this->entities.begin() + i);
}
-ExtrusionEntityCollection
-ExtrusionEntityCollection::chained_path(bool no_reverse, ExtrusionRole role) const
+ExtrusionEntityCollection ExtrusionEntityCollection::chained_path(bool no_reverse, ExtrusionRole role) const
{
ExtrusionEntityCollection coll;
this->chained_path(&coll, no_reverse, role);
return coll;
}
-void
-ExtrusionEntityCollection::chained_path(ExtrusionEntityCollection* retval, bool no_reverse, ExtrusionRole role, std::vector<size_t>* orig_indices) const
+void ExtrusionEntityCollection::chained_path(ExtrusionEntityCollection* retval, bool no_reverse, ExtrusionRole role, std::vector<size_t>* orig_indices) const
{
if (this->entities.empty()) return;
this->chained_path_from(this->entities.front()->first_point(), retval, no_reverse, role, orig_indices);
@@ -108,6 +101,7 @@ void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEnt
*retval = *this;
return;
}
+
retval->entities.reserve(this->entities.size());
retval->orig_indices.reserve(this->entities.size());
@@ -115,10 +109,10 @@ void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEnt
std::map<ExtrusionEntity*,size_t> indices_map;
ExtrusionEntitiesPtr my_paths;
- for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) {
+ for (ExtrusionEntity * const &entity_src : this->entities) {
if (role != erMixed) {
// The caller wants only paths with a specific extrusion role.
- auto role2 = (*it)->role();
+ auto role2 = entity_src->role();
if (role != role2) {
// This extrusion entity does not match the role asked.
assert(role2 != erMixed);
@@ -126,32 +120,30 @@ void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEnt
}
}
- ExtrusionEntity* entity = (*it)->clone();
+ ExtrusionEntity *entity = entity_src->clone();
my_paths.push_back(entity);
- if (orig_indices != NULL) indices_map[entity] = it - this->entities.begin();
+ if (orig_indices != nullptr)
+ indices_map[entity] = &entity_src - &this->entities.front();
}
Points endpoints;
- for (ExtrusionEntitiesPtr::iterator it = my_paths.begin(); it != my_paths.end(); ++it) {
- endpoints.push_back((*it)->first_point());
- if (no_reverse || !(*it)->can_reverse()) {
- endpoints.push_back((*it)->first_point());
- } else {
- endpoints.push_back((*it)->last_point());
- }
+ for (const ExtrusionEntity *entity : my_paths) {
+ endpoints.push_back(entity->first_point());
+ endpoints.push_back((no_reverse || ! entity->can_reverse()) ?
+ entity->first_point() : entity->last_point());
}
- while (!my_paths.empty()) {
+ while (! my_paths.empty()) {
// find nearest point
int start_index = start_near.nearest_point_index(endpoints);
int path_index = start_index/2;
ExtrusionEntity* entity = my_paths.at(path_index);
// never reverse loops, since it's pointless for chained path and callers might depend on orientation
- if (start_index % 2 && !no_reverse && entity->can_reverse()) {
+ if (start_index % 2 && !no_reverse && entity->can_reverse())
entity->reverse();
- }
retval->entities.push_back(my_paths.at(path_index));
- if (orig_indices != NULL) orig_indices->push_back(indices_map[entity]);
+ if (orig_indices != nullptr)
+ orig_indices->push_back(indices_map[entity]);
my_paths.erase(my_paths.begin() + path_index);
endpoints.erase(endpoints.begin() + 2*path_index, endpoints.begin() + 2*path_index + 2);
start_near = retval->entities.back()->last_point();
@@ -160,60 +152,50 @@ void ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEnt
void ExtrusionEntityCollection::polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const
{
- for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it)
- (*it)->polygons_covered_by_width(out, scaled_epsilon);
+ for (const ExtrusionEntity *entity : this->entities)
+ entity->polygons_covered_by_width(out, scaled_epsilon);
}
void ExtrusionEntityCollection::polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const
{
- for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it)
- (*it)->polygons_covered_by_spacing(out, scaled_epsilon);
+ for (const ExtrusionEntity *entity : this->entities)
+ entity->polygons_covered_by_spacing(out, scaled_epsilon);
}
-/* Recursively count paths and loops contained in this collection */
-size_t
-ExtrusionEntityCollection::items_count() const
+// Recursively count paths and loops contained in this collection.
+size_t ExtrusionEntityCollection::items_count() const
{
size_t count = 0;
- for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) {
- if ((*it)->is_collection()) {
- ExtrusionEntityCollection* collection = dynamic_cast<ExtrusionEntityCollection*>(*it);
- count += collection->items_count();
- } else {
- ++count;
- }
- }
+ for (const ExtrusionEntity *entity : this->entities)
+ if (entity->is_collection())
+ count += static_cast<const ExtrusionEntityCollection*>(entity)->items_count();
+ else
+ ++ count;
return count;
}
-/* Returns a single vector of pointers to all non-collection items contained in this one */
-void
-ExtrusionEntityCollection::flatten(ExtrusionEntityCollection* retval) const
+// Returns a single vector of pointers to all non-collection items contained in this one.
+void ExtrusionEntityCollection::flatten(ExtrusionEntityCollection* retval) const
{
- for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) {
- if ((*it)->is_collection()) {
- ExtrusionEntityCollection* collection = dynamic_cast<ExtrusionEntityCollection*>(*it);
- retval->append(collection->flatten().entities);
- } else {
- retval->append(**it);
- }
- }
+ for (const ExtrusionEntity *entity : this->entities)
+ if (entity->is_collection())
+ retval->append(static_cast<const ExtrusionEntityCollection*>(entity)->flatten().entities);
+ else
+ retval->append(*entity);
}
-ExtrusionEntityCollection
-ExtrusionEntityCollection::flatten() const
+ExtrusionEntityCollection ExtrusionEntityCollection::flatten() const
{
ExtrusionEntityCollection coll;
this->flatten(&coll);
return coll;
}
-double
-ExtrusionEntityCollection::min_mm3_per_mm() const
+double ExtrusionEntityCollection::min_mm3_per_mm() const
{
double min_mm3_per_mm = std::numeric_limits<double>::max();
- for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it)
- min_mm3_per_mm = std::min(min_mm3_per_mm, (*it)->min_mm3_per_mm());
+ for (const ExtrusionEntity *entity : this->entities)
+ min_mm3_per_mm = std::min(min_mm3_per_mm, entity->min_mm3_per_mm());
return min_mm3_per_mm;
}
diff --git a/src/libslic3r/ExtrusionEntityCollection.hpp b/src/libslic3r/ExtrusionEntityCollection.hpp
index 230c04160..4fe964ee1 100644
--- a/src/libslic3r/ExtrusionEntityCollection.hpp
+++ b/src/libslic3r/ExtrusionEntityCollection.hpp
@@ -9,7 +9,10 @@ namespace Slic3r {
class ExtrusionEntityCollection : public ExtrusionEntity
{
public:
- ExtrusionEntityCollection* clone() const;
+ ExtrusionEntity* clone() const override;
+ // Create a new object, initialize it with this object using the move semantics.
+ ExtrusionEntity* clone_move() override { return new ExtrusionEntityCollection(std::move(*this)); }
+
ExtrusionEntitiesPtr entities; // we own these entities
std::vector<size_t> orig_indices; // handy for XS
bool no_sort;
@@ -36,11 +39,12 @@ public:
bool empty() const { return this->entities.empty(); };
void clear();
void swap (ExtrusionEntityCollection &c);
- void append(const ExtrusionEntity &entity) { this->entities.push_back(entity.clone()); }
- void append(const ExtrusionEntitiesPtr &entities) {
+ 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 ExtrusionEntitiesPtr &entities) {
this->entities.reserve(this->entities.size() + entities.size());
- for (ExtrusionEntitiesPtr::const_iterator ptr = entities.begin(); ptr != entities.end(); ++ptr)
- this->entities.push_back((*ptr)->clone());
+ for (const ExtrusionEntity *ptr : entities)
+ this->entities.emplace_back(ptr->clone());
}
void append(ExtrusionEntitiesPtr &&src) {
if (entities.empty())
diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp
index fbdef29b9..ad308adab 100644
--- a/src/libslic3r/Fill/Fill.cpp
+++ b/src/libslic3r/Fill/Fill.cpp
@@ -13,103 +13,203 @@
namespace Slic3r {
-struct SurfaceGroupAttrib
+struct SurfaceFillParams
{
- SurfaceGroupAttrib() : is_solid(false), flow_width(0.f), pattern(-1) {}
- bool operator==(const SurfaceGroupAttrib &other) const
- { return is_solid == other.is_solid && flow_width == other.flow_width && pattern == other.pattern; }
- bool is_solid;
- float flow_width;
- // pattern is of type InfillPattern, -1 for an unset pattern.
- int pattern;
+ SurfaceFillParams() : flow(0.f, 0.f, 0.f, false) { memset(this, 0, sizeof(*this)); }
+ // Zero based extruder ID.
+ unsigned int extruder;
+ // Infill pattern, adjusted for the density etc.
+ InfillPattern pattern;
+
+ // FillBase
+ // in unscaled coordinates
+ coordf_t spacing;
+ // infill / perimeter overlap, in unscaled coordinates
+ coordf_t overlap;
+ // Angle as provided by the region config, in radians.
+ float angle;
+ // Non-negative for a bridge.
+ float bridge_angle;
+
+ // FillParams
+ float density;
+ // Don't connect the fill lines around the inner perimeter.
+ bool dont_connect;
+ // Don't adjust spacing to fill the space evenly.
+ bool dont_adjust;
+
+ // width, height of extrusion, nozzle diameter, is bridge
+ // For the output, for fill generator.
+ Flow flow;
+
+ // For the output
+ ExtrusionRole extrusion_role;
+
+ // Various print settings?
+
+ // Index of this entry in a linear vector.
+ size_t idx;
+
+
+ bool operator<(const SurfaceFillParams &rhs) const {
+#define RETURN_COMPARE_NON_EQUAL(KEY) if (this->KEY < rhs.KEY) return true; if (this->KEY > rhs.KEY) return false;
+#define RETURN_COMPARE_NON_EQUAL_TYPED(TYPE, KEY) if (TYPE(this->KEY) < TYPE(rhs.KEY)) return true; if (TYPE(this->KEY) > TYPE(rhs.KEY)) return false;
+
+ // Sort first by decreasing bridging angle, so that the bridges are processed with priority when trimming one layer by the other.
+ if (this->bridge_angle > rhs.bridge_angle) return true;
+ if (this->bridge_angle < rhs.bridge_angle) return false;
+
+ RETURN_COMPARE_NON_EQUAL(extruder);
+ RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, pattern);
+ RETURN_COMPARE_NON_EQUAL(spacing);
+ RETURN_COMPARE_NON_EQUAL(overlap);
+ RETURN_COMPARE_NON_EQUAL(angle);
+ RETURN_COMPARE_NON_EQUAL(density);
+ RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_connect);
+ RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust);
+ RETURN_COMPARE_NON_EQUAL(flow.width);
+ RETURN_COMPARE_NON_EQUAL(flow.height);
+ RETURN_COMPARE_NON_EQUAL(flow.nozzle_diameter);
+ RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, flow.bridge);
+ RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, extrusion_role);
+ return false;
+ }
+
+ bool operator==(const SurfaceFillParams &rhs) const {
+ return this->extruder == rhs.extruder &&
+ this->pattern == rhs.pattern &&
+ this->pattern == rhs.pattern &&
+ this->spacing == rhs.spacing &&
+ this->overlap == rhs.overlap &&
+ this->angle == rhs.angle &&
+ this->density == rhs.density &&
+ this->dont_connect == rhs.dont_connect &&
+ this->dont_adjust == rhs.dont_adjust &&
+ this->flow == rhs.flow &&
+ this->extrusion_role == rhs.extrusion_role;
+ }
};
-// Generate infills for Slic3r::Layer::Region.
-// The Slic3r::Layer::Region at this point of time may contain
-// surfaces of various types (internal/bridge/top/bottom/solid).
-// The infills are generated on the groups of surfaces with a compatible type.
-// Returns an array of Slic3r::ExtrusionPath::Collection objects containing the infills generaed now
-// and the thin fills generated by generate_perimeters().
-void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
-{
-// Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id;
-
- double fill_density = layerm.region()->config().fill_density;
- Flow infill_flow = layerm.flow(frInfill);
- Flow solid_infill_flow = layerm.flow(frSolidInfill);
- Flow top_solid_infill_flow = layerm.flow(frTopSolidInfill);
-
- Surfaces surfaces;
-
- // merge adjacent surfaces
- // in case of bridge surfaces, the ones with defined angle will be attached to the ones
- // without any angle (shouldn't this logic be moved to process_external_surfaces()?)
- {
- Polygons polygons_bridged;
- polygons_bridged.reserve(layerm.fill_surfaces.surfaces.size());
- for (Surfaces::iterator it = layerm.fill_surfaces.surfaces.begin(); it != layerm.fill_surfaces.surfaces.end(); ++ it)
- if (it->bridge_angle >= 0)
- polygons_append(polygons_bridged, *it);
-
- // group surfaces by distinct properties (equal surface_type, thickness, thickness_layers, bridge_angle)
- // group is of type Slic3r::SurfaceCollection
- //FIXME: Use some smart heuristics to merge similar surfaces to eliminate tiny regions.
- std::vector<SurfacesPtr> groups;
- layerm.fill_surfaces.group(&groups);
-
- // merge compatible groups (we can generate continuous infill for them)
- {
- // cache flow widths and patterns used for all solid groups
- // (we'll use them for comparing compatible groups)
- std::vector<SurfaceGroupAttrib> group_attrib(groups.size());
- for (size_t i = 0; i < groups.size(); ++ i) {
- // we can only merge solid non-bridge surfaces, so discard
- // non-solid surfaces
- const Surface &surface = *groups[i].front();
- if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0)) {
- group_attrib[i].is_solid = true;
- group_attrib[i].flow_width = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width;
- group_attrib[i].pattern = surface.is_external() ?
+struct SurfaceFill {
+ SurfaceFill(const SurfaceFillParams& params) : region_id(size_t(-1)), surface(stCount, ExPolygon()), params(params) {}
+
+ size_t region_id;
+ Surface surface;
+ ExPolygons expolygons;
+ SurfaceFillParams params;
+};
+
+std::vector<SurfaceFill> group_fills(const Layer &layer)
+{
+ std::vector<SurfaceFill> surface_fills;
+
+ // Fill in a map of a region & surface to SurfaceFillParams.
+ std::set<SurfaceFillParams> set_surface_params;
+ std::vector<std::vector<const SurfaceFillParams*>> region_to_surface_params(layer.regions().size(), std::vector<const SurfaceFillParams*>());
+ SurfaceFillParams params;
+ bool has_internal_voids = false;
+ for (size_t region_id = 0; region_id < layer.regions().size(); ++ region_id) {
+ const LayerRegion &layerm = *layer.regions()[region_id];
+ region_to_surface_params[region_id].assign(layerm.fill_surfaces.size(), nullptr);
+ for (const Surface &surface : layerm.fill_surfaces.surfaces)
+ if (surface.surface_type == stInternalVoid)
+ has_internal_voids = true;
+ else {
+ FlowRole extrusion_role = (surface.surface_type == stTop) ? frTopSolidInfill : (surface.is_solid() ? frSolidInfill : frInfill);
+ bool is_bridge = layer.id() > 0 && surface.is_bridge();
+ params.extruder = layerm.region()->extruder(extrusion_role);
+ params.pattern = layerm.region()->config().fill_pattern.value;
+ params.density = float(layerm.region()->config().fill_density);
+
+ if (surface.is_solid()) {
+ params.density = 100.f;
+ params.pattern = (surface.is_external() && ! is_bridge) ?
(surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value) :
- ipRectilinear;
- }
- }
- // Loop through solid groups, find compatible groups and append them to this one.
- for (size_t i = 0; i < groups.size(); ++ i) {
- if (! group_attrib[i].is_solid)
- continue;
- for (size_t j = i + 1; j < groups.size();) {
- if (group_attrib[i] == group_attrib[j]) {
- // groups are compatible, merge them
- groups[i].insert(groups[i].end(), groups[j].begin(), groups[j].end());
- groups.erase(groups.begin() + j);
- group_attrib.erase(group_attrib.begin() + j);
- } else
- ++ j;
- }
- }
- }
-
- // Give priority to bridges. Process the bridges in the first round, the rest of the surfaces in the 2nd round.
- for (size_t round = 0; round < 2; ++ round) {
- for (std::vector<SurfacesPtr>::iterator it_group = groups.begin(); it_group != groups.end(); ++ it_group) {
- const SurfacesPtr &group = *it_group;
- bool is_bridge = group.front()->bridge_angle >= 0;
- if (is_bridge != (round == 0))
- continue;
- // Make a union of polygons defining the infiill regions of a group, use a safety offset.
- Polygons union_p = union_(to_polygons(*it_group), true);
- // Subtract surfaces having a defined bridge_angle from any other, use a safety offset.
- if (! polygons_bridged.empty() && ! is_bridge)
- union_p = diff(union_p, polygons_bridged, true);
- // subtract any other surface already processed
- //FIXME Vojtech: Because the bridge surfaces came first, they are subtracted twice!
- // Using group.front() as a template.
- surfaces_append(surfaces, diff_ex(union_p, to_polygons(surfaces), true), *group.front());
- }
- }
- }
-
+ ipRectilinear;
+ } else if (params.density <= 0)
+ continue;
+
+ params.extrusion_role =
+ is_bridge ?
+ erBridgeInfill :
+ (surface.is_solid() ?
+ ((surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
+ erInternalInfill);
+ params.bridge_angle = float(surface.bridge_angle);
+ params.angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value));
+
+ // calculate the actual flow we'll be using for this infill
+ params.flow = layerm.region()->flow(
+ extrusion_role,
+ (surface.thickness == -1) ? layer.height : surface.thickness, // extrusion height
+ is_bridge || Fill::use_bridge_flow(params.pattern), // bridge flow?
+ layer.id() == 0, // first layer?
+ -1, // auto width
+ *layer.object()
+ );
+
+ // Calculate flow spacing for infill pattern generation.
+ if (! surface.is_solid() && ! is_bridge) {
+ // it's internal infill, so we can calculate a generic flow spacing
+ // for all layers, for avoiding the ugly effect of
+ // misaligned infill on first layer because of different extrusion width and
+ // layer height
+ params.spacing = layerm.region()->flow(
+ frInfill,
+ layer.object()->config().layer_height.value, // TODO: handle infill_every_layers?
+ false, // no bridge
+ false, // no first layer
+ -1, // auto width
+ *layer.object()
+ ).spacing();
+ } else
+ params.spacing = params.flow.spacing();
+
+ auto it_params = set_surface_params.find(params);
+ if (it_params == set_surface_params.end())
+ it_params = set_surface_params.insert(it_params, params);
+ region_to_surface_params[region_id][&surface - &layerm.fill_surfaces.surfaces.front()] = &(*it_params);
+ }
+ }
+
+ surface_fills.reserve(set_surface_params.size());
+ for (const SurfaceFillParams &params : set_surface_params) {
+ const_cast<SurfaceFillParams&>(params).idx = surface_fills.size();
+ surface_fills.emplace_back(params);
+ }
+
+ for (size_t region_id = 0; region_id < layer.regions().size(); ++ region_id) {
+ const LayerRegion &layerm = *layer.regions()[region_id];
+ for (const Surface &surface : layerm.fill_surfaces.surfaces)
+ if (surface.surface_type != stInternalVoid) {
+ const SurfaceFillParams *params = region_to_surface_params[region_id][&surface - &layerm.fill_surfaces.surfaces.front()];
+ if (params != nullptr) {
+ SurfaceFill &fill = surface_fills[params->idx];
+ if (fill.region_id == size_t(-1)) {
+ fill.region_id = region_id;
+ fill.surface = surface;
+ fill.expolygons.emplace_back(std::move(fill.surface.expolygon));
+ } else
+ fill.expolygons.emplace_back(surface.expolygon);
+ }
+ }
+ }
+
+ {
+ Polygons all_polygons;
+ for (SurfaceFill &fill : surface_fills)
+ if (! fill.expolygons.empty()) {
+ if (fill.expolygons.size() > 1 || ! all_polygons.empty()) {
+ Polygons polys = to_polygons(std::move(fill.expolygons));
+ // Make a union of polygons, use a safety offset, subtract the preceding polygons.
+ // Bridges are processed first (see SurfaceFill::operator<())
+ fill.expolygons = all_polygons.empty() ? union_ex(polys, true) : diff_ex(polys, all_polygons, true);
+ append(all_polygons, std::move(polys));
+ } else if (&fill != &surface_fills.back())
+ append(all_polygons, to_polygons(fill.expolygons));
+ }
+ }
+
// we need to detect any narrow surfaces that might collapse
// when adding spacing below
// such narrow surfaces are often generated in sloping walls
@@ -119,155 +219,204 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
// we are going to grow such regions by overlapping them with the void (if any)
// TODO: detect and investigate whether there could be narrow regions without
// any void neighbors
- {
- coord_t distance_between_surfaces = std::max(
- std::max(infill_flow.scaled_spacing(), solid_infill_flow.scaled_spacing()),
- top_solid_infill_flow.scaled_spacing());
- Polygons surfaces_polygons = to_polygons(surfaces);
- Polygons collapsed = diff(
- surfaces_polygons,
- offset2(surfaces_polygons, (float)-distance_between_surfaces/2, (float)+distance_between_surfaces/2),
- true);
- Polygons to_subtract;
- to_subtract.reserve(collapsed.size() + number_polygons(surfaces));
- for (Surfaces::const_iterator it_surface = surfaces.begin(); it_surface != surfaces.end(); ++ it_surface)
- if (it_surface->surface_type == stInternalVoid)
- polygons_append(to_subtract, *it_surface);
- polygons_append(to_subtract, collapsed);
- surfaces_append(
- surfaces,
- intersection_ex(
- offset(collapsed, (float)distance_between_surfaces),
- to_subtract,
- true),
- stInternalSolid);
+ if (has_internal_voids) {
+ // Internal voids are generated only if "infill_only_where_needed" or "infill_every_layers" are active.
+ coord_t distance_between_surfaces = 0;
+ Polygons surfaces_polygons;
+ Polygons voids;
+ int region_internal_infill = -1;
+ int region_solid_infill = -1;
+ int region_some_infill = -1;
+ for (SurfaceFill &surface_fill : surface_fills)
+ if (! surface_fill.expolygons.empty()) {
+ distance_between_surfaces = std::max(distance_between_surfaces, surface_fill.params.flow.scaled_spacing());
+ append((surface_fill.surface.surface_type == stInternalVoid) ? voids : surfaces_polygons, to_polygons(surface_fill.expolygons));
+ if (surface_fill.surface.surface_type == stInternalSolid)
+ region_internal_infill = (int)surface_fill.region_id;
+ if (surface_fill.surface.is_solid())
+ region_solid_infill = (int)surface_fill.region_id;
+ if (surface_fill.surface.surface_type != stInternalVoid)
+ region_some_infill = (int)surface_fill.region_id;
+ }
+ if (! voids.empty() && ! surfaces_polygons.empty()) {
+ // First clip voids by the printing polygons, as the voids were ignored by the loop above during mutual clipping.
+ voids = diff(voids, surfaces_polygons);
+ // Corners of infill regions, which would not be filled with an extrusion path with a radius of distance_between_surfaces/2
+ Polygons collapsed = diff(
+ surfaces_polygons,
+ offset2(surfaces_polygons, (float)-distance_between_surfaces/2, (float)+distance_between_surfaces/2),
+ true);
+ //FIXME why the voids are added to collapsed here? First it is expensive, second the result may lead to some unwanted regions being
+ // added if two offsetted void regions merge.
+ // polygons_append(voids, collapsed);
+ ExPolygons extensions = intersection_ex(offset(collapsed, (float)distance_between_surfaces), voids, true);
+ // Now find an internal infill SurfaceFill to add these extrusions to.
+ SurfaceFill *internal_solid_fill = nullptr;
+ unsigned int region_id = 0;
+ if (region_internal_infill != -1)
+ region_id = region_internal_infill;
+ else if (region_solid_infill != -1)
+ region_id = region_solid_infill;
+ else if (region_some_infill != -1)
+ region_id = region_some_infill;
+ const LayerRegion& layerm = *layer.regions()[region_id];
+ for (SurfaceFill &surface_fill : surface_fills)
+ if (surface_fill.surface.surface_type == stInternalSolid && std::abs(layer.height - surface_fill.params.flow.height) < EPSILON) {
+ internal_solid_fill = &surface_fill;
+ break;
+ }
+ if (internal_solid_fill == nullptr) {
+ // Produce another solid fill.
+ params.extruder = layerm.region()->extruder(frSolidInfill);
+ params.pattern = ipRectilinear;
+ params.density = 100.f;
+ params.extrusion_role = erInternalInfill;
+ params.angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value));
+ // calculate the actual flow we'll be using for this infill
+ params.flow = layerm.region()->flow(
+ frSolidInfill,
+ layer.height, // extrusion height
+ false, // bridge flow?
+ layer.id() == 0, // first layer?
+ -1, // auto width
+ *layer.object()
+ );
+ params.spacing = params.flow.spacing();
+ surface_fills.emplace_back(params);
+ surface_fills.back().surface.surface_type = stInternalSolid;
+ surface_fills.back().surface.thickness = layer.height;
+ surface_fills.back().expolygons = std::move(extensions);
+ } else {
+ append(extensions, std::move(internal_solid_fill->expolygons));
+ internal_solid_fill->expolygons = union_ex(extensions);
+ }
+ }
}
- if (0) {
-// require "Slic3r/SVG.pm";
-// Slic3r::SVG::output("fill_" . $layerm->print_z . ".svg",
-// expolygons => [ map $_->expolygon, grep !$_->is_solid, @surfaces ],
-// red_expolygons => [ map $_->expolygon, grep $_->is_solid, @surfaces ],
-// );
- }
+ return surface_fills;
+}
- for (const Surface &surface : surfaces) {
- if (surface.surface_type == stInternalVoid)
- continue;
- InfillPattern fill_pattern = layerm.region()->config().fill_pattern.value;
- double density = fill_density;
- FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill :
- (surface.is_solid() ? frSolidInfill : frInfill);
- bool is_bridge = layerm.layer()->id() > 0 && surface.is_bridge();
-
- if (surface.is_solid()) {
- density = 100.;
- fill_pattern = (surface.is_external() && ! is_bridge) ?
- (surface.is_top() ? layerm.region()->config().top_fill_pattern.value : layerm.region()->config().bottom_fill_pattern.value) :
- ipRectilinear;
- } else if (density <= 0)
- continue;
-
- // get filler object
- std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(fill_pattern));
- f->set_bounding_box(layerm.layer()->object()->bounding_box());
-
- // calculate the actual flow we'll be using for this infill
- coordf_t h = (surface.thickness == -1) ? layerm.layer()->height : surface.thickness;
- Flow flow = layerm.region()->flow(
- role,
- h,
- is_bridge || f->use_bridge_flow(), // bridge flow?
- layerm.layer()->id() == 0, // first layer?
- -1, // auto width
- *layerm.layer()->object()
- );
-
- // calculate flow spacing for infill pattern generation
- bool using_internal_flow = false;
- if (! surface.is_solid() && ! is_bridge) {
- // it's internal infill, so we can calculate a generic flow spacing
- // for all layers, for avoiding the ugly effect of
- // misaligned infill on first layer because of different extrusion width and
- // layer height
- Flow internal_flow = layerm.region()->flow(
- frInfill,
- layerm.layer()->object()->config().layer_height.value, // TODO: handle infill_every_layers?
- false, // no bridge
- false, // no first layer
- -1, // auto width
- *layerm.layer()->object()
- );
- f->spacing = internal_flow.spacing();
- using_internal_flow = true;
- } else {
- f->spacing = flow.spacing();
- }
+#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
+void export_group_fills_to_svg(const char *path, const std::vector<SurfaceFill> &fills)
+{
+ BoundingBox bbox;
+ for (const auto &fill : fills)
+ for (const auto &expoly : fill.expolygons)
+ bbox.merge(get_extents(expoly));
+ Point legend_size = export_surface_type_legend_to_svg_box_size();
+ Point legend_pos(bbox.min(0), bbox.max(1));
+ bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1)));
+
+ SVG svg(path, bbox);
+ const float transparency = 0.5f;
+ for (const auto &fill : fills)
+ for (const auto &expoly : fill.expolygons)
+ svg.draw(expoly, surface_type_to_color_name(fill.surface.surface_type), transparency);
+ export_surface_type_legend_to_svg(svg, legend_pos);
+ svg.Close();
+}
+#endif
+// friend to Layer
+void Layer::make_fills()
+{
+ for (LayerRegion *layerm : m_regions)
+ layerm->fills.clear();
+
+
+#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
+// this->export_region_fill_surfaces_to_svg_debug("10_fill-initial");
+#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
+
+ std::vector<SurfaceFill> surface_fills = group_fills(*this);
+ const Slic3r::BoundingBox bbox = this->object()->bounding_box();
+
+#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
+ {
+ static int iRun = 0;
+ export_group_fills_to_svg(debug_out_path("Layer-fill_surfaces-10_fill-final-%d.svg", iRun ++).c_str(), surface_fills);
+ }
+#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
+
+ for (SurfaceFill &surface_fill : surface_fills) {
+ // Create the filler object.
+ std::unique_ptr<Fill> f = std::unique_ptr<Fill>(Fill::new_from_type(surface_fill.params.pattern));
+ f->set_bounding_box(bbox);
+ f->layer_id = this->id();
+ f->z = this->print_z;
+ f->angle = surface_fill.params.angle;
+
+ // calculate flow spacing for infill pattern generation
+ bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.flow.bridge;
double link_max_length = 0.;
- if (! is_bridge) {
+ if (! surface_fill.params.flow.bridge) {
#if 0
link_max_length = layerm.region()->config().get_abs_value(surface.is_external() ? "external_fill_link_max_length" : "fill_link_max_length", flow.spacing());
// printf("flow spacing: %f, is_external: %d, link_max_length: %lf\n", flow.spacing(), int(surface.is_external()), link_max_length);
#else
- if (density > 80.) // 80%
+ if (surface_fill.params.density > 80.) // 80%
link_max_length = 3. * f->spacing;
#endif
}
- f->layer_id = layerm.layer()->id();
- f->z = layerm.layer()->print_z;
- f->angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value));
// Maximum length of the perimeter segment linking two infill lines.
f->link_max_length = (coord_t)scale_(link_max_length);
// Used by the concentric infill pattern to clip the loops to create extrusion paths.
- f->loop_clipping = coord_t(scale_(flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER);
-// f->layer_height = h;
+ f->loop_clipping = coord_t(scale_(surface_fill.params.flow.nozzle_diameter) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER);
// apply half spacing using this flow's own spacing and generate infill
FillParams params;
- params.density = float(0.01 * density);
-// params.dont_adjust = true;
- params.dont_adjust = false;
- Polylines polylines = f->fill_surface(&surface, params);
- if (polylines.empty())
- continue;
-
- // calculate actual flow from spacing (which might have been adjusted by the infill
- // pattern generator)
- if (using_internal_flow) {
- // if we used the internal flow we're not doing a solid infill
- // so we can safely ignore the slight variation that might have
- // been applied to $f->flow_spacing
- } else {
- flow = Flow::new_from_spacing(f->spacing, flow.nozzle_diameter, (float)h, is_bridge || f->use_bridge_flow());
- }
+ params.density = float(0.01 * surface_fill.params.density);
+ params.dont_adjust = surface_fill.params.dont_adjust; // false
- // Save into layer.
- auto *eec = new ExtrusionEntityCollection();
- out.entities.push_back(eec);
- // Only concentric fills are not sorted.
- eec->no_sort = f->no_sort();
- extrusion_entities_append_paths(
- eec->entities, std::move(polylines),
- is_bridge ?
- erBridgeInfill :
- (surface.is_solid() ?
- ((surface.surface_type == stTop) ? erTopSolidInfill : erSolidInfill) :
- erInternalInfill),
- flow.mm3_per_mm(), flow.width, flow.height);
+ for (ExPolygon &expoly : surface_fill.expolygons) {
+ // Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
+ f->spacing = surface_fill.params.spacing;
+ surface_fill.surface.expolygon = std::move(expoly);
+ Polylines polylines = f->fill_surface(&surface_fill.surface, params);
+ if (! polylines.empty()) {
+ // calculate actual flow from spacing (which might have been adjusted by the infill
+ // pattern generator)
+ double flow_mm3_per_mm = surface_fill.params.flow.mm3_per_mm();
+ double flow_width = surface_fill.params.flow.width;
+ if (using_internal_flow) {
+ // if we used the internal flow we're not doing a solid infill
+ // so we can safely ignore the slight variation that might have
+ // been applied to f->spacing
+ } else {
+ Flow new_flow = Flow::new_from_spacing(float(f->spacing), surface_fill.params.flow.nozzle_diameter, surface_fill.params.flow.height, surface_fill.params.flow.bridge);
+ flow_mm3_per_mm = new_flow.mm3_per_mm();
+ flow_width = new_flow.width;
+ }
+ // Save into layer.
+ auto *eec = new ExtrusionEntityCollection();
+ m_regions[surface_fill.region_id]->fills.entities.push_back(eec);
+ // Only concentric fills are not sorted.
+ eec->no_sort = f->no_sort();
+ extrusion_entities_append_paths(
+ eec->entities, std::move(polylines),
+ surface_fill.params.extrusion_role,
+ flow_mm3_per_mm, float(flow_width), surface_fill.params.flow.height);
+ }
+ }
}
// add thin fill regions
- // thin_fills are of C++ Slic3r::ExtrusionEntityCollection, perl type Slic3r::ExtrusionPath::Collection
// Unpacks the collection, creates multiple collections per path.
// The path type could be ExtrusionPath, ExtrusionLoop or ExtrusionEntityCollection.
// Why the paths are unpacked?
- for (const ExtrusionEntity *thin_fill : layerm.thin_fills.entities) {
- ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection());
- out.entities.push_back(&collection);
- collection.entities.push_back(thin_fill->clone());
- }
+ for (LayerRegion *layerm : m_regions)
+ for (const ExtrusionEntity *thin_fill : layerm->thin_fills.entities) {
+ ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection());
+ layerm->fills.entities.push_back(&collection);
+ collection.entities.push_back(thin_fill->clone());
+ }
+
+#ifndef NDEBUG
+ for (LayerRegion *layerm : m_regions)
+ for (size_t i = 0; i < layerm->fills.entities.size(); ++ i)
+ assert(dynamic_cast<ExtrusionEntityCollection*>(layerm->fills.entities[i]) != nullptr);
+#endif
}
} // namespace Slic3r
diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp
index 7a99e84f7..c16d76415 100644
--- a/src/libslic3r/Fill/FillBase.cpp
+++ b/src/libslic3r/Fill/FillBase.cpp
@@ -34,7 +34,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipArchimedeanChords: return new FillArchimedeanChords();
case ipHilbertCurve: return new FillHilbertCurve();
case ipOctagramSpiral: return new FillOctagramSpiral();
- default: throw std::invalid_argument("unknown type");;
+ default: throw std::invalid_argument("unknown type");
}
}
@@ -45,6 +45,24 @@ Fill* Fill::new_from_type(const std::string &type)
return (it == enum_keys_map.end()) ? nullptr : new_from_type(InfillPattern(it->second));
}
+// Force initialization of the Fill::use_bridge_flow() internal static map in a thread safe fashion even on compilers
+// not supporting thread safe non-static data member initializers.
+static bool use_bridge_flow_initializer = Fill::use_bridge_flow(ipGrid);
+
+bool Fill::use_bridge_flow(const InfillPattern type)
+{
+ static std::vector<unsigned char> cached;
+ if (cached.empty()) {
+ cached.assign(size_t(ipCount), 0);
+ for (size_t i = 0; i < cached.size(); ++ i) {
+ auto *fill = Fill::new_from_type((InfillPattern)i);
+ cached[i] = fill->use_bridge_flow();
+ delete fill;
+ }
+ }
+ return cached[type] != 0;
+}
+
Polylines Fill::fill_surface(const Surface *surface, const FillParams &params)
{
// Perform offset.
diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp
index 8bf6c3689..fb7947893 100644
--- a/src/libslic3r/Fill/FillBase.hpp
+++ b/src/libslic3r/Fill/FillBase.hpp
@@ -70,6 +70,7 @@ public:
static Fill* new_from_type(const InfillPattern type);
static Fill* new_from_type(const std::string &type);
+ static bool use_bridge_flow(const InfillPattern type);
void set_bounding_box(const Slic3r::BoundingBox &bbox) { bounding_box = bbox; }
diff --git a/src/libslic3r/Flow.hpp b/src/libslic3r/Flow.hpp
index 4b0a846ad..51cc4da9d 100644
--- a/src/libslic3r/Flow.hpp
+++ b/src/libslic3r/Flow.hpp
@@ -56,6 +56,8 @@ public:
// Enable some perimeter squish (see INSET_OVERLAP_TOLERANCE).
// Here an overlap of 0.2x external perimeter spacing is allowed for by the elephant foot compensation.
coord_t scaled_elephant_foot_spacing() const { return coord_t(0.5f * float(this->scaled_width() + 0.6f * this->scaled_spacing())); }
+
+ bool operator==(const Flow &rhs) const { return this->width == rhs.width && this->height == rhs.height && this->nozzle_diameter == rhs.nozzle_diameter && this->bridge == rhs.bridge; }
static Flow new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio);
// Create a flow from the spacing of extrusion lines.
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 819dcc56e..b5857a77b 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -690,15 +690,19 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
throw std::runtime_error(msg);
}
- if (print->config().remaining_times.value) {
- BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for normal mode" << log_memory_info();
- m_normal_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
+ GCodeTimeEstimator::PostProcessData normal_data = m_normal_time_estimator.get_post_process_data();
+ GCodeTimeEstimator::PostProcessData silent_data = m_silent_time_estimator.get_post_process_data();
+
+ bool remaining_times_enabled = print->config().remaining_times.value;
+
+ BOOST_LOG_TRIVIAL(debug) << "Time estimator post processing" << log_memory_info();
+ GCodeTimeEstimator::post_process(path_tmp, 60.0f, remaining_times_enabled ? &normal_data : nullptr, (remaining_times_enabled && m_silent_time_estimator_enabled) ? &silent_data : nullptr);
+
+ if (remaining_times_enabled)
+ {
m_normal_time_estimator.reset();
- if (m_silent_time_estimator_enabled) {
- BOOST_LOG_TRIVIAL(debug) << "Processing remaining times for silent mode" << log_memory_info();
- m_silent_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
+ if (m_silent_time_estimator_enabled)
m_silent_time_estimator.reset();
- }
}
// starts analyzer calculations
@@ -1771,13 +1775,9 @@ void GCode::process_layer(
// This extrusion is part of certain Region, which tells us which extruder should be used for it:
int correct_extruder_id = Print::get_extruder(*fill, region);
- //FIXME what is this?
- entity_type=="infills" ?
- std::max<int>(0, (is_solid_infill(fill->entities.front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) - 1) :
- std::max<int>(region.config().perimeter_extruder.value - 1, 0);
// Let's recover vector of extruder overrides:
- const ExtruderPerCopy* entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(fill, correct_extruder_id, (int)layer_to_print.object()->copies().size());
+ const ExtruderPerCopy* entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(fill, correct_extruder_id, layer_to_print.object()->copies().size());
// Now we must add this extrusion into the by_extruder map, once for each extruder that will print it:
for (unsigned int extruder : layer_tools.extruders)
@@ -1949,7 +1949,7 @@ void GCode::process_layer(
_write(file, gcode);
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
", time estimator memory: " <<
- format_memsize_MB(m_normal_time_estimator.memory_used() + m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0) <<
+ format_memsize_MB(m_normal_time_estimator.memory_used() + (m_silent_time_estimator_enabled ? m_silent_time_estimator.memory_used() : 0)) <<
", analyzer memory: " <<
format_memsize_MB(m_analyzer.memory_used()) <<
log_memory_info();
@@ -2030,38 +2030,6 @@ std::string GCode::change_layer(coordf_t print_z)
return gcode;
}
-static inline const char* ExtrusionRole2String(const ExtrusionRole role)
-{
- switch (role) {
- case erNone: return "erNone";
- case erPerimeter: return "erPerimeter";
- case erExternalPerimeter: return "erExternalPerimeter";
- case erOverhangPerimeter: return "erOverhangPerimeter";
- case erInternalInfill: return "erInternalInfill";
- case erSolidInfill: return "erSolidInfill";
- case erTopSolidInfill: return "erTopSolidInfill";
- case erBridgeInfill: return "erBridgeInfill";
- case erGapFill: return "erGapFill";
- case erSkirt: return "erSkirt";
- case erSupportMaterial: return "erSupportMaterial";
- case erSupportMaterialInterface: return "erSupportMaterialInterface";
- case erWipeTower: return "erWipeTower";
- case erMixed: return "erMixed";
-
- default: return "erInvalid";
- };
-}
-
-static inline const char* ExtrusionLoopRole2String(const ExtrusionLoopRole role)
-{
- switch (role) {
- case elrDefault: return "elrDefault";
- case elrContourInternalPerimeter: return "elrContourInternalPerimeter";
- case elrSkirt: return "elrSkirt";
- default: return "elrInvalid";
- }
-};
-
// Return a value in <0, 1> of a cubic B-spline kernel centered around zero.
// The B-spline is re-scaled so it has value 1 at zero.
static inline float bspline_kernel(float x)
@@ -2444,8 +2412,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// extrude along the path
std::string gcode;
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
-// description += ExtrusionLoopRole2String(loop.loop_role());
-// description += ExtrusionRole2String(path->role);
+// description += ExtrusionLoop::role_to_string(loop.loop_role());
+// description += ExtrusionEntity::role_to_string(path->role);
path->simplify(SCALED_RESOLUTION);
gcode += this->_extrude(*path, description, speed);
}
@@ -2498,8 +2466,8 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
// extrude along the path
std::string gcode;
for (ExtrusionPath path : multipath.paths) {
-// description += ExtrusionLoopRole2String(loop.loop_role());
-// description += ExtrusionRole2String(path->role);
+// description += ExtrusionLoop::role_to_string(loop.loop_role());
+// description += ExtrusionEntity::role_to_string(path->role);
path.simplify(SCALED_RESOLUTION);
gcode += this->_extrude(path, description, speed);
}
@@ -2528,7 +2496,7 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string des
std::string GCode::extrude_path(ExtrusionPath path, std::string description, double speed)
{
-// description += ExtrusionRole2String(path.role());
+// description += ExtrusionEntity::role_to_string(path.role());
path.simplify(SCALED_RESOLUTION);
std::string gcode = this->_extrude(path, description, speed);
if (m_wipe.enable) {
@@ -3056,7 +3024,7 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
// 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 std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copies_extruder, unsigned int object_copies_num)
+void GCode::ObjectByExtruder::Island::Region::append(const std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copies_extruder, size_t object_copies_num)
{
// We are going to manipulate either perimeters or infills, exactly in the same way. Let's create pointers to the proper structure to not repeat ourselves:
ExtrusionEntityCollection* perimeters_or_infills = &infills;
diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp
index 83d61c483..72813810b 100644
--- a/src/libslic3r/GCode.hpp
+++ b/src/libslic3r/GCode.hpp
@@ -246,7 +246,7 @@ protected:
std::vector<const ExtruderPerCopy*> perimeters_overrides;
// 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 std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copy_extruders, unsigned int object_copies_num);
+ void append(const std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copy_extruders, size_t object_copies_num);
};
std::vector<Region> by_region; // all extrusions for this island, grouped by regions
diff --git a/src/libslic3r/GCode/PreviewData.cpp b/src/libslic3r/GCode/PreviewData.cpp
index e634461ae..74de2f532 100644
--- a/src/libslic3r/GCode/PreviewData.cpp
+++ b/src/libslic3r/GCode/PreviewData.cpp
@@ -121,7 +121,7 @@ GCodePreviewData::LegendItem::LegendItem(const std::string& text, const GCodePre
{
}
-const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[Num_Extrusion_Roles] =
+const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[erCount] =
{
Color(0.0f, 0.0f, 0.0f, 1.0f), // erNone
Color(1.0f, 0.0f, 0.0f, 1.0f), // erPerimeter
@@ -140,44 +140,20 @@ const GCodePreviewData::Color GCodePreviewData::Extrusion::Default_Extrusion_Rol
Color(0.0f, 0.0f, 0.0f, 1.0f) // erMixed
};
-// todo: merge with Slic3r::ExtrusionRole2String() from GCode.cpp
-const std::string GCodePreviewData::Extrusion::Default_Extrusion_Role_Names[Num_Extrusion_Roles]
-{
- L("None"),
- L("Perimeter"),
- L("External perimeter"),
- L("Overhang perimeter"),
- L("Internal infill"),
- L("Solid infill"),
- L("Top solid infill"),
- L("Bridge infill"),
- L("Gap fill"),
- L("Skirt"),
- L("Support material"),
- L("Support material interface"),
- L("Wipe tower"),
- L("Custom"),
- L("Mixed")
-};
-
const GCodePreviewData::Extrusion::EViewType GCodePreviewData::Extrusion::Default_View_Type = GCodePreviewData::Extrusion::FeatureType;
void GCodePreviewData::Extrusion::set_default()
{
view_type = Default_View_Type;
- ::memcpy((void*)role_colors, (const void*)Default_Extrusion_Role_Colors, Num_Extrusion_Roles * sizeof(Color));
+ ::memcpy((void*)role_colors, (const void*)Default_Extrusion_Role_Colors, erCount * sizeof(Color));
- for (unsigned int i = 0; i < Num_Extrusion_Roles; ++i)
- {
- role_names[i] = Default_Extrusion_Role_Names[i];
- }
+ for (unsigned int i = 0; i < erCount; ++i)
+ role_names[i] = ExtrusionEntity::role_to_string(ExtrusionRole(i));
role_flags = 0;
- for (unsigned int i = 0; i < Num_Extrusion_Roles; ++i)
- {
+ for (unsigned int i = 0; i < erCount; ++i)
role_flags |= 1 << i;
- }
}
bool GCodePreviewData::Extrusion::is_role_flag_set(ExtrusionRole role) const
@@ -318,7 +294,7 @@ GCodePreviewData::Color GCodePreviewData::get_volumetric_rate_color(float rate)
void GCodePreviewData::set_extrusion_role_color(const std::string& role_name, float red, float green, float blue, float alpha)
{
- for (unsigned int i = 0; i < Extrusion::Num_Extrusion_Roles; ++i)
+ for (unsigned int i = 0; i < erCount; ++i)
{
if (role_name == extrusion.role_names[i])
{
diff --git a/src/libslic3r/GCode/PreviewData.hpp b/src/libslic3r/GCode/PreviewData.hpp
index 1c8e0463d..6490399b4 100644
--- a/src/libslic3r/GCode/PreviewData.hpp
+++ b/src/libslic3r/GCode/PreviewData.hpp
@@ -80,9 +80,8 @@ public:
Num_View_Types
};
- static const unsigned int Num_Extrusion_Roles = (unsigned int)erMixed + 1;
- static const Color Default_Extrusion_Role_Colors[Num_Extrusion_Roles];
- static const std::string Default_Extrusion_Role_Names[Num_Extrusion_Roles];
+ static const Color Default_Extrusion_Role_Colors[erCount];
+ static const std::string Default_Extrusion_Role_Names[erCount];
static const EViewType Default_View_Type;
struct Layer
@@ -96,8 +95,8 @@ public:
typedef std::vector<Layer> LayersList;
EViewType view_type;
- Color role_colors[Num_Extrusion_Roles];
- std::string role_names[Num_Extrusion_Roles];
+ Color role_colors[erCount];
+ std::string role_names[erCount];
LayersList layers;
unsigned int role_flags;
diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp
index 9280aa33a..0a9ec320e 100644
--- a/src/libslic3r/GCode/ToolOrdering.cpp
+++ b/src/libslic3r/GCode/ToolOrdering.cpp
@@ -329,6 +329,28 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
}
}
+ // If the model contains empty layers (such as https://github.com/prusa3d/Slic3r/issues/1266), there might be layers
+ // that were not marked as has_wipe_tower, even when they should have been. This produces a crash with soluble supports
+ // and maybe other problems. We will therefore go through layer_tools and detect and fix this.
+ // So, if there is a non-object layer starting with different extruder than the last one ended with (or containing more than one extruder),
+ // we'll mark it with has_wipe tower.
+ for (unsigned int i=0; i+1<m_layer_tools.size(); ++i) {
+ LayerTools& lt = m_layer_tools[i];
+ LayerTools& lt_next = m_layer_tools[i+1];
+ if (lt.extruders.empty() || lt_next.extruders.empty())
+ break;
+ if (!lt_next.has_wipe_tower && (lt_next.extruders.front() != lt.extruders.back() || lt_next.extruders.size() > 1))
+ lt_next.has_wipe_tower = true;
+ // We should also check that the next wipe tower layer is no further than max_layer_height:
+ unsigned int j = i+1;
+ double last_wipe_tower_print_z = lt_next.print_z;
+ while (++j < m_layer_tools.size()-1 && !m_layer_tools[j].has_wipe_tower)
+ if (m_layer_tools[j+1].print_z - last_wipe_tower_print_z > max_layer_height) {
+ m_layer_tools[j].has_wipe_tower = true;
+ last_wipe_tower_print_z = m_layer_tools[j].print_z;
+ }
+ }
+
// Calculate the wipe_tower_layer_height values.
coordf_t wipe_tower_print_z_last = 0.;
for (LayerTools &lt : m_layer_tools)
@@ -458,14 +480,14 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
continue;
}
- const auto& object = object_list[i];
+ const PrintObject* object = object_list[i];
// Finds this layer:
auto this_layer_it = std::find_if(object->layers().begin(), object->layers().end(), [&lt](const Layer* lay) { return std::abs(lt.print_z - lay->print_z)<EPSILON; });
if (this_layer_it == object->layers().end())
continue;
const Layer* this_layer = *this_layer_it;
- unsigned int num_of_copies = object->copies().size();
+ size_t num_of_copies = object->copies().size();
for (unsigned int copy = 0; copy < num_of_copies; ++copy) { // iterate through copies first, so that we mark neighbouring infills to minimize travel moves
@@ -494,7 +516,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
if ((!is_entity_overridden(fill, copy) && fill->total_volume() > min_infill_volume)) { // this infill will be used to wipe this extruder
set_extruder_override(fill, copy, new_extruder, num_of_copies);
- volume_to_wipe -= fill->total_volume();
+ volume_to_wipe -= float(fill->total_volume());
}
}
}
@@ -512,7 +534,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int
if ((!is_entity_overridden(fill, copy) && fill->total_volume() > min_infill_volume)) {
set_extruder_override(fill, copy, new_extruder, num_of_copies);
- volume_to_wipe -= fill->total_volume();
+ volume_to_wipe -= float(fill->total_volume());
}
}
}
@@ -540,9 +562,9 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
if (this_layer_it == object->layers().end())
continue;
const Layer* this_layer = *this_layer_it;
- unsigned int num_of_copies = object->copies().size();
+ size_t num_of_copies = object->copies().size();
- for (unsigned int copy = 0; copy < num_of_copies; ++copy) { // iterate through copies first, so that we mark neighbouring infills to minimize travel moves
+ for (size_t copy = 0; copy < num_of_copies; ++copy) { // iterate through copies first, so that we mark neighbouring infills to minimize travel moves
for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) {
const auto& region = *object->print()->regions()[region_id];
@@ -598,7 +620,7 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
// so -1 was used as "print as usual".
// The resulting vector has to keep track of which extrusions are the ones that were overridden and which were not. In the extruder is used as overridden,
// its number is saved as it is (zero-based index). Usual extrusions are saved as -number-1 (unfortunately there is no negative zero).
-const std::vector<int>* WipingExtrusions::get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, int num_of_copies)
+const std::vector<int>* WipingExtrusions::get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies)
{
auto entity_map_it = entity_map.find(entity);
if (entity_map_it == entity_map.end())
diff --git a/src/libslic3r/GCode/ToolOrdering.hpp b/src/libslic3r/GCode/ToolOrdering.hpp
index d4006120d..0d4b83ecb 100644
--- a/src/libslic3r/GCode/ToolOrdering.hpp
+++ b/src/libslic3r/GCode/ToolOrdering.hpp
@@ -24,7 +24,7 @@ public:
}
// This is called from GCode::process_layer - see implementation for further comments:
- const std::vector<int>* get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, int num_of_copies);
+ const std::vector<int>* 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
// marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower:
@@ -44,7 +44,7 @@ private:
void set_extruder_override(const ExtrusionEntity* entity, unsigned int copy_id, int extruder, unsigned int num_of_copies);
// Returns true in case that entity is not printed with its usual extruder for a given copy:
- bool is_entity_overridden(const ExtrusionEntity* entity, int copy_id) const {
+ bool is_entity_overridden(const ExtrusionEntity* entity, size_t copy_id) const {
return (entity_map.find(entity) == entity_map.end() ? false : entity_map.at(entity).at(copy_id) != -1);
}
diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp
index da4c6aa6e..84d03ba20 100644
--- a/src/libslic3r/GCode/WipeTower.cpp
+++ b/src/libslic3r/GCode/WipeTower.cpp
@@ -82,7 +82,7 @@ public:
}
WipeTowerWriter& change_analyzer_mm3_per_mm(float len, float e) {
- static const float area = M_PI * 1.75f * 1.75f / 4.f;
+ static const float area = float(M_PI) * 1.75f * 1.75f / 4.f;
float mm3_per_mm = (len == 0.f ? 0.f : area * e / len);
// adds tag for analyzer:
char buf[64];
@@ -100,7 +100,7 @@ public:
return *this;
}
- WipeTowerWriter& set_initial_tool(const unsigned int tool) { m_current_tool = tool; return *this; }
+ WipeTowerWriter& set_initial_tool(size_t tool) { m_current_tool = tool; return *this; }
WipeTowerWriter& set_z(float z)
{ m_current_z = z; return *this; }
@@ -151,7 +151,7 @@ public:
float dx = x - m_current_pos.x();
float dy = y - m_current_pos.y();
- double len = sqrt(dx*dx+dy*dy);
+ float len = std::sqrt(dx*dx+dy*dy);
if (record_length)
m_used_filament_length += e;
@@ -159,11 +159,11 @@ public:
Vec2f rotated_current_pos(rotate(m_current_pos + Vec2f(0.f,m_y_shift), m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle)); // this is where we are
Vec2f rot(rotate(Vec2f(x,y+m_y_shift), m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle)); // this is where we want to go
- if (! m_preview_suppressed && e > 0.f && len > 0.) {
+ if (! m_preview_suppressed && e > 0.f && len > 0.f) {
change_analyzer_mm3_per_mm(len, e);
// Width of a squished extrusion, corrected for the roundings of the squished extrusions.
// This is left zero if it is a travel move.
- float width = float(double(e) * m_filpar[0].filament_area / (len * m_layer_height));
+ float width = e * m_filpar[0].filament_area / (len * m_layer_height);
// Correct for the roundings of a squished extrusion.
width += m_layer_height * float(1. - M_PI / 4.);
if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos)
@@ -172,10 +172,10 @@ public:
}
m_gcode += "G1";
- if (std::abs(rot.x() - rotated_current_pos.x()) > EPSILON)
+ if (std::abs(rot.x() - rotated_current_pos.x()) > (float)EPSILON)
m_gcode += set_format_X(rot.x());
- if (std::abs(rot.y() - rotated_current_pos.y()) > EPSILON)
+ if (std::abs(rot.y() - rotated_current_pos.y()) > (float)EPSILON)
m_gcode += set_format_Y(rot.y());
@@ -184,7 +184,7 @@ public:
if (f != 0.f && f != m_current_feedrate) {
if (limit_volumetric_flow) {
- float e_speed = e / (((len == 0) ? std::abs(e) : len) / f * 60.f);
+ float e_speed = e / (((len == 0.f) ? std::abs(e) : len) / f * 60.f);
f /= std::max(1.f, e_speed / m_filpar[m_current_tool].max_e_speed);
}
m_gcode += set_format_F(f);
@@ -194,7 +194,7 @@ public:
m_current_pos.y() = y;
// Update the elapsed time with a rough estimate.
- m_elapsed_time += ((len == 0) ? std::abs(e) : len) / m_current_feedrate * 60.f;
+ m_elapsed_time += ((len == 0.f) ? std::abs(e) : len) / m_current_feedrate * 60.f;
m_gcode += "\n";
return *this;
}
@@ -214,7 +214,7 @@ public:
{
float dx = x - m_current_pos.x();
float dy = y - m_current_pos.y();
- return extrude_explicit(x, y, sqrt(dx*dx+dy*dy) * m_extrusion_flow, f, true);
+ return extrude_explicit(x, y, std::sqrt(dx*dx+dy*dy) * m_extrusion_flow, f, true);
}
WipeTowerWriter& extrude(const Vec2f &dest, const float f = 0.f)
@@ -311,7 +311,7 @@ public:
return *this;
}
- WipeTowerWriter& set_tool(int tool)
+ WipeTowerWriter& set_tool(size_t tool)
{
m_current_tool = tool;
return *this;
@@ -320,57 +320,52 @@ public:
// Set extruder temperature, don't wait by default.
WipeTowerWriter& set_extruder_temp(int temperature, bool wait = false)
{
- char buf[128];
- sprintf(buf, "M%d S%d\n", wait ? 109 : 104, temperature);
- m_gcode += buf;
+ m_gcode += "M" + std::to_string(wait ? 109 : 104) + " S" + std::to_string(temperature) + "\n";
return *this;
- };
+ }
// Wait for a period of time (seconds).
WipeTowerWriter& wait(float time)
{
- if (time==0)
+ if (time==0.f)
return *this;
char buf[128];
sprintf(buf, "G4 S%.3f\n", time);
m_gcode += buf;
return *this;
- };
+ }
// Set speed factor override percentage.
WipeTowerWriter& speed_override(int speed)
{
- char buf[128];
- sprintf(buf, "M220 S%d\n", speed);
- m_gcode += buf;
+ m_gcode += "M220 S" + std::to_string(speed) + "\n";
return *this;
- };
+ }
// Let the firmware back up the active speed override value.
WipeTowerWriter& speed_override_backup()
{
m_gcode += "M220 B\n";
return *this;
- };
+ }
// Let the firmware restore the active speed override value.
WipeTowerWriter& speed_override_restore()
{
m_gcode += "M220 R\n";
return *this;
- };
+ }
// Set digital trimpot motor
WipeTowerWriter& set_extruder_trimpot(int current)
{
- char buf[128];
if (m_gcode_flavor == gcfRepRap)
- sprintf(buf, "M906 E%d\n", current);
+ m_gcode += "M906 E";
else
- sprintf(buf, "M907 E%d\n", current);
- m_gcode += buf;
+ m_gcode += "M907 E";
+ m_gcode += std::to_string(current) + "\n";
return *this;
- };
+ }
WipeTowerWriter& flush_planner_queue()
{
@@ -386,28 +381,20 @@ public:
}
WipeTowerWriter& comment_with_value(const char *comment, int value)
- {
- char strvalue[64];
- sprintf(strvalue, "%d", value);
- m_gcode += std::string(";") + comment + strvalue + "\n";
+ {
+ m_gcode += std::string(";") + comment + std::to_string(value) + "\n";
return *this;
- };
+ }
- WipeTowerWriter& set_fan(unsigned int speed)
+ WipeTowerWriter& set_fan(unsigned speed)
{
if (speed == m_last_fan_speed)
return *this;
-
if (speed == 0)
m_gcode += "M107\n";
- else
- {
- m_gcode += "M106 S";
- char buf[128];
- sprintf(buf,"%u\n",(unsigned int)(255.0 * speed / 100.0));
- m_gcode += buf;
- }
+ else
+ m_gcode += "M106 S" + std::to_string(unsigned(255.0 * speed / 100.0)) + "\n";
m_last_fan_speed = speed;
return *this;
}
@@ -419,7 +406,7 @@ private:
Vec2f m_current_pos;
float m_current_z;
float m_current_feedrate;
- unsigned int m_current_tool;
+ size_t m_current_tool;
float m_layer_height;
float m_extrusion_flow;
bool m_preview_suppressed;
@@ -430,7 +417,7 @@ private:
float m_y_shift = 0.f;
float m_wipe_tower_width = 0.f;
float m_wipe_tower_depth = 0.f;
- float m_last_fan_speed = 0.f;
+ unsigned m_last_fan_speed = 0;
int current_temp = -1;
const float m_default_analyzer_line_width;
float m_used_filament_length = 0.f;
@@ -479,12 +466,12 @@ private:
WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<float>>& wiping_matrix, size_t initial_tool) :
m_semm(config.single_extruder_multi_material.value),
m_wipe_tower_pos(config.wipe_tower_x, config.wipe_tower_y),
- m_wipe_tower_width(config.wipe_tower_width),
- m_wipe_tower_rotation_angle(config.wipe_tower_rotation_angle),
+ m_wipe_tower_width(float(config.wipe_tower_width)),
+ m_wipe_tower_rotation_angle(float(config.wipe_tower_rotation_angle)),
m_y_shift(0.f),
m_z_pos(0.f),
m_is_first_layer(false),
- m_bridging(config.wipe_tower_bridging),
+ m_bridging(float(config.wipe_tower_bridging)),
m_gcode_flavor(config.gcode_flavor),
m_current_tool(initial_tool),
wipe_volumes(wiping_matrix)
@@ -492,16 +479,16 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<fl
// If this is a single extruder MM printer, we will use all the SE-specific config values.
// Otherwise, the defaults will be used to turn off the SE stuff.
if (m_semm) {
- m_cooling_tube_retraction = config.cooling_tube_retraction;
- m_cooling_tube_length = config.cooling_tube_length;
- m_parking_pos_retraction = config.parking_pos_retraction;
- m_extra_loading_move = config.extra_loading_move;
- m_set_extruder_trimpot = config.high_current_on_filament_swap;
+ m_cooling_tube_retraction = float(config.cooling_tube_retraction);
+ m_cooling_tube_length = float(config.cooling_tube_length);
+ m_parking_pos_retraction = float(config.parking_pos_retraction);
+ m_extra_loading_move = float(config.extra_loading_move);
+ m_set_extruder_trimpot = config.high_current_on_filament_swap;
}
// Calculate where the priming lines should be - very naive test not detecting parallelograms or custom shapes
const std::vector<Vec2d>& bed_points = config.bed_shape.values;
m_bed_shape = (bed_points.size() == 4 ? RectangularBed : CircularBed);
- m_bed_width = BoundingBoxf(bed_points).size().x();
+ m_bed_width = float(BoundingBoxf(bed_points).size().x());
}
@@ -518,21 +505,21 @@ void WipeTower::set_extruder(size_t idx, const PrintConfig& config)
// If this is a single extruder MM printer, we will use all the SE-specific config values.
// Otherwise, the defaults will be used to turn off the SE stuff.
if (m_semm) {
- m_filpar[idx].loading_speed = config.filament_loading_speed.get_at(idx);
- m_filpar[idx].loading_speed_start = config.filament_loading_speed_start.get_at(idx);
- m_filpar[idx].unloading_speed = config.filament_unloading_speed.get_at(idx);
- m_filpar[idx].unloading_speed_start = config.filament_unloading_speed_start.get_at(idx);
- m_filpar[idx].delay = config.filament_toolchange_delay.get_at(idx);
+ m_filpar[idx].loading_speed = float(config.filament_loading_speed.get_at(idx));
+ m_filpar[idx].loading_speed_start = float(config.filament_loading_speed_start.get_at(idx));
+ m_filpar[idx].unloading_speed = float(config.filament_unloading_speed.get_at(idx));
+ m_filpar[idx].unloading_speed_start = float(config.filament_unloading_speed_start.get_at(idx));
+ m_filpar[idx].delay = float(config.filament_toolchange_delay.get_at(idx));
m_filpar[idx].cooling_moves = config.filament_cooling_moves.get_at(idx);
- m_filpar[idx].cooling_initial_speed = config.filament_cooling_initial_speed.get_at(idx);
- m_filpar[idx].cooling_final_speed = config.filament_cooling_final_speed.get_at(idx);
+ m_filpar[idx].cooling_initial_speed = float(config.filament_cooling_initial_speed.get_at(idx));
+ m_filpar[idx].cooling_final_speed = float(config.filament_cooling_final_speed.get_at(idx));
}
m_filpar[idx].filament_area = float((M_PI/4.f) * pow(config.filament_diameter.get_at(idx), 2)); // all extruders are assumed to have the same filament diameter at this point
- float nozzle_diameter = config.nozzle_diameter.get_at(idx);
+ float nozzle_diameter = float(config.nozzle_diameter.get_at(idx));
m_filpar[idx].nozzle_diameter = nozzle_diameter; // to be used in future with (non-single) multiextruder MM
- float max_vol_speed = config.filament_max_volumetric_speed.get_at(idx);
+ float max_vol_speed = float(config.filament_max_volumetric_speed.get_at(idx));
if (max_vol_speed!= 0.f)
m_filpar[idx].max_e_speed = (max_vol_speed / filament_area());
@@ -561,7 +548,7 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
const std::vector<unsigned int> &tools,
// If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower.
// If false, the last priming are will be large enough to wipe the last extruder sufficiently.
- bool last_wipe_inside_wipe_tower)
+ bool /*last_wipe_inside_wipe_tower*/)
{
this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false);
this->m_current_tool = tools.front();
@@ -581,7 +568,7 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
// Iterate over all priming toolchanges and push respective ToolChangeResults into results vector.
for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) {
- int old_tool = m_current_tool;
+ size_t old_tool = m_current_tool;
WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
writer.set_extrusion_flow(m_extrusion_flow)
@@ -630,8 +617,8 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
ToolChangeResult result;
result.priming = true;
- result.initial_tool = old_tool;
- result.new_tool = m_current_tool;
+ result.initial_tool = int(old_tool);
+ result.new_tool = int(m_current_tool);
result.print_z = this->m_z_pos;
result.layer_height = this->m_layer_height;
result.gcode = writer.gcode();
@@ -666,12 +653,12 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
return results;
}
-WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_in_layer)
+WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool last_in_layer)
{
if ( m_print_brim )
return toolchange_Brim();
- int old_tool = m_current_tool;
+ size_t old_tool = m_current_tool;
float wipe_area = 0.f;
bool last_change_in_layer = false;
@@ -696,7 +683,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_
box_coordinates cleaning_box(
Vec2f(m_perimeter_width / 2.f, m_perimeter_width / 2.f),
m_wipe_tower_width - m_perimeter_width,
- (tool != (unsigned int)(-1) ? /*m_layer_info->depth*/wipe_area+m_depth_traversed-0.5*m_perimeter_width
+ (tool != (unsigned int)(-1) ? /*m_layer_info->depth*/wipe_area+m_depth_traversed-0.5f*m_perimeter_width
: m_wipe_tower_depth-m_perimeter_width));
WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
@@ -764,8 +751,8 @@ WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_
ToolChangeResult result;
result.priming = false;
- result.initial_tool = old_tool;
- result.new_tool = m_current_tool;
+ result.initial_tool = int(old_tool);
+ result.new_tool = int(m_current_tool);
result.print_z = this->m_z_pos;
result.layer_height = this->m_layer_height;
result.gcode = writer.gcode();
@@ -778,7 +765,7 @@ WipeTower::ToolChangeResult WipeTower::tool_change(unsigned int tool, bool last_
WipeTower::ToolChangeResult WipeTower::toolchange_Brim(bool sideOnly, float y_offset)
{
- int old_tool = m_current_tool;
+ size_t old_tool = m_current_tool;
const box_coordinates wipeTower_box(
Vec2f::Zero(),
@@ -802,7 +789,7 @@ WipeTower::ToolChangeResult WipeTower::toolchange_Brim(bool sideOnly, float y_of
// Extrude 4 rounds of a brim around the future wipe tower.
box_coordinates box(wipeTower_box);
for (size_t i = 0; i < 4; ++ i) {
- box.expand(m_perimeter_width - m_layer_height*(1.f-M_PI_4)); // the brim shall have 'normal' spacing with no extra void space
+ box.expand(m_perimeter_width - m_layer_height*float(1.-M_PI_4)); // the brim shall have 'normal' spacing with no extra void space
writer.travel (box.ld, 7000)
.extrude(box.lu, 2100).extrude(box.ru)
.extrude(box.rd ).extrude(box.ld);
@@ -822,8 +809,8 @@ WipeTower::ToolChangeResult WipeTower::toolchange_Brim(bool sideOnly, float y_of
ToolChangeResult result;
result.priming = false;
- result.initial_tool = old_tool;
- result.new_tool = m_current_tool;
+ result.initial_tool = int(old_tool);
+ result.new_tool = int(m_current_tool);
result.print_z = this->m_z_pos;
result.layer_height = this->m_layer_height;
result.gcode = writer.gcode();
@@ -911,8 +898,8 @@ void WipeTower::toolchange_Unload(
const float x = volume_to_length(m_filpar[m_current_tool].ramming_speed[i] * 0.25f, line_width, m_layer_height);
const float e = m_filpar[m_current_tool].ramming_speed[i] * 0.25f / filament_area(); // transform volume per sec to E move;
const float dist = std::min(x - e_done, remaining); // distance to travel for either the next 0.25s, or to the next turnaround
- const float actual_time = dist/x * 0.25;
- writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0, 0, e * (dist / x), dist / (actual_time / 60.));
+ const float actual_time = dist/x * 0.25f;
+ writer.ram(writer.x(), writer.x() + (m_left_to_right ? 1.f : -1.f) * dist, 0.f, 0.f, e * (dist / x), dist / (actual_time / 60.f));
remaining -= dist;
if (remaining < WT_EPSILON) { // we reached a turning point
@@ -995,8 +982,8 @@ void WipeTower::toolchange_Unload(
// Change the tool, set a speed override for soluble and flex materials.
void WipeTower::toolchange_Change(
WipeTowerWriter &writer,
- const unsigned int new_tool,
- const std::string& new_material)
+ const size_t new_tool,
+ const std::string& new_material)
{
// Ask the writer about how much of the old filament we consumed:
if (m_current_tool < m_used_filament_length.size())
@@ -1091,21 +1078,21 @@ void WipeTower::toolchange_Wipe(
float traversed_x = writer.x();
if (m_left_to_right)
- writer.extrude(xr - (i % 4 == 0 ? 0 : 1.5*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff);
+ writer.extrude(xr - (i % 4 == 0 ? 0 : 1.5f*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff);
else
- writer.extrude(xl + (i % 4 == 1 ? 0 : 1.5*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff);
+ writer.extrude(xl + (i % 4 == 1 ? 0 : 1.5f*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff);
- if (writer.y()+EPSILON > cleaning_box.lu.y()-0.5f*m_perimeter_width)
+ if (writer.y()+float(EPSILON) > cleaning_box.lu.y()-0.5f*m_perimeter_width)
break; // in case next line would not fit
traversed_x -= writer.x();
- x_to_wipe -= fabs(traversed_x);
+ x_to_wipe -= std::abs(traversed_x);
if (x_to_wipe < WT_EPSILON) {
- writer.travel(m_left_to_right ? xl + 1.5*m_perimeter_width : xr - 1.5*m_perimeter_width, writer.y(), 7200);
+ writer.travel(m_left_to_right ? xl + 1.5f*m_perimeter_width : xr - 1.5f*m_perimeter_width, writer.y(), 7200);
break;
}
// stepping to the next line:
- writer.extrude(writer.x() + (i % 4 == 0 ? -1.f : (i % 4 == 1 ? 1.f : 0.f)) * 1.5*m_perimeter_width, writer.y() + dy);
+ writer.extrude(writer.x() + (i % 4 == 0 ? -1.f : (i % 4 == 1 ? 1.f : 0.f)) * 1.5f*m_perimeter_width, writer.y() + dy);
m_left_to_right = !m_left_to_right;
}
@@ -1128,7 +1115,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
// Otherwise the caller would likely travel to the wipe tower in vain.
assert(! this->layer_finished());
- int old_tool = m_current_tool;
+ size_t old_tool = m_current_tool;
WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar);
writer.set_extrusion_flow(m_extrusion_flow)
@@ -1188,7 +1175,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
writer.travel(fill_box.ld + Vec2f(m_perimeter_width * 2, 0.f))
.extrude(fill_box.lu + Vec2f(m_perimeter_width * 2, 0.f), 2900 * speed_factor);
- const int n = 1+(right-left)/(m_bridging);
+ const int n = 1+int((right-left)/m_bridging);
const float dx = (right-left)/n;
for (int i=1;i<=n;++i) {
float x=left+dx*i;
@@ -1211,8 +1198,8 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
ToolChangeResult result;
result.priming = false;
- result.initial_tool = old_tool;
- result.new_tool = m_current_tool;
+ result.initial_tool = int(old_tool);
+ result.new_tool = int(m_current_tool);
result.print_z = this->m_z_pos;
result.layer_height = this->m_layer_height;
result.gcode = writer.gcode();
@@ -1267,7 +1254,7 @@ void WipeTower::plan_tower()
for (auto& layer : m_plan)
layer.depth = 0.f;
- for (int layer_index = m_plan.size() - 1; layer_index >= 0; --layer_index)
+ for (int layer_index = int(m_plan.size()) - 1; layer_index >= 0; --layer_index)
{
float this_layer_depth = std::max(m_plan[layer_index].depth, m_plan[layer_index].toolchanges_depth());
m_plan[layer_index].depth = this_layer_depth;
diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp
index fab75c5e6..5477aa609 100644
--- a/src/libslic3r/GCode/WipeTower.hpp
+++ b/src/libslic3r/GCode/WipeTower.hpp
@@ -7,21 +7,21 @@
#include <utility>
#include <algorithm>
-#include "libslic3r/PrintConfig.hpp"
-
+#include "libslic3r/Point.hpp"
namespace Slic3r
{
class WipeTowerWriter;
-
+class PrintConfig;
+enum GCodeFlavor : unsigned char;
class WipeTower
{
public:
struct Extrusion
- {
+ {
Extrusion(const Vec2f &pos, float width, unsigned int tool) : pos(pos), width(width), tool(tool) {}
// End position of this extrusion.
Vec2f pos;
@@ -79,7 +79,6 @@ public:
// width -- width of wipe tower in mm ( default 60 mm - leave as it is )
// wipe_area -- space available for one toolchange in mm
WipeTower(const PrintConfig& config, const std::vector<std::vector<float>>& wiping_matrix, size_t initial_tool);
- virtual ~WipeTower() {}
// Set the extruder properties.
@@ -149,7 +148,7 @@ public:
// Returns gcode for a toolchange and a final print head position.
// On the first layer, extrude a brim around the future wipe tower first.
- ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer);
+ ToolChangeResult tool_change(size_t new_tool, bool last_in_layer);
// Fill the unfilled space with a sparse infill.
// Call this method only if layer_finished() is false.
@@ -195,7 +194,7 @@ private:
const bool m_peters_wipe_tower = false; // sparse wipe tower inspired by Peter's post processor - not finished yet
const float Width_To_Nozzle_Ratio = 1.25f; // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust
const float WT_EPSILON = 1e-3f;
- const float filament_area() const {
+ float filament_area() const {
return m_filpar[0].filament_area; // all extruders are assumed to have the same filament diameter at this point
}
@@ -244,7 +243,7 @@ private:
bool m_print_brim = true;
// A fill-in direction (positive Y, negative Y) alternates with each layer.
wipe_shape m_current_shape = SHAPE_NORMAL;
- unsigned int m_current_tool = 0;
+ size_t m_current_tool = 0;
const std::vector<std::vector<float>> wipe_volumes;
float m_depth_traversed = 0.f; // Current y position at the wipe tower.
@@ -309,13 +308,13 @@ private:
// to store information about tool changes for a given layer
struct WipeTowerInfo{
struct ToolChange {
- unsigned int old_tool;
- unsigned int new_tool;
+ size_t old_tool;
+ size_t new_tool;
float required_depth;
float ramming_depth;
float first_wipe_line;
float wipe_volume;
- ToolChange(unsigned int old, unsigned int newtool, float depth=0.f, float ramming_depth=0.f, float fwl=0.f, float wv=0.f)
+ ToolChange(size_t old, size_t newtool, float depth=0.f, float ramming_depth=0.f, float fwl=0.f, float wv=0.f)
: old_tool{old}, new_tool{newtool}, required_depth{depth}, ramming_depth{ramming_depth}, first_wipe_line{fwl}, wipe_volume{wv} {}
};
float z; // z position of the layer
@@ -350,7 +349,7 @@ private:
void toolchange_Change(
WipeTowerWriter &writer,
- const unsigned int new_tool,
+ const size_t new_tool,
const std::string& new_material);
void toolchange_Load(
diff --git a/src/libslic3r/GCodeTimeEstimator.cpp b/src/libslic3r/GCodeTimeEstimator.cpp
index 00b409344..4693ba9e6 100644
--- a/src/libslic3r/GCodeTimeEstimator.cpp
+++ b/src/libslic3r/GCodeTimeEstimator.cpp
@@ -173,9 +173,7 @@ namespace Slic3r {
const std::string GCodeTimeEstimator::Normal_Last_M73_Output_Placeholder_Tag = "; _TE_NORMAL_LAST_M73_OUTPUT_PLACEHOLDER";
const std::string GCodeTimeEstimator::Silent_Last_M73_Output_Placeholder_Tag = "; _TE_SILENT_LAST_M73_OUTPUT_PLACEHOLDER";
- // temporary human readable form to use until not removed from gcode by the new post-process method
const std::string GCodeTimeEstimator::Color_Change_Tag = "PRINT_COLOR_CHANGE";
-// const std::string GCodeTimeEstimator::Color_Change_Tag = "_TE_COLOR_CHANGE";
GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
: m_mode(mode)
@@ -273,130 +271,138 @@ namespace Slic3r {
#endif // ENABLE_MOVE_STATS
}
- bool GCodeTimeEstimator::post_process_remaining_times(const std::string& filename, float interval)
+ bool GCodeTimeEstimator::post_process(const std::string& filename, float interval_sec, const PostProcessData* const normal_mode, const PostProcessData* const silent_mode)
{
boost::nowide::ifstream in(filename);
if (!in.good())
- throw std::runtime_error(std::string("Remaining times export failed.\nCannot open file for reading.\n"));
+ throw std::runtime_error(std::string("Time estimator post process export failed.\nCannot open file for reading.\n"));
- std::string path_tmp = filename + ".times";
+ std::string path_tmp = filename + ".postprocess";
FILE* out = boost::nowide::fopen(path_tmp.c_str(), "wb");
if (out == nullptr)
- throw std::runtime_error(std::string("Remaining times export failed.\nCannot open file for writing.\n"));
+ throw std::runtime_error(std::string("Time estimator post process export failed.\nCannot open file for writing.\n"));
- std::string time_mask;
- switch (m_mode)
- {
- default:
- case Normal:
- {
- time_mask = "M73 P%s R%s\n";
- break;
- }
- case Silent:
- {
- time_mask = "M73 Q%s S%s\n";
- break;
- }
- }
+ std::string normal_time_mask = "M73 P%s R%s\n";
+ std::string silent_time_mask = "M73 Q%s S%s\n";
+ char line_M73[64];
- unsigned int g1_lines_count = 0;
- float last_recorded_time = 0.0f;
std::string gcode_line;
// buffer line to export only when greater than 64K to reduce writing calls
std::string export_line;
- char time_line[64];
- G1LineIdToBlockIdMap::const_iterator it_line_id = m_g1_line_ids.begin();
- while (std::getline(in, gcode_line))
+
+ // helper function to write to disk
+ auto write_string = [&](const std::string& str) {
+ fwrite((const void*)export_line.c_str(), 1, export_line.length(), out);
+ if (ferror(out))
+ {
+ in.close();
+ fclose(out);
+ boost::nowide::remove(path_tmp.c_str());
+ throw std::runtime_error(std::string("Time estimator post process export failed.\nIs the disk full?\n"));
+ }
+ export_line.clear();
+ };
+
+ GCodeReader parser;
+ unsigned int g1_lines_count = 0;
+ int normal_g1_line_id = 0;
+ float normal_last_recorded_time = 0.0f;
+ int silent_g1_line_id = 0;
+ float silent_last_recorded_time = 0.0f;
+
+ // helper function to process g1 lines
+ auto process_g1_line = [&](const PostProcessData* const data, const GCodeReader::GCodeLine& line, int& g1_line_id, float& last_recorded_time, const std::string& time_mask) {
+ if (data == nullptr)
+ return;
+
+ assert((g1_line_id >= (int)data->g1_line_ids.size()) || (data->g1_line_ids[g1_line_id].first >= g1_lines_count));
+ const Block* block = nullptr;
+ const G1LineIdToBlockId& map_item = data->g1_line_ids[g1_line_id];
+ if ((g1_line_id < (int)data->g1_line_ids.size()) && (map_item.first == g1_lines_count))
+ {
+ if (line.has_e() && (map_item.second < (unsigned int)data->blocks.size()))
+ block = &data->blocks[map_item.second];
+ ++g1_line_id;
+ }
+
+ if ((block != nullptr) && (block->elapsed_time != -1.0f))
+ {
+ float block_remaining_time = data->time - block->elapsed_time;
+ if (std::abs(last_recorded_time - block_remaining_time) > interval_sec)
+ {
+ sprintf(line_M73, time_mask.c_str(), std::to_string((int)(100.0f * block->elapsed_time / data->time)).c_str(), _get_time_minutes(block_remaining_time).c_str());
+ gcode_line += line_M73;
+
+ last_recorded_time = block_remaining_time;
+ }
+ }
+ };
+
+ while (std::getline(in, gcode_line))
{
if (!in.good())
{
fclose(out);
- throw std::runtime_error(std::string("Remaining times export failed.\nError while reading from file.\n"));
+ throw std::runtime_error(std::string("Time estimator post process export failed.\nError while reading from file.\n"));
}
+ // check tags
+ // remove color change tag
+ if (gcode_line == "; " + Color_Change_Tag)
+ continue;
+
// replaces placeholders for initial line M73 with the real lines
- if (((m_mode == Normal) && (gcode_line == Normal_First_M73_Output_Placeholder_Tag)) ||
- ((m_mode == Silent) && (gcode_line == Silent_First_M73_Output_Placeholder_Tag)))
+ if ((normal_mode != nullptr) && (gcode_line == Normal_First_M73_Output_Placeholder_Tag))
{
- sprintf(time_line, time_mask.c_str(), "0", _get_time_minutes(m_time).c_str());
- gcode_line = time_line;
+ sprintf(line_M73, normal_time_mask.c_str(), "0", _get_time_minutes(normal_mode->time).c_str());
+ gcode_line = line_M73;
+ }
+ else if ((silent_mode != nullptr) && (gcode_line == Silent_First_M73_Output_Placeholder_Tag))
+ {
+ sprintf(line_M73, silent_time_mask.c_str(), "0", _get_time_minutes(silent_mode->time).c_str());
+ gcode_line = line_M73;
}
// replaces placeholders for final line M73 with the real lines
- else if (((m_mode == Normal) && (gcode_line == Normal_Last_M73_Output_Placeholder_Tag)) ||
- ((m_mode == Silent) && (gcode_line == Silent_Last_M73_Output_Placeholder_Tag)))
+ else if ((normal_mode != nullptr) && (gcode_line == Normal_Last_M73_Output_Placeholder_Tag))
+ {
+ sprintf(line_M73, normal_time_mask.c_str(), "100", "0");
+ gcode_line = line_M73;
+ }
+ else if ((silent_mode != nullptr) && (gcode_line == Silent_Last_M73_Output_Placeholder_Tag))
{
- sprintf(time_line, time_mask.c_str(), "100", "0");
- gcode_line = time_line;
+ sprintf(line_M73, silent_time_mask.c_str(), "100", "0");
+ gcode_line = line_M73;
}
else
- gcode_line += "\n";
-
+ gcode_line += "\n";
// add remaining time lines where needed
- m_parser.parse_line(gcode_line,
- [this, &it_line_id, &g1_lines_count, &last_recorded_time, &time_line, &gcode_line, time_mask, interval](GCodeReader& reader, const GCodeReader::GCodeLine& line)
- {
- if (line.cmd_is("G1"))
+ parser.parse_line(gcode_line,
+ [&](GCodeReader& reader, const GCodeReader::GCodeLine& line)
{
- ++g1_lines_count;
-
- assert(it_line_id == m_g1_line_ids.end() || it_line_id->first >= g1_lines_count);
-
- const Block *block = nullptr;
- if (it_line_id != m_g1_line_ids.end() && it_line_id->first == g1_lines_count) {
- if (line.has_e() && it_line_id->second < (unsigned int)m_blocks.size())
- block = &m_blocks[it_line_id->second];
- ++it_line_id;
- }
-
- if (block != nullptr && block->elapsed_time != -1.0f) {
- float block_remaining_time = m_time - block->elapsed_time;
- if (std::abs(last_recorded_time - block_remaining_time) > interval)
- {
- sprintf(time_line, time_mask.c_str(), std::to_string((int)(100.0f * block->elapsed_time / m_time)).c_str(), _get_time_minutes(block_remaining_time).c_str());
- gcode_line += time_line;
-
- last_recorded_time = block_remaining_time;
- }
+ if (line.cmd_is("G1"))
+ {
+ ++g1_lines_count;
+ process_g1_line(silent_mode, line, silent_g1_line_id, silent_last_recorded_time, silent_time_mask);
+ process_g1_line(normal_mode, line, normal_g1_line_id, normal_last_recorded_time, normal_time_mask);
}
- }
- });
+ });
export_line += gcode_line;
if (export_line.length() > 65535)
- {
- fwrite((const void*)export_line.c_str(), 1, export_line.length(), out);
- if (ferror(out))
- {
- in.close();
- fclose(out);
- boost::nowide::remove(path_tmp.c_str());
- throw std::runtime_error(std::string("Remaining times export failed.\nIs the disk full?\n"));
- }
- export_line.clear();
- }
+ write_string(export_line);
}
- if (export_line.length() > 0)
- {
- fwrite((const void*)export_line.c_str(), 1, export_line.length(), out);
- if (ferror(out))
- {
- in.close();
- fclose(out);
- boost::nowide::remove(path_tmp.c_str());
- throw std::runtime_error(std::string("Remaining times export failed.\nIs the disk full?\n"));
- }
- }
+ if (!export_line.empty())
+ write_string(export_line);
fclose(out);
in.close();
if (rename_file(path_tmp, filename))
throw std::runtime_error(std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + filename + '\n' +
- "Is " + path_tmp + " locked?" + '\n');
+ "Is " + path_tmp + " locked?" + '\n');
return true;
}
diff --git a/src/libslic3r/GCodeTimeEstimator.hpp b/src/libslic3r/GCodeTimeEstimator.hpp
index dd5d14b57..d9f3bc211 100644
--- a/src/libslic3r/GCodeTimeEstimator.hpp
+++ b/src/libslic3r/GCodeTimeEstimator.hpp
@@ -213,9 +213,19 @@ namespace Slic3r {
typedef std::map<Block::EMoveType, MoveStats> MovesStatsMap;
#endif // ENABLE_MOVE_STATS
+ public:
typedef std::pair<unsigned int, unsigned int> G1LineIdToBlockId;
typedef std::vector<G1LineIdToBlockId> G1LineIdToBlockIdMap;
+ struct PostProcessData
+ {
+ const G1LineIdToBlockIdMap& g1_line_ids;
+ const BlocksList& blocks;
+ float time;
+
+ PostProcessData(const G1LineIdToBlockIdMap& g1_line_ids, const BlocksList& blocks, float time) : g1_line_ids(g1_line_ids), blocks(blocks), time(time) {}
+ };
+
private:
EMode m_mode;
GCodeReader m_parser;
@@ -263,11 +273,12 @@ namespace Slic3r {
void calculate_time_from_lines(const std::vector<std::string>& gcode_lines);
// Process the gcode contained in the file with the given filename,
- // placing in it new lines (M73) containing the remaining time, at the given interval in seconds
- // and saving the result back in the same file
- // This time estimator should have been already used to calculate the time estimate for the gcode
- // contained in the given file before to call this method
- bool post_process_remaining_times(const std::string& filename, float interval_sec);
+ // replacing placeholders with correspondent new lines M73
+ // placing new lines M73 (containing the remaining time) where needed (in dependence of the given interval in seconds)
+ // and removing working tags (as those used for color changes)
+ // if normal_mode == nullptr no M73 line will be added for normal mode
+ // if silent_mode == nullptr no M73 line will be added for silent mode
+ static bool post_process(const std::string& filename, float interval_sec, const PostProcessData* const normal_mode, const PostProcessData* const silent_mode);
// Set current position on the given axis with the given value
void set_axis_position(EAxis axis, float position);
@@ -362,6 +373,8 @@ namespace Slic3r {
// Return an estimate of the memory consumed by the time estimator.
size_t memory_used() const;
+ PostProcessData get_post_process_data() const { return PostProcessData(m_g1_line_ids, m_blocks, m_time); }
+
private:
void _reset();
void _reset_time();
diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp
index a8160867a..4ac64b777 100644
--- a/src/libslic3r/Layer.cpp
+++ b/src/libslic3r/Layer.cpp
@@ -121,7 +121,6 @@ void Layer::make_perimeters()
for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it) {
LayerRegion* other_layerm = *it;
const PrintRegionConfig &other_config = other_layerm->region()->config();
-
if (config.perimeter_extruder == other_config.perimeter_extruder
&& config.perimeters == other_config.perimeters
&& config.perimeter_speed == other_config.perimeter_speed
@@ -130,7 +129,8 @@ void Layer::make_perimeters()
&& config.overhangs == other_config.overhangs
&& config.opt_serialize("perimeter_extrusion_width") == other_config.opt_serialize("perimeter_extrusion_width")
&& config.thin_walls == other_config.thin_walls
- && config.external_perimeters_first == other_config.external_perimeters_first) {
+ && config.external_perimeters_first == other_config.external_perimeters_first
+ && config.infill_overlap == other_config.infill_overlap) {
layerms.push_back(other_layerm);
done[it - m_regions.begin()] = true;
}
@@ -142,12 +142,17 @@ void Layer::make_perimeters()
(*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
} else {
SurfaceCollection new_slices;
+ // Use the region with highest infill rate, as the make_perimeters() function below decides on the gap fill based on the infill existence.
+ LayerRegion *layerm_config = layerms.front();
{
// group slices (surfaces) according to number of extra perimeters
std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ]
- for (LayerRegion *layerm : layerms)
+ for (LayerRegion *layerm : layerms) {
for (Surface &surface : layerm->slices.surfaces)
slices[surface.extra_perimeters].emplace_back(surface);
+ if (layerm->region()->config().fill_density > layerm_config->region()->config().fill_density)
+ layerm_config = layerm;
+ }
// merge the surfaces assigned to each group
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
new_slices.append(union_ex(surfaces_with_extra_perimeters.second, true), surfaces_with_extra_perimeters.second.front());
@@ -155,7 +160,7 @@ void Layer::make_perimeters()
// make perimeters
SurfaceCollection fill_surfaces;
- (*layerm)->make_perimeters(new_slices, &fill_surfaces);
+ layerm_config->make_perimeters(new_slices, &fill_surfaces);
// assign fill_surfaces to each layer
if (!fill_surfaces.surfaces.empty()) {
@@ -171,21 +176,6 @@ void Layer::make_perimeters()
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << " - Done";
}
-void Layer::make_fills()
-{
- #ifdef SLIC3R_DEBUG
- printf("Making fills for layer " PRINTF_ZU "\n", this->id());
- #endif
- for (LayerRegion *layerm : m_regions) {
- layerm->fills.clear();
- make_fill(*layerm, layerm->fills);
-#ifndef NDEBUG
- for (size_t i = 0; i < layerm->fills.entities.size(); ++ i)
- assert(dynamic_cast<ExtrusionEntityCollection*>(layerm->fills.entities[i]) != NULL);
-#endif
- }
-}
-
void Layer::export_region_slices_to_svg(const char *path) const
{
BoundingBox bbox;
diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp
index 6297b49d0..555017207 100644
--- a/src/libslic3r/Layer.hpp
+++ b/src/libslic3r/Layer.hpp
@@ -62,7 +62,7 @@ public:
void slices_to_fill_surfaces_clipped();
void prepare_fill_surfaces();
void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces);
- void process_external_surfaces(const Layer* lower_layer);
+ void process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered);
double infill_area_threshold() const;
// Trim surfaces by trimming polygons. Used by the elephant foot compensation at the 1st layer.
void trim_surfaces(const Polygons &trimming_polygons);
diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp
index caf8dc20f..6fc0b4e37 100644
--- a/src/libslic3r/LayerRegion.cpp
+++ b/src/libslic3r/LayerRegion.cpp
@@ -86,11 +86,12 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
//#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 1.5
#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtSquare, 0.
-void LayerRegion::process_external_surfaces(const Layer* lower_layer)
+void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered)
{
- const Surfaces &surfaces = this->fill_surfaces.surfaces;
- const double margin = scale_(EXTERNAL_INFILL_MARGIN);
-
+ const Surfaces &surfaces = this->fill_surfaces.surfaces;
+ const bool has_infill = this->region()->config().fill_density.value > 0.;
+ const float margin = float(scale_(EXTERNAL_INFILL_MARGIN));
+
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
export_region_fill_surfaces_to_svg_debug("3_process_external_surfaces-initial");
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
@@ -106,36 +107,44 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
// Internal surfaces, not grown.
Surfaces internal;
// Areas, where an infill of various types (top, bottom, bottom bride, sparse, void) could be placed.
- //FIXME if non zero infill, then fill_boundaries could be cheaply initialized from layerm->fill_expolygons.
- Polygons fill_boundaries;
+ Polygons fill_boundaries = to_polygons(this->fill_expolygons);
+ Polygons lower_layer_covered_tmp;
// Collect top surfaces and internal surfaces.
// Collect fill_boundaries: If we're slicing with no infill, we can't extend external surfaces over non-existent infill.
// This loop destroys the surfaces (aliasing this->fill_surfaces.surfaces) by moving into top/internal/fill_boundaries!
+
{
- // bottom_polygons are used to trim inflated top surfaces.
- fill_boundaries.reserve(number_polygons(surfaces));
- bool has_infill = this->region()->config().fill_density.value > 0.;
+ // Voids are sparse infills if infill rate is zero.
+ Polygons voids;
for (const Surface &surface : this->fill_surfaces.surfaces) {
if (surface.surface_type == stTop) {
// Collect the top surfaces, inflate them and trim them by the bottom surfaces.
// This gives the priority to bottom surfaces.
- surfaces_append(top, offset_ex(surface.expolygon, float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
- } else if (surface.surface_type == stBottom || (surface.surface_type == stBottomBridge && lower_layer == NULL)) {
+ surfaces_append(top, offset_ex(surface.expolygon, margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
+ } else if (surface.surface_type == stBottom || (surface.surface_type == stBottomBridge && lower_layer == nullptr)) {
// Grown by 3mm.
- surfaces_append(bottom, offset_ex(surface.expolygon, float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
+ surfaces_append(bottom, offset_ex(surface.expolygon, margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS), surface);
} else if (surface.surface_type == stBottomBridge) {
if (! surface.empty())
- bridges.push_back(surface);
+ bridges.emplace_back(surface);
+ }
+ if (surface.is_internal()) {
+ assert(surface.surface_type == stInternal);
+ if (! has_infill && lower_layer != nullptr)
+ polygons_append(voids, surface.expolygon);
+ internal.emplace_back(std::move(surface));
+ }
+ }
+ if (! has_infill && lower_layer != nullptr && ! voids.empty()) {
+ // Remove voids from fill_boundaries, that are not supported by the layer below.
+ if (lower_layer_covered == nullptr) {
+ lower_layer_covered = &lower_layer_covered_tmp;
+ lower_layer_covered_tmp = to_polygons(lower_layer->slices.expolygons);
}
- bool internal_surface = surface.surface_type != stTop && ! surface.is_bottom();
- if (has_infill || surface.surface_type != stInternal) {
- if (internal_surface)
- // Make a copy as the following line uses the move semantics.
- internal.push_back(surface);
- polygons_append(fill_boundaries, std::move(surface.expolygon));
- } else if (internal_surface)
- internal.push_back(std::move(surface));
+ if (! lower_layer_covered->empty())
+ voids = diff(voids, *lower_layer_covered);
+ fill_boundaries = diff(fill_boundaries, voids);
}
}
@@ -184,9 +193,9 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
break;
}
// Grown by 3mm.
- Polygons polys = offset(to_polygons(bridges[i].expolygon), float(margin), EXTERNAL_SURFACES_OFFSET_PARAMETERS);
+ Polygons polys = offset(to_polygons(bridges[i].expolygon), margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS);
if (idx_island == -1) {
- printf("Bridge did not fall into the source region!\r\n");
+ BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!";
} else {
// Found an island, to which this bridge region belongs. Trim it,
polys = intersection(polys, to_polygons(fill_boundaries_ex[idx_island]));
@@ -356,26 +365,23 @@ void LayerRegion::prepare_fill_surfaces()
// if no solid layers are requested, turn top/bottom surfaces to internal
if (this->region()->config().top_solid_layers == 0) {
- for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
- if (surface->surface_type == stTop)
- surface->surface_type = (this->layer()->object()->config().infill_only_where_needed) ?
- stInternalVoid : stInternal;
+ for (Surface &surface : this->fill_surfaces.surfaces)
+ if (surface.is_top())
+ surface.surface_type = this->layer()->object()->config().infill_only_where_needed ? stInternalVoid : stInternal;
}
if (this->region()->config().bottom_solid_layers == 0) {
- for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
- if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge)
- surface->surface_type = stInternal;
- }
+ for (Surface &surface : this->fill_surfaces.surfaces)
+ if (surface.is_bottom()) // (surface.surface_type == stBottom)
+ surface.surface_type = stInternal;
}
-
+
// turn too small internal regions into solid regions according to the user setting
if (this->region()->config().fill_density.value > 0) {
// scaling an area requires two calls!
double min_area = scale_(scale_(this->region()->config().solid_infill_below_area.value));
- for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
- if (surface->surface_type == stInternal && surface->area() <= min_area)
- surface->surface_type = stInternalSolid;
- }
+ for (Surface &surface : this->fill_surfaces.surfaces)
+ if (surface.surface_type == stInternal && surface.area() <= min_area)
+ surface.surface_type = stInternalSolid;
}
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp
index 422467e08..19f032b1c 100644
--- a/src/libslic3r/Model.hpp
+++ b/src/libslic3r/Model.hpp
@@ -674,7 +674,7 @@ private:
explicit ModelInstance(ModelObject* object) : print_volume_state(PVS_Inside), printable(true), object(object) { assert(this->id().valid()); }
// Constructor, which assigns a new unique ID.
explicit ModelInstance(ModelObject *object, const ModelInstance &other) :
- m_transformation(other.m_transformation), print_volume_state(PVS_Inside), printable(true), object(object) {assert(this->id().valid() && this->id() != other.id());}
+ m_transformation(other.m_transformation), print_volume_state(PVS_Inside), printable(other.printable), object(object) { assert(this->id().valid() && this->id() != other.id()); }
explicit ModelInstance(ModelInstance &&rhs) = delete;
ModelInstance& operator=(const ModelInstance &rhs) = delete;
diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp
index 4dac192ad..0c16f4a1d 100644
--- a/src/libslic3r/PerimeterGenerator.cpp
+++ b/src/libslic3r/PerimeterGenerator.cpp
@@ -6,21 +6,240 @@
namespace Slic3r {
+static ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, Flow &flow, const float tolerance)
+{
+ ExtrusionPaths paths;
+ ExtrusionPath path(role);
+ ThickLines lines = thick_polyline.thicklines();
+
+ for (int i = 0; i < (int)lines.size(); ++i) {
+ const ThickLine& line = lines[i];
+
+ const coordf_t line_len = line.length();
+ if (line_len < SCALED_EPSILON) continue;
+
+ double thickness_delta = fabs(line.a_width - line.b_width);
+ if (thickness_delta > tolerance) {
+ const unsigned int segments = (unsigned int)ceil(thickness_delta / tolerance);
+ const coordf_t seg_len = line_len / segments;
+ Points pp;
+ std::vector<coordf_t> width;
+ {
+ pp.push_back(line.a);
+ width.push_back(line.a_width);
+ for (size_t j = 1; j < segments; ++j) {
+ pp.push_back((line.a.cast<double>() + (line.b - line.a).cast<double>().normalized() * (j * seg_len)).cast<coord_t>());
+
+ coordf_t w = line.a_width + (j*seg_len) * (line.b_width-line.a_width) / line_len;
+ width.push_back(w);
+ width.push_back(w);
+ }
+ pp.push_back(line.b);
+ width.push_back(line.b_width);
+
+ assert(pp.size() == segments + 1u);
+ assert(width.size() == segments*2);
+ }
+
+ // delete this line and insert new ones
+ lines.erase(lines.begin() + i);
+ for (size_t j = 0; j < segments; ++j) {
+ ThickLine new_line(pp[j], pp[j+1]);
+ new_line.a_width = width[2*j];
+ new_line.b_width = width[2*j+1];
+ lines.insert(lines.begin() + i + j, new_line);
+ }
+
+ -- i;
+ continue;
+ }
+
+ const double w = fmax(line.a_width, line.b_width);
+ if (path.polyline.points.empty()) {
+ path.polyline.append(line.a);
+ path.polyline.append(line.b);
+ // Convert from spacing to extrusion width based on the extrusion model
+ // of a square extrusion ended with semi circles.
+ flow.width = unscale<float>(w) + flow.height * float(1. - 0.25 * PI);
+ #ifdef SLIC3R_DEBUG
+ printf(" filling %f gap\n", flow.width);
+ #endif
+ path.mm3_per_mm = flow.mm3_per_mm();
+ path.width = flow.width;
+ path.height = flow.height;
+ } else {
+ thickness_delta = fabs(scale_(flow.width) - w);
+ if (thickness_delta <= tolerance) {
+ // the width difference between this line and the current flow width is
+ // within the accepted tolerance
+ path.polyline.append(line.b);
+ } else {
+ // we need to initialize a new line
+ paths.emplace_back(std::move(path));
+ path = ExtrusionPath(role);
+ -- i;
+ }
+ }
+ }
+ if (path.polyline.is_valid())
+ paths.emplace_back(std::move(path));
+ return paths;
+}
+
+static ExtrusionEntityCollection variable_width(const ThickPolylines& polylines, ExtrusionRole role, Flow flow)
+{
+ // This value determines granularity of adaptive width, as G-code does not allow
+ // variable extrusion within a single move; this value shall only affect the amount
+ // of segments, and any pruning shall be performed before we apply this tolerance.
+ ExtrusionEntityCollection coll;
+ const float tolerance = float(scale_(0.05));
+ for (const ThickPolyline &p : polylines) {
+ ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance);
+ // Append paths to collection.
+ if (! paths.empty()) {
+ if (paths.front().first_point() == paths.back().last_point())
+ coll.append(ExtrusionLoop(std::move(paths)));
+ else
+ coll.append(std::move(paths));
+ }
+ }
+ return coll;
+}
+
+// Hierarchy of perimeters.
+class PerimeterGeneratorLoop {
+public:
+ // Polygon of this contour.
+ Polygon polygon;
+ // Is it a contour or a hole?
+ // Contours are CCW oriented, holes are CW oriented.
+ bool is_contour;
+ // Depth in the hierarchy. External perimeter has depth = 0. An external perimeter could be both a contour and a hole.
+ unsigned short depth;
+ // Children contour, may be both CCW and CW oriented (outer contours or holes).
+ std::vector<PerimeterGeneratorLoop> children;
+
+ PerimeterGeneratorLoop(Polygon polygon, unsigned short depth, bool is_contour) :
+ polygon(polygon), is_contour(is_contour), depth(depth) {}
+ // External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
+ bool is_external() const { return this->depth == 0; }
+ // An island, which may have holes, but it does not have another internal island.
+ bool is_internal_contour() const;
+};
+
+typedef std::vector<PerimeterGeneratorLoop> PerimeterGeneratorLoops;
+
+static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perimeter_generator, const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls)
+{
+ // loops is an arrayref of ::Loop objects
+ // turn each one into an ExtrusionLoop object
+ ExtrusionEntityCollection coll;
+ for (const PerimeterGeneratorLoop &loop : loops) {
+ bool is_external = loop.is_external();
+
+ ExtrusionRole role;
+ ExtrusionLoopRole loop_role;
+ role = is_external ? erExternalPerimeter : erPerimeter;
+ if (loop.is_internal_contour()) {
+ // Note that we set loop role to ContourInternalPerimeter
+ // also when loop is both internal and external (i.e.
+ // there's only one contour loop).
+ loop_role = elrContourInternalPerimeter;
+ } else {
+ loop_role = elrDefault;
+ }
+
+ // detect overhanging/bridging perimeters
+ ExtrusionPaths paths;
+ if (perimeter_generator.config->overhangs && perimeter_generator.layer_id > 0
+ && !(perimeter_generator.object_config->support_material && perimeter_generator.object_config->support_material_contact_distance.value == 0)) {
+ // get non-overhang paths by intersecting this loop with the grown lower slices
+ extrusion_paths_append(
+ paths,
+ intersection_pl(loop.polygon, perimeter_generator.lower_slices_polygons()),
+ role,
+ is_external ? perimeter_generator.ext_mm3_per_mm() : perimeter_generator.mm3_per_mm(),
+ is_external ? perimeter_generator.ext_perimeter_flow.width : perimeter_generator.perimeter_flow.width,
+ (float)perimeter_generator.layer_height);
+
+ // get overhang paths by checking what parts of this loop fall
+ // outside the grown lower slices (thus where the distance between
+ // the loop centerline and original lower slices is >= half nozzle diameter
+ extrusion_paths_append(
+ paths,
+ diff_pl(loop.polygon, perimeter_generator.lower_slices_polygons()),
+ erOverhangPerimeter,
+ perimeter_generator.mm3_per_mm_overhang(),
+ perimeter_generator.overhang_flow.width,
+ perimeter_generator.overhang_flow.height);
+
+ // reapply the nearest point search for starting point
+ // We allow polyline reversal because Clipper may have randomly
+ // reversed polylines during clipping.
+ paths = (ExtrusionPaths)ExtrusionEntityCollection(paths).chained_path();
+ } else {
+ ExtrusionPath path(role);
+ path.polyline = loop.polygon.split_at_first_point();
+ path.mm3_per_mm = is_external ? perimeter_generator.ext_mm3_per_mm() : perimeter_generator.mm3_per_mm();
+ path.width = is_external ? perimeter_generator.ext_perimeter_flow.width : perimeter_generator.perimeter_flow.width;
+ path.height = (float)perimeter_generator.layer_height;
+ paths.push_back(path);
+ }
+
+ coll.append(ExtrusionLoop(paths, loop_role));
+ }
+
+ // Append thin walls to the nearest-neighbor search (only for first iteration)
+ if (! thin_walls.empty()) {
+ ExtrusionEntityCollection tw = variable_width(thin_walls, erExternalPerimeter, perimeter_generator.ext_perimeter_flow);
+ coll.append(tw.entities);
+ thin_walls.clear();
+ }
+
+ // Sort entities into a new collection using a nearest-neighbor search,
+ // preserving the original indices which are useful for detecting thin walls.
+ ExtrusionEntityCollection sorted_coll;
+ coll.chained_path(&sorted_coll, false, erMixed, &sorted_coll.orig_indices);
+
+ // traverse children and build the final collection
+ ExtrusionEntityCollection entities;
+ for (const size_t &idx : sorted_coll.orig_indices) {
+ if (idx >= loops.size()) {
+ // This is a thin wall. Let's get it from the sorted collection as it might have been reversed.
+ entities.append(std::move(*sorted_coll.entities[&idx - &sorted_coll.orig_indices.front()]));
+ } else {
+ const PerimeterGeneratorLoop &loop = loops[idx];
+ ExtrusionLoop eloop = *dynamic_cast<ExtrusionLoop*>(coll.entities[idx]);
+ ExtrusionEntityCollection children = traverse_loops(perimeter_generator, loop.children, thin_walls);
+ if (loop.is_contour) {
+ eloop.make_counter_clockwise();
+ entities.append(std::move(children.entities));
+ entities.append(std::move(eloop));
+ } else {
+ eloop.make_clockwise();
+ entities.append(std::move(eloop));
+ entities.append(std::move(children.entities));
+ }
+ }
+ }
+ return entities;
+}
+
void PerimeterGenerator::process()
{
// other perimeters
- this->_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
+ m_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
coord_t perimeter_width = this->perimeter_flow.scaled_width();
coord_t perimeter_spacing = this->perimeter_flow.scaled_spacing();
// external perimeters
- this->_ext_mm3_per_mm = this->ext_perimeter_flow.mm3_per_mm();
+ m_ext_mm3_per_mm = this->ext_perimeter_flow.mm3_per_mm();
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
coord_t ext_perimeter_spacing2 = this->ext_perimeter_flow.scaled_spacing(this->perimeter_flow);
// overhang perimeters
- this->_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
+ m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
// solid infill
coord_t solid_infill_spacing = this->solid_infill_flow.scaled_spacing();
@@ -35,16 +254,17 @@ void PerimeterGenerator::process()
// which is the spacing between external and internal, which is not correct
// and would make the collapsing (thus the details resolution) dependent on
// internal flow which is unrelated.
- coord_t min_spacing = perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE);
- coord_t ext_min_spacing = ext_perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE);
-
+ coord_t min_spacing = coord_t(perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE));
+ coord_t ext_min_spacing = coord_t(ext_perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE));
+ bool has_gap_fill = this->config->gap_fill_speed.value > 0;
+
// prepare grown lower layer slices for overhang detection
if (this->lower_slices != NULL && this->config->overhangs) {
// We consider overhang any part where the entire nozzle diameter is not supported by the
// lower layer, so we take lower slices and offset them by half the nozzle diameter used
// in the current layer
double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->perimeter_extruder-1);
- this->_lower_slices_p = offset(*this->lower_slices, float(scale_(+nozzle_diameter/2)));
+ m_lower_slices_polygons = offset(*this->lower_slices, float(scale_(+nozzle_diameter/2)));
}
// we need to process each island separately because we might have different
@@ -69,20 +289,20 @@ void PerimeterGenerator::process()
offsets = this->config->thin_walls ?
offset2_ex(
last,
- -(ext_perimeter_width / 2 + ext_min_spacing / 2 - 1),
- +(ext_min_spacing / 2 - 1)) :
- offset_ex(last, - ext_perimeter_width / 2);
+ - float(ext_perimeter_width / 2. + ext_min_spacing / 2. - 1),
+ + float(ext_min_spacing / 2. - 1)) :
+ offset_ex(last, - float(ext_perimeter_width / 2.));
// look for thin walls
if (this->config->thin_walls) {
// the following offset2 ensures almost nothing in @thin_walls is narrower than $min_width
// (actually, something larger than that still may exist due to mitering or other causes)
- coord_t min_width = scale_(this->ext_perimeter_flow.nozzle_diameter / 3);
+ coord_t min_width = coord_t(scale_(this->ext_perimeter_flow.nozzle_diameter / 3));
ExPolygons expp = offset2_ex(
// medial axis requires non-overlapping geometry
diff_ex(to_polygons(last),
- offset(offsets, ext_perimeter_width / 2),
+ offset(offsets, float(ext_perimeter_width / 2.)),
true),
- - min_width / 2, min_width / 2);
+ - float(min_width / 2.), float(min_width / 2.));
// the maximum thickness of our thin wall area is equal to the minimum thickness of a single loop
for (ExPolygon &ex : expp)
ex.medial_axis(ext_perimeter_width + ext_perimeter_spacing2, min_width, &thin_walls);
@@ -99,19 +319,19 @@ void PerimeterGenerator::process()
// Also the offset2(perimeter, -x, x) may sometimes lead to a perimeter, which is larger than
// the original.
offset2_ex(last,
- - (distance + min_spacing / 2 - 1),
- min_spacing / 2 - 1) :
+ - float(distance + min_spacing / 2. - 1.),
+ float(min_spacing / 2. - 1.)) :
// If "detect thin walls" is not enabled, this paths will be entered, which
// leads to overflows, as in prusa3d/Slic3r GH #32
- offset_ex(last, - distance);
+ offset_ex(last, - float(distance));
// look for gaps
- if (this->config->gap_fill_speed.value > 0 && this->config->fill_density.value > 0)
+ if (has_gap_fill)
// not using safety offset here would "detect" very narrow gaps
// (but still long enough to escape the area threshold) that gap fill
// won't be able to fill but we'd still remove from infill area
append(gaps, diff_ex(
- offset(last, -0.5 * distance),
- offset(offsets, 0.5 * distance + 10))); // safety offset
+ offset(last, - float(0.5 * distance)),
+ offset(offsets, float(0.5 * distance + 10)))); // safety offset
}
if (offsets.empty()) {
// Store the number of loops actually generated.
@@ -124,6 +344,11 @@ void PerimeterGenerator::process()
break;
}
for (const ExPolygon &expolygon : offsets) {
+ // Outer contour may overlap with an inner contour,
+ // inner contour may overlap with another inner contour,
+ // outer contour may overlap with itself.
+ //FIXME evaluate the overlaps, annotate each point with an overlap depth,
+ // compensate for the depth of intersection.
contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true));
if (! expolygon.holes.empty()) {
holes[i].reserve(holes[i].size() + expolygon.holes.size());
@@ -132,6 +357,11 @@ void PerimeterGenerator::process()
}
}
last = std::move(offsets);
+ if (i == loop_number && (! has_gap_fill || this->config->fill_density.value == 0)) {
+ // The last run of this loop is executed to collect gaps for gap fill.
+ // As the gap fill is either disabled or not
+ break;
+ }
}
// nest loops: holes first
@@ -189,7 +419,7 @@ void PerimeterGenerator::process()
}
}
// at this point, all loops should be in contours[0]
- ExtrusionEntityCollection entities = this->_traverse_loops(contours.front(), thin_walls);
+ ExtrusionEntityCollection entities = traverse_loops(*this, contours.front(), thin_walls);
// if brim will be printed, reverse the order of perimeters so that
// we continue inwards after having finished the brim
// TODO: add test for perimeter order
@@ -208,15 +438,14 @@ void PerimeterGenerator::process()
double max = 2. * perimeter_spacing;
ExPolygons gaps_ex = diff_ex(
//FIXME offset2 would be enough and cheaper.
- offset2_ex(gaps, -min/2, +min/2),
- offset2_ex(gaps, -max/2, +max/2),
+ offset2_ex(gaps, - float(min / 2.), float(min / 2.)),
+ offset2_ex(gaps, - float(max / 2.), float(max / 2.)),
true);
ThickPolylines polylines;
for (const ExPolygon &ex : gaps_ex)
ex.medial_axis(max, min, &polylines);
if (! polylines.empty()) {
- ExtrusionEntityCollection gap_fill = this->_variable_width(polylines,
- erGapFill, this->solid_infill_flow);
+ ExtrusionEntityCollection gap_fill = variable_width(polylines, erGapFill, this->solid_infill_flow);
this->gap_fill->append(gap_fill.entities);
/* 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).
@@ -243,229 +472,23 @@ void PerimeterGenerator::process()
perimeter_spacing / 2;
// only apply infill overlap if we actually have one perimeter
if (inset > 0)
- inset -= scale_(this->config->get_abs_value("infill_overlap", unscale<double>(inset + solid_infill_spacing / 2)));
+ inset -= coord_t(scale_(this->config->get_abs_value("infill_overlap", unscale<double>(inset + solid_infill_spacing / 2))));
// simplify infill contours according to resolution
Polygons pp;
for (ExPolygon &ex : last)
ex.simplify_p(SCALED_RESOLUTION, &pp);
// collapse too narrow infill areas
- coord_t min_perimeter_infill_spacing = solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE);
+ coord_t min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
// append infill areas to fill_surfaces
this->fill_surfaces->append(
offset2_ex(
union_ex(pp),
- - inset - min_perimeter_infill_spacing / 2,
- min_perimeter_infill_spacing / 2),
+ float(- inset - min_perimeter_infill_spacing / 2.),
+ float(min_perimeter_infill_spacing / 2.)),
stInternal);
} // for each island
}
-ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
- const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) const
-{
- // loops is an arrayref of ::Loop objects
- // turn each one into an ExtrusionLoop object
- ExtrusionEntityCollection coll;
- for (PerimeterGeneratorLoops::const_iterator loop = loops.begin();
- loop != loops.end(); ++loop) {
- bool is_external = loop->is_external();
-
- ExtrusionRole role;
- ExtrusionLoopRole loop_role;
- role = is_external ? erExternalPerimeter : erPerimeter;
- if (loop->is_internal_contour()) {
- // Note that we set loop role to ContourInternalPerimeter
- // also when loop is both internal and external (i.e.
- // there's only one contour loop).
- loop_role = elrContourInternalPerimeter;
- } else {
- loop_role = elrDefault;
- }
-
- // detect overhanging/bridging perimeters
- ExtrusionPaths paths;
- if (this->config->overhangs && this->layer_id > 0
- && !(this->object_config->support_material && this->object_config->support_material_contact_distance.value == 0)) {
- // get non-overhang paths by intersecting this loop with the grown lower slices
- extrusion_paths_append(
- paths,
- intersection_pl(loop->polygon, this->_lower_slices_p),
- role,
- is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm,
- is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width,
- this->layer_height);
-
- // get overhang paths by checking what parts of this loop fall
- // outside the grown lower slices (thus where the distance between
- // the loop centerline and original lower slices is >= half nozzle diameter
- extrusion_paths_append(
- paths,
- diff_pl(loop->polygon, this->_lower_slices_p),
- erOverhangPerimeter,
- this->_mm3_per_mm_overhang,
- this->overhang_flow.width,
- this->overhang_flow.height);
-
- // reapply the nearest point search for starting point
- // We allow polyline reversal because Clipper may have randomly
- // reversed polylines during clipping.
- paths = (ExtrusionPaths)ExtrusionEntityCollection(paths).chained_path();
- } else {
- ExtrusionPath path(role);
- path.polyline = loop->polygon.split_at_first_point();
- path.mm3_per_mm = is_external ? this->_ext_mm3_per_mm : this->_mm3_per_mm;
- path.width = is_external ? this->ext_perimeter_flow.width : this->perimeter_flow.width;
- path.height = this->layer_height;
- paths.push_back(path);
- }
-
- coll.append(ExtrusionLoop(paths, loop_role));
- }
-
- // append thin walls to the nearest-neighbor search (only for first iteration)
- if (!thin_walls.empty()) {
- ExtrusionEntityCollection tw = this->_variable_width
- (thin_walls, erExternalPerimeter, this->ext_perimeter_flow);
-
- coll.append(tw.entities);
- thin_walls.clear();
- }
-
- // sort entities into a new collection using a nearest-neighbor search,
- // preserving the original indices which are useful for detecting thin walls
- ExtrusionEntityCollection sorted_coll;
- coll.chained_path(&sorted_coll, false, erMixed, &sorted_coll.orig_indices);
-
- // traverse children and build the final collection
- ExtrusionEntityCollection entities;
- for (std::vector<size_t>::const_iterator idx = sorted_coll.orig_indices.begin();
- idx != sorted_coll.orig_indices.end();
- ++idx) {
-
- if (*idx >= loops.size()) {
- // this is a thin wall
- // let's get it from the sorted collection as it might have been reversed
- size_t i = idx - sorted_coll.orig_indices.begin();
- entities.append(*sorted_coll.entities[i]);
- } else {
- const PerimeterGeneratorLoop &loop = loops[*idx];
- ExtrusionLoop eloop = *dynamic_cast<ExtrusionLoop*>(coll.entities[*idx]);
-
- ExtrusionEntityCollection children = this->_traverse_loops(loop.children, thin_walls);
- if (loop.is_contour) {
- eloop.make_counter_clockwise();
- entities.append(children.entities);
- entities.append(eloop);
- } else {
- eloop.make_clockwise();
- entities.append(eloop);
- entities.append(children.entities);
- }
- }
- }
- return entities;
-}
-
-static inline ExtrusionPaths thick_polyline_to_extrusion_paths(const ThickPolyline &thick_polyline, ExtrusionRole role, Flow &flow, const float tolerance)
-{
- ExtrusionPaths paths;
- ExtrusionPath path(role);
- ThickLines lines = thick_polyline.thicklines();
-
- for (int i = 0; i < (int)lines.size(); ++i) {
- const ThickLine& line = lines[i];
-
- const coordf_t line_len = line.length();
- if (line_len < SCALED_EPSILON) continue;
-
- double thickness_delta = fabs(line.a_width - line.b_width);
- if (thickness_delta > tolerance) {
- const unsigned short segments = ceil(thickness_delta / tolerance);
- const coordf_t seg_len = line_len / segments;
- Points pp;
- std::vector<coordf_t> width;
- {
- pp.push_back(line.a);
- width.push_back(line.a_width);
- for (size_t j = 1; j < segments; ++j) {
- pp.push_back((line.a.cast<double>() + (line.b - line.a).cast<double>().normalized() * (j * seg_len)).cast<coord_t>());
-
- coordf_t w = line.a_width + (j*seg_len) * (line.b_width-line.a_width) / line_len;
- width.push_back(w);
- width.push_back(w);
- }
- pp.push_back(line.b);
- width.push_back(line.b_width);
-
- assert(pp.size() == segments + 1u);
- assert(width.size() == segments*2);
- }
-
- // delete this line and insert new ones
- lines.erase(lines.begin() + i);
- for (size_t j = 0; j < segments; ++j) {
- ThickLine new_line(pp[j], pp[j+1]);
- new_line.a_width = width[2*j];
- new_line.b_width = width[2*j+1];
- lines.insert(lines.begin() + i + j, new_line);
- }
-
- -- i;
- continue;
- }
-
- const double w = fmax(line.a_width, line.b_width);
- if (path.polyline.points.empty()) {
- path.polyline.append(line.a);
- path.polyline.append(line.b);
- // Convert from spacing to extrusion width based on the extrusion model
- // of a square extrusion ended with semi circles.
- flow.width = unscale<float>(w) + flow.height * (1. - 0.25 * PI);
- #ifdef SLIC3R_DEBUG
- printf(" filling %f gap\n", flow.width);
- #endif
- path.mm3_per_mm = flow.mm3_per_mm();
- path.width = flow.width;
- path.height = flow.height;
- } else {
- thickness_delta = fabs(scale_(flow.width) - w);
- if (thickness_delta <= tolerance) {
- // the width difference between this line and the current flow width is
- // within the accepted tolerance
- path.polyline.append(line.b);
- } else {
- // we need to initialize a new line
- paths.emplace_back(std::move(path));
- path = ExtrusionPath(role);
- -- i;
- }
- }
- }
- if (path.polyline.is_valid())
- paths.emplace_back(std::move(path));
- return paths;
-}
-
-ExtrusionEntityCollection PerimeterGenerator::_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const
-{
- // This value determines granularity of adaptive width, as G-code does not allow
- // variable extrusion within a single move; this value shall only affect the amount
- // of segments, and any pruning shall be performed before we apply this tolerance.
- ExtrusionEntityCollection coll;
- const double tolerance = scale_(0.05);
- for (const ThickPolyline &p : polylines) {
- ExtrusionPaths paths = thick_polyline_to_extrusion_paths(p, role, flow, tolerance);
- // Append paths to collection.
- if (! paths.empty()) {
- if (paths.front().first_point() == paths.back().last_point())
- coll.append(ExtrusionLoop(std::move(paths)));
- else
- coll.append(std::move(paths));
- }
- }
- return coll;
-}
-
bool PerimeterGeneratorLoop::is_internal_contour() const
{
// An internal contour is a contour containing no other contours
diff --git a/src/libslic3r/PerimeterGenerator.hpp b/src/libslic3r/PerimeterGenerator.hpp
index 44af8c8be..8cd71e697 100644
--- a/src/libslic3r/PerimeterGenerator.hpp
+++ b/src/libslic3r/PerimeterGenerator.hpp
@@ -11,29 +11,6 @@
namespace Slic3r {
-// Hierarchy of perimeters.
-class PerimeterGeneratorLoop {
-public:
- // Polygon of this contour.
- Polygon polygon;
- // Is it a contour or a hole?
- // Contours are CCW oriented, holes are CW oriented.
- bool is_contour;
- // Depth in the hierarchy. External perimeter has depth = 0. An external perimeter could be both a contour and a hole.
- unsigned short depth;
- // Children contour, may be both CCW and CW oriented (outer contours or holes).
- std::vector<PerimeterGeneratorLoop> children;
-
- PerimeterGeneratorLoop(Polygon polygon, unsigned short depth, bool is_contour) :
- polygon(polygon), is_contour(is_contour), depth(depth) {}
- // External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
- bool is_external() const { return this->depth == 0; }
- // An island, which may have holes, but it does not have another internal island.
- bool is_internal_contour() const;
-};
-
-typedef std::vector<PerimeterGeneratorLoop> PerimeterGeneratorLoops;
-
class PerimeterGenerator {
public:
// Inputs:
@@ -73,18 +50,21 @@ public:
overhang_flow(flow), solid_infill_flow(flow),
config(config), object_config(object_config), print_config(print_config),
loops(loops), gap_fill(gap_fill), fill_surfaces(fill_surfaces),
- _ext_mm3_per_mm(-1), _mm3_per_mm(-1), _mm3_per_mm_overhang(-1)
- {};
- void process();
+ m_ext_mm3_per_mm(-1), m_mm3_per_mm(-1), m_mm3_per_mm_overhang(-1)
+ {}
+
+ void process();
+
+ double ext_mm3_per_mm() const { return m_ext_mm3_per_mm; }
+ double mm3_per_mm() const { return m_mm3_per_mm; }
+ double mm3_per_mm_overhang() const { return m_mm3_per_mm_overhang; }
+ Polygons lower_slices_polygons() const { return m_lower_slices_polygons; }
private:
- double _ext_mm3_per_mm;
- double _mm3_per_mm;
- double _mm3_per_mm_overhang;
- Polygons _lower_slices_p;
-
- ExtrusionEntityCollection _traverse_loops(const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) const;
- ExtrusionEntityCollection _variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const;
+ double m_ext_mm3_per_mm;
+ double m_mm3_per_mm;
+ double m_mm3_per_mm_overhang;
+ Polygons m_lower_slices_polygons;
};
}
diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp
index 530d84907..0cfd97415 100644
--- a/src/libslic3r/PlaceholderParser.cpp
+++ b/src/libslic3r/PlaceholderParser.cpp
@@ -108,7 +108,6 @@ static inline bool opts_equal(const DynamicConfig &config_old, const DynamicConf
std::vector<std::string> PlaceholderParser::config_diff(const DynamicPrintConfig &rhs)
{
- const ConfigDef *def = rhs.def();
std::vector<std::string> diff_keys;
for (const t_config_option_key &opt_key : rhs.keys())
if (! opts_equal(m_config, rhs, opt_key))
@@ -124,7 +123,6 @@ std::vector<std::string> PlaceholderParser::config_diff(const DynamicPrintConfig
// a current extruder ID is used.
bool PlaceholderParser::apply_config(const DynamicPrintConfig &rhs)
{
- const ConfigDef *def = rhs.def();
bool modified = false;
for (const t_config_option_key &opt_key : rhs.keys()) {
if (! opts_equal(m_config, rhs, opt_key)) {
diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp
index 796215781..9d4df56d0 100644
--- a/src/libslic3r/Print.cpp
+++ b/src/libslic3r/Print.cpp
@@ -1228,24 +1228,35 @@ std::string Print::validate() const
if (has_custom_layering) {
const std::vector<coordf_t> &layer_height_profile_tallest = layer_height_profiles[tallest_object_idx];
for (size_t idx_object = 0; idx_object < m_objects.size(); ++ idx_object) {
+ if (idx_object == tallest_object_idx)
+ continue;
const std::vector<coordf_t> &layer_height_profile = layer_height_profiles[idx_object];
- bool failed = false;
- if (layer_height_profile_tallest.size() >= layer_height_profile.size()) {
- size_t i = 0;
- while (i < layer_height_profile.size() && i < layer_height_profile_tallest.size()) {
- if (std::abs(layer_height_profile_tallest[i] - layer_height_profile[i])) {
- failed = true;
- break;
- }
- ++ i;
- if (i == layer_height_profile.size() - 2) // this element contains this objects max z
- if (layer_height_profile_tallest[i] > layer_height_profile[i]) // the difference does not matter in this case
- ++ i;
+
+ // The comparison of the profiles is not just about element-wise equality, some layers may not be
+ // explicitely included. Always remember z and height of last reference layer that in the vector
+ // and compare to that.
+ size_t i = 0; // index into tested profile
+ size_t j = 0; // index into reference profile
+ coordf_t ref_z = -1.;
+ coordf_t next_ref_z = layer_height_profile_tallest[0];
+ coordf_t ref_height = -1.;
+ while (i < layer_height_profile.size()) {
+ coordf_t this_z = layer_height_profile[i];
+ coordf_t this_height = layer_height_profile[i+1];
+ if (next_ref_z < this_z + EPSILON) {
+ ref_z = next_ref_z;
+ do { // one layer can be in the vector several times
+ ref_height = layer_height_profile_tallest[j+1];
+ if (j+2 >= layer_height_profile_tallest.size())
+ break;
+ j += 2;
+ next_ref_z = layer_height_profile_tallest[j];
+ } while (ref_z == next_ref_z);
}
- } else
- failed = true;
- if (failed)
- return L("The Wipe tower is only supported if all objects have the same layer height profile");
+ if (std::abs(this_height - ref_height) > EPSILON)
+ return L("The Wipe tower is only supported if all objects have the same layer height profile");
+ i += 2;
+ }
}
}
}
diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp
index b6d7b678d..89a5f3e74 100644
--- a/src/libslic3r/Print.hpp
+++ b/src/libslic3r/Print.hpp
@@ -39,6 +39,8 @@ class PrintRegion
public:
const Print* print() const { return m_print; }
const PrintRegionConfig& config() const { return m_config; }
+ // 1-based extruder identifier for this region and role.
+ unsigned int extruder(FlowRole role) const;
Flow flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const;
// Average diameter of nozzles participating on extruding this region.
coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const;
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index 8b73a2e82..1ce00f269 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -2049,7 +2049,7 @@ void PrintConfigDef::init_fff_params()
{
int threads = (unsigned int)boost::thread::hardware_concurrency();
def->set_default_value(new ConfigOptionInt(threads > 0 ? threads : 2));
- def->cli == ConfigOptionDef::nocli;
+ def->cli = ConfigOptionDef::nocli;
}
def = this->add("toolchange_gcode", coString);
@@ -2894,7 +2894,7 @@ void DynamicPrintConfig::normalize()
{
this->opt<ConfigOptionInt>("perimeters", true)->value = 1;
this->opt<ConfigOptionInt>("top_solid_layers", true)->value = 0;
- this->opt<ConfigOptionPercent>("fill_density", true)->value = 0;
+ this->opt<ConfigOptionPercent>("fill_density", true)->value = 0;
}
}
}
diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp
index 015b2bde7..6a19edf84 100644
--- a/src/libslic3r/PrintConfig.hpp
+++ b/src/libslic3r/PrintConfig.hpp
@@ -24,7 +24,7 @@
namespace Slic3r {
-enum GCodeFlavor {
+enum GCodeFlavor : unsigned char {
gcfRepRap, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlin, gcfSailfish, gcfMach3, gcfMachinekit,
gcfSmoothie, gcfNoExtrusion,
};
@@ -35,7 +35,7 @@ enum PrintHostType {
enum InfillPattern {
ipRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
- ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral,
+ ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipCount,
};
enum SupportMaterialPattern {
diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp
index e19bceeb7..2834d9105 100644
--- a/src/libslic3r/PrintObject.cpp
+++ b/src/libslic3r/PrintObject.cpp
@@ -258,8 +258,8 @@ void PrintObject::prepare_infill()
m_print->throw_if_canceled();
// Decide what surfaces are to be filled.
- // Here the S_TYPE_TOP / S_TYPE_BOTTOMBRIDGE / S_TYPE_BOTTOM infill is turned to just S_TYPE_INTERNAL if zero top / bottom infill layers are configured.
- // Also tiny S_TYPE_INTERNAL surfaces are turned to S_TYPE_INTERNAL_SOLID.
+ // Here the stTop / stBottomBridge / stBottom infill is turned to just stInternal if zero top / bottom infill layers are configured.
+ // Also tiny stInternal surfaces are turned to stInternalSolid.
BOOST_LOG_TRIVIAL(info) << "Preparing fill surfaces..." << log_memory_info();
for (auto *layer : m_layers)
for (auto *region : layer->m_regions) {
@@ -271,8 +271,8 @@ void PrintObject::prepare_infill()
// and rearrange top/bottom/internal surfaces
// It produces enlarged overlapping bridging areas.
//
- // 1) S_TYPE_BOTTOMBRIDGE / S_TYPE_BOTTOM infill is grown by 3mm and clipped by the total infill area. Bridges are detected. The areas may overlap.
- // 2) S_TYPE_TOP is grown by 3mm and clipped by the grown bottom areas. The areas may overlap.
+ // 1) stBottomBridge / stBottom infill is grown by 3mm and clipped by the total infill area. Bridges are detected. The areas may overlap.
+ // 2) stTop is grown by 3mm and clipped by the grown bottom areas. The areas may overlap.
// 3) Clip the internal surfaces by the grown top/bottom surfaces.
// 4) Merge surfaces with the same style. This will mostly get rid of the overlaps.
//FIXME This does not likely merge surfaces, which are supported by a material with different colors, but same properties.
@@ -468,9 +468,17 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|| opt_key == "support_material_contact_distance"
|| opt_key == "xy_size_compensation") {
steps.emplace_back(posSlice);
+ } else if (opt_key == "support_material") {
+ steps.emplace_back(posSupportMaterial);
+ if (m_config.support_material_contact_distance == 0.) {
+ // Enabling / disabling supports while soluble support interface is enabled.
+ // This changes the bridging logic (bridging enabled without supports, disabled with supports).
+ // Reset everything.
+ // See GH #1482 for details.
+ steps.emplace_back(posSlice);
+ }
} else if (
- opt_key == "support_material"
- || opt_key == "support_material_auto"
+ opt_key == "support_material_auto"
|| opt_key == "support_material_angle"
|| opt_key == "support_material_buildplate_only"
|| opt_key == "support_material_enforce_layers"
@@ -524,8 +532,13 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
steps.emplace_back(posPerimeters);
steps.emplace_back(posSupportMaterial);
} else if (opt_key == "bridge_flow_ratio") {
- steps.emplace_back(posPerimeters);
- steps.emplace_back(posInfill);
+ if (m_config.support_material_contact_distance > 0.) {
+ // Only invalidate due to bridging if bridging is enabled.
+ // If later "support_material_contact_distance" is modified, the complete PrintObject is invalidated anyway.
+ steps.emplace_back(posPerimeters);
+ steps.emplace_back(posInfill);
+ steps.emplace_back(posSupportMaterial);
+ }
} else if (
opt_key == "seam_position"
|| opt_key == "seam_preferred_direction"
@@ -810,15 +823,72 @@ void PrintObject::process_external_surfaces()
{
BOOST_LOG_TRIVIAL(info) << "Processing external surfaces..." << log_memory_info();
+ // Cached surfaces covered by some extrusion, defining regions, over which the from the surfaces one layer higher are allowed to expand.
+ std::vector<Polygons> surfaces_covered;
+ // Is there any printing region, that has zero infill? If so, then we don't want the expansion to be performed over the complete voids, but only
+ // over voids, which are supported by the layer below.
+ bool has_voids = false;
+ for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id)
+ if (! this->region_volumes.empty() && this->print()->regions()[region_id]->config().fill_density == 0) {
+ has_voids = true;
+ break;
+ }
+ if (has_voids && m_layers.size() > 1) {
+ // All but stInternal fill surfaces will get expanded and possibly trimmed.
+ std::vector<unsigned char> layer_expansions_and_voids(m_layers.size(), false);
+ for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++ layer_idx) {
+ const Layer *layer = m_layers[layer_idx];
+ bool expansions = false;
+ bool voids = false;
+ for (const LayerRegion *layerm : layer->regions()) {
+ for (const Surface &surface : layerm->fill_surfaces.surfaces) {
+ if (surface.surface_type == stInternal)
+ voids = true;
+ else
+ expansions = true;
+ if (voids && expansions) {
+ layer_expansions_and_voids[layer_idx] = true;
+ goto end;
+ }
+ }
+ }
+ end:;
+ }
+ BOOST_LOG_TRIVIAL(debug) << "Collecting surfaces covered with extrusions in parallel - start";
+ surfaces_covered.resize(m_layers.size() - 1, Polygons());
+ auto unsupported_width = - float(scale_(0.3 * EXTERNAL_INFILL_MARGIN));
+ tbb::parallel_for(
+ tbb::blocked_range<size_t>(0, m_layers.size() - 1),
+ [this, &surfaces_covered, &layer_expansions_and_voids, unsupported_width](const tbb::blocked_range<size_t>& range) {
+ for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
+ if (layer_expansions_and_voids[layer_idx + 1]) {
+ m_print->throw_if_canceled();
+ Polygons voids;
+ for (const LayerRegion *layerm : m_layers[layer_idx]->regions()) {
+ if (layerm->region()->config().fill_density.value == 0.)
+ for (const Surface &surface : layerm->fill_surfaces.surfaces)
+ // Shrink the holes, let the layer above expand slightly inside the unsupported areas.
+ polygons_append(voids, offset(surface.expolygon, unsupported_width));
+ }
+ surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->slices.expolygons), voids);
+ }
+ }
+ );
+ m_print->throw_if_canceled();
+ BOOST_LOG_TRIVIAL(debug) << "Collecting surfaces covered with extrusions in parallel - end";
+ }
+
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++region_id) {
BOOST_LOG_TRIVIAL(debug) << "Processing external surfaces for region " << region_id << " in parallel - start";
tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size()),
- [this, region_id](const tbb::blocked_range<size_t>& range) {
+ [this, &surfaces_covered, region_id](const tbb::blocked_range<size_t>& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
m_print->throw_if_canceled();
// BOOST_LOG_TRIVIAL(trace) << "Processing external surface, layer" << m_layers[layer_idx]->print_z;
- m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces((layer_idx == 0) ? NULL : m_layers[layer_idx - 1]);
+ m_layers[layer_idx]->get_region((int)region_id)->process_external_surfaces(
+ (layer_idx == 0) ? nullptr : m_layers[layer_idx - 1],
+ (layer_idx == 0 || surfaces_covered.empty() || surfaces_covered[layer_idx - 1].empty()) ? nullptr : &surfaces_covered[layer_idx - 1]);
}
}
);
@@ -1315,7 +1385,7 @@ void PrintObject::bridge_over_infill()
)};
push @new_surfaces, map Slic3r::Surface->new(
expolygon => $_,
- surface_type => S_TYPE_INTERNALVOID,
+ surface_type => stInternalVoid,
), @{intersection_ex(
[ map $_->p, @$group ],
[ map @$_, @$to_bridge ],
@@ -1443,11 +1513,8 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c
layer_height_profile.clear();
if (layer_height_profile.empty()) {
- if (0)
-// if (this->layer_height_profile.empty())
- layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes);
- else
- layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges); // #ys_FIXME_experiment
+ //layer_height_profile = layer_height_profile_adaptive(slicing_parameters, model_object.layer_config_ranges, model_object.volumes);
+ layer_height_profile = layer_height_profile_from_ranges(slicing_parameters, model_object.layer_config_ranges);
updated = true;
}
return updated;
@@ -1870,12 +1937,13 @@ std::vector<ExPolygons> PrintObject::slice_modifiers(size_t region_id, const std
merge.assign(out.size(), false);
} else {
for (size_t i = 0; i < out.size(); ++ i)
- if (! this_slices[i].empty())
+ if (! this_slices[i].empty()) {
if (! out[i].empty()) {
append(out[i], this_slices[i]);
merge[i] = true;
} else
out[i] = std::move(this_slices[i]);
+ }
}
i = j;
} else
@@ -2238,8 +2306,7 @@ void PrintObject::clip_fill_surfaces()
// Detect things that we need to support.
// Cummulative slices.
Polygons slices;
- for (const ExPolygon &expoly : layer->slices.expolygons)
- polygons_append(slices, to_polygons(expoly));
+ polygons_append(slices, layer->slices.expolygons);
// Cummulative fill surfaces.
Polygons fill_surfaces;
// Solid surfaces to be supported.
@@ -2348,7 +2415,7 @@ void PrintObject::discover_horizontal_shells()
polygons_append(solid, to_polygons(surface.expolygon));
if (solid.empty())
continue;
-// Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == S_TYPE_TOP) ? 'top' : 'bottom';
+// Slic3r::debugf "Layer %d has %s surfaces\n", $i, ($type == stTop) ? 'top' : 'bottom';
size_t solid_layers = (type == stTop) ? region_config.top_solid_layers.value : region_config.bottom_solid_layers.value;
for (int n = (type == stTop) ? i-1 : i+1; std::abs(n - (int)i) < solid_layers; (type == stTop) ? -- n : ++ n) {
@@ -2367,7 +2434,7 @@ void PrintObject::discover_horizontal_shells()
// shells to be generated in the base but not in the walls (where there are many
// narrow bottom surfaces): reassigning $solid will consider the 'shadow' of the
// upper perimeter as an obstacle and shell will not be propagated to more upper layers
- //FIXME How does it work for S_TYPE_INTERNALBRIDGE? This is set for sparse infill. Likely this does not work.
+ //FIXME How does it work for stInternalBRIDGE? This is set for sparse infill. Likely this does not work.
Polygons new_internal_solid;
{
Polygons internal;
@@ -2560,7 +2627,7 @@ void PrintObject::combine_infill()
continue;
// Slic3r::debugf " combining %d %s regions from layers %d-%d\n",
// scalar(@$intersection),
-// ($type == S_TYPE_INTERNAL ? 'internal' : 'internal-solid'),
+// ($type == stInternal ? 'internal' : 'internal-solid'),
// $layer_idx-($every-1), $layer_idx;
// intersection now contains the regions that can be combined across the full amount of layers,
// so let's remove those areas from all layers.
diff --git a/src/libslic3r/PrintRegion.cpp b/src/libslic3r/PrintRegion.cpp
index fc2bdfa7d..b3ac6a4a5 100644
--- a/src/libslic3r/PrintRegion.cpp
+++ b/src/libslic3r/PrintRegion.cpp
@@ -2,6 +2,21 @@
namespace Slic3r {
+// 1-based extruder identifier for this region and role.
+unsigned int PrintRegion::extruder(FlowRole role) const
+{
+ size_t extruder = 0;
+ if (role == frPerimeter || role == frExternalPerimeter)
+ extruder = m_config.perimeter_extruder;
+ else if (role == frInfill)
+ extruder = m_config.infill_extruder;
+ else if (role == frSolidInfill || role == frTopSolidInfill)
+ extruder = m_config.solid_infill_extruder;
+ else
+ throw std::invalid_argument("Unknown role");
+ return extruder;
+}
+
Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const
{
ConfigOptionFloatOrPercent config_width;
@@ -28,24 +43,13 @@ Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool fir
throw std::invalid_argument("Unknown role");
}
}
- if (config_width.value == 0) {
+
+ if (config_width.value == 0)
config_width = object.config().extrusion_width;
- }
-
- // get the configured nozzle_diameter for the extruder associated
- // to the flow role requested
- size_t extruder = 0; // 1-based
- if (role == frPerimeter || role == frExternalPerimeter) {
- extruder = m_config.perimeter_extruder;
- } else if (role == frInfill) {
- extruder = m_config.infill_extruder;
- } else if (role == frSolidInfill || role == frTopSolidInfill) {
- extruder = m_config.solid_infill_extruder;
- } else {
- throw std::invalid_argument("Unknown role");
- }
- double nozzle_diameter = m_print->config().nozzle_diameter.get_at(extruder-1);
+ // Get the configured nozzle_diameter for the extruder associated to the flow role requested.
+ // Here this->extruder(role) - 1 may underflow to MAX_INT, but then the get_at() will follback to zero'th element, so everything is all right.
+ double nozzle_diameter = m_print->config().nozzle_diameter.get_at(this->extruder(role) - 1);
return Flow::new_from_config_width(role, config_width, (float)nozzle_diameter, (float)layer_height, bridge ? (float)m_config.bridge_flow_ratio : 0.0f);
}
@@ -79,12 +83,14 @@ void PrintRegion::collect_object_printing_extruders(const PrintConfig &print_con
void PrintRegion::collect_object_printing_extruders(std::vector<unsigned int> &object_extruders) const
{
- auto num_extruders = (int)print()->config().nozzle_diameter.size();
// PrintRegion, if used by some PrintObject, shall have all the extruders set to an existing printer extruder.
// If not, then there must be something wrong with the Print::apply() function.
+#ifndef NDEBUG
+ auto num_extruders = (int)print()->config().nozzle_diameter.size();
assert(this->config().perimeter_extruder <= num_extruders);
assert(this->config().infill_extruder <= num_extruders);
assert(this->config().solid_infill_extruder <= num_extruders);
+#endif
collect_object_printing_extruders(print()->config(), this->config(), object_extruders);
}
diff --git a/src/libslic3r/SLA/SLAAutoSupports.hpp b/src/libslic3r/SLA/SLAAutoSupports.hpp
index 3b696212e..38f21e6cf 100644
--- a/src/libslic3r/SLA/SLAAutoSupports.hpp
+++ b/src/libslic3r/SLA/SLAAutoSupports.hpp
@@ -185,8 +185,6 @@ private:
SLAAutoSupports::Config m_config;
- float m_supports_force_total = 0.f;
-
void process(const std::vector<ExPolygons>& slices, const std::vector<float>& heights);
void uniformly_cover(const ExPolygons& islands, Structure& structure, PointGrid3D &grid3d, bool is_new_island = false, bool just_one = false);
void project_onto_mesh(std::vector<sla::SupportPoint>& points) const;
diff --git a/src/libslic3r/Surface.cpp b/src/libslic3r/Surface.cpp
index acc19e631..58ac7294c 100644
--- a/src/libslic3r/Surface.cpp
+++ b/src/libslic3r/Surface.cpp
@@ -4,64 +4,6 @@
namespace Slic3r {
-Surface::operator Polygons() const
-{
- return this->expolygon;
-}
-
-double
-Surface::area() const
-{
- return this->expolygon.area();
-}
-
-bool
-Surface::is_solid() const
-{
- return this->surface_type == stTop
- || this->surface_type == stBottom
- || this->surface_type == stBottomBridge
- || this->surface_type == stInternalSolid
- || this->surface_type == stInternalBridge;
-}
-
-bool
-Surface::is_external() const
-{
- return this->surface_type == stTop
- || this->surface_type == stBottom
- || this->surface_type == stBottomBridge;
-}
-
-bool
-Surface::is_internal() const
-{
- return this->surface_type == stInternal
- || this->surface_type == stInternalBridge
- || this->surface_type == stInternalSolid
- || this->surface_type == stInternalVoid;
-}
-
-bool
-Surface::is_top() const
-{
- return this->surface_type == stTop;
-}
-
-bool
-Surface::is_bottom() const
-{
- return this->surface_type == stBottom
- || this->surface_type == stBottomBridge;
-}
-
-bool
-Surface::is_bridge() const
-{
- return this->surface_type == stBottomBridge
- || this->surface_type == stInternalBridge;
-}
-
BoundingBox get_extents(const Surface &surface)
{
return get_extents(surface.expolygon.contour);
diff --git a/src/libslic3r/Surface.hpp b/src/libslic3r/Surface.hpp
index e0f7e1ea3..fbebe5610 100644
--- a/src/libslic3r/Surface.hpp
+++ b/src/libslic3r/Surface.hpp
@@ -24,9 +24,8 @@ enum SurfaceType {
stInternalVoid,
// Inner/outer perimeters.
stPerimeter,
- // Last surface type, if the SurfaceType is used as an index into a vector.
- stLast,
- stCount = stLast + 1
+ // Number of SurfaceType enums.
+ stCount,
};
class Surface
@@ -91,16 +90,18 @@ public:
return *this;
}
- operator Polygons() const;
- double area() const;
- bool empty() const { return expolygon.empty(); }
- void clear() { expolygon.clear(); }
- bool is_solid() const;
- bool is_external() const;
- bool is_internal() const;
- bool is_top() const;
- bool is_bottom() const;
- bool is_bridge() const;
+ operator Polygons() const { return this->expolygon; }
+ double area() const { return this->expolygon.area(); }
+ bool empty() const { return expolygon.empty(); }
+ void clear() { expolygon.clear(); }
+
+ // The following methods do not test for stPerimeter.
+ bool is_top() const { return this->surface_type == stTop; }
+ bool is_bottom() const { return this->surface_type == stBottom || this->surface_type == stBottomBridge; }
+ bool is_bridge() const { return this->surface_type == stBottomBridge || this->surface_type == stInternalBridge; }
+ bool is_external() const { return this->is_top() || this->is_bottom(); }
+ bool is_internal() const { return ! this->is_external(); }
+ bool is_solid() const { return this->is_external() || this->surface_type == stInternalSolid || this->surface_type == stInternalBridge; }
};
typedef std::vector<Surface> Surfaces;
diff --git a/src/libslic3r/SurfaceCollection.hpp b/src/libslic3r/SurfaceCollection.hpp
index 9544748e9..b60105eb3 100644
--- a/src/libslic3r/SurfaceCollection.hpp
+++ b/src/libslic3r/SurfaceCollection.hpp
@@ -37,6 +37,7 @@ public:
void clear() { surfaces.clear(); }
bool empty() const { return surfaces.empty(); }
+ size_t size() const { return surfaces.size(); }
bool has(SurfaceType type) const {
for (const Surface &surface : this->surfaces)
if (surface.surface_type == type) return true;
diff --git a/src/slic3r/Config/Snapshot.cpp b/src/slic3r/Config/Snapshot.cpp
index 8fd64bb2a..622b31a17 100644
--- a/src/slic3r/Config/Snapshot.cpp
+++ b/src/slic3r/Config/Snapshot.cpp
@@ -202,9 +202,9 @@ void Snapshot::export_selections(AppConfig &config) const
config.clear_section("presets");
config.set("presets", "print", print);
config.set("presets", "filament", filaments.front());
- for (int i = 1; i < filaments.size(); ++i) {
+ for (unsigned i = 1; i < filaments.size(); ++i) {
char name[64];
- sprintf(name, "filament_%d", i);
+ sprintf(name, "filament_%u", i);
config.set("presets", name, filaments[i]);
}
config.set("presets", "printer", printer);
@@ -373,9 +373,9 @@ const Snapshot& SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot:
snapshot.print = app_config.get("presets", "print");
snapshot.filaments.emplace_back(app_config.get("presets", "filament"));
snapshot.printer = app_config.get("presets", "printer");
- for (unsigned int i = 1; i < 1000; ++ i) {
+ for (unsigned i = 1; i < 1000; ++ i) {
char name[64];
- sprintf(name, "filament_%d", i);
+ sprintf(name, "filament_%u", i);
if (! app_config.has("presets", name))
break;
snapshot.filaments.emplace_back(app_config.get("presets", name));
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index 2916d0177..8094cdde1 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -1142,7 +1142,7 @@ void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
Color color;
::memcpy((void*)color.data(), (const void*)volume->color, 4 * sizeof(float));
fprintf(fp, "\n# material volume %d\n", volumes_count);
- fprintf(fp, "usemtl material_%lld\n", 1 + std::distance(colors.begin(), colors.find(color)));
+ fprintf(fp, "usemtl material_%lld\n", (long long)(1 + std::distance(colors.begin(), colors.find(color))));
int base_vertex_id = vertices_count + 1;
int base_normal_id = normals_count + 1;
@@ -1242,8 +1242,8 @@ static void thick_lines_to_indexed_vertex_array(
// calculate new XY normals
Vec2d xy_right_normal = unscale(line.normal()).normalized();
- int idx_a[4];
- int idx_b[4];
+ int idx_a[4] = { 0, 0, 0, 0 }; // initialized to avoid warnings
+ int idx_b[4] = { 0, 0, 0, 0 }; // initialized to avoid warnings
int idx_last = int(volume.vertices_and_normals_interleaved.size() / 6);
bool bottom_z_different = bottom_z_prev != bottom_z;
diff --git a/src/slic3r/GUI/BedShapeDialog.cpp b/src/slic3r/GUI/BedShapeDialog.cpp
index a9be260bd..90fc0ff80 100644
--- a/src/slic3r/GUI/BedShapeDialog.cpp
+++ b/src/slic3r/GUI/BedShapeDialog.cpp
@@ -446,7 +446,7 @@ void BedShapePanel::update_shape()
auto twopi = 2 * PI;
auto edges = 72;
std::vector<Vec2d> points;
- for (size_t i = 1; i <= edges; ++i) {
+ for (int i = 1; i <= edges; ++i) {
auto angle = i * twopi / edges;
points.push_back(Vec2d(r*cos(angle), r*sin(angle)));
}
diff --git a/src/slic3r/GUI/BitmapCache.cpp b/src/slic3r/GUI/BitmapCache.cpp
index 3e8924143..f7cefe72b 100644
--- a/src/slic3r/GUI/BitmapCache.cpp
+++ b/src/slic3r/GUI/BitmapCache.cpp
@@ -57,7 +57,7 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_
m_map[bitmap_key] = bitmap;
} else {
bitmap = it->second;
- if (bitmap->GetWidth() != width || bitmap->GetHeight() != height)
+ if (size_t(bitmap->GetWidth()) != width || size_t(bitmap->GetHeight()) != height)
bitmap->Create(width, height);
}
#ifndef BROKEN_ALPHA
@@ -194,7 +194,7 @@ wxBitmap* BitmapCache::insert_raw_rgba(const std::string &bitmap_key, unsigned w
return this->insert(bitmap_key, wxImage_to_wxBitmap_with_alpha(std::move(image), scale));
}
-wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int width, unsigned int height,
+wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned width, unsigned height,
const bool grayscale/* = false*/)
{
std::string bitmap_key = bitmap_name + ( height !=0 ?
@@ -211,10 +211,10 @@ wxBitmap* BitmapCache::load_png(const std::string &bitmap_name, unsigned int wid
image.GetWidth() == 0 || image.GetHeight() == 0)
return nullptr;
- if (height != 0 && image.GetHeight() != height)
- width = int(0.5f + float(image.GetWidth()) * height / image.GetHeight());
- else if (width != 0 && image.GetWidth() != width)
- height = int(0.5f + float(image.GetHeight()) * width / image.GetWidth());
+ if (height != 0 && unsigned(image.GetHeight()) != height)
+ width = unsigned(0.5f + float(image.GetWidth()) * height / image.GetHeight());
+ else if (width != 0 && unsigned(image.GetWidth()) != width)
+ height = unsigned(0.5f + float(image.GetHeight()) * width / image.GetWidth());
if (height != 0 && width != 0)
image.Rescale(width, height, wxIMAGE_QUALITY_BILINEAR);
diff --git a/src/slic3r/GUI/BitmapCache.hpp b/src/slic3r/GUI/BitmapCache.hpp
index 10ce3299e..ce77057c8 100644
--- a/src/slic3r/GUI/BitmapCache.hpp
+++ b/src/slic3r/GUI/BitmapCache.hpp
@@ -32,9 +32,9 @@ public:
wxBitmap* insert_raw_rgba(const std::string &bitmap_key, unsigned width, unsigned height, const unsigned char *raw_data, float scale = 1.0f, const bool grayscale = false);
// Load png from resources/icons. bitmap_key is given without the .png suffix. Bitmap will be rescaled to provided height/width if nonzero.
- wxBitmap* load_png(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0, const bool grayscale = false);
+ wxBitmap* load_png(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, const bool grayscale = false);
// Load svg from resources/icons. bitmap_key is given without the .svg suffix. SVG will be rasterized to provided height/width.
- wxBitmap* load_svg(const std::string &bitmap_key, unsigned int width = 0, unsigned int height = 0, float scale = 1.0f, const bool grayscale = false);
+ wxBitmap* load_svg(const std::string &bitmap_key, unsigned width = 0, unsigned height = 0, float scale = 1.0f, const bool grayscale = false);
static wxBitmap mksolid(size_t width, size_t height, unsigned char r, unsigned char g, unsigned char b, unsigned char transparency);
static wxBitmap mksolid(size_t width, size_t height, const unsigned char rgb[3]) { return mksolid(width, height, rgb[0], rgb[1], rgb[2], wxALPHA_OPAQUE); }
diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp
index 2f37eb894..c9cdff162 100644
--- a/src/slic3r/GUI/ConfigManipulation.cpp
+++ b/src/slic3r/GUI/ConfigManipulation.cpp
@@ -243,7 +243,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
"infill_speed", "bridge_speed" })
toggle_field(el, have_infill || have_solid_infill);
- toggle_field("gap_fill_speed", have_perimeters && have_infill);
+ // Gap fill is newly allowed in between perimeter lines even for empty infill (see GH #1476).
+ toggle_field("gap_fill_speed", have_perimeters);
bool have_top_solid_infill = config->opt_int("top_solid_layers") > 0;
for (auto el : { "top_infill_extrusion_width", "top_solid_infill_speed" })
diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp
index 454b4874f..07d75c947 100644
--- a/src/slic3r/GUI/Field.cpp
+++ b/src/slic3r/GUI/Field.cpp
@@ -189,7 +189,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
case coFloatOrPercent: {
if (m_opt.type == coFloatOrPercent && !str.IsEmpty() && str.Last() != '%')
{
- double val;
+ double val = 0.;
// Replace the first occurence of comma in decimal number.
str.Replace(",", ".", false);
if (check_value && !str.ToCDouble(&val))
@@ -197,8 +197,8 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
show_error(m_parent, _(L("Invalid numeric input.")));
set_value(double_to_string(val), true);
}
- else if (check_value && (m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max ||
- m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1) &&
+ else if (check_value && ((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) ||
+ (m_opt.sidetext.rfind("mm ") != std::string::npos && val > 1)) &&
(m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast<std::string>(m_value)))
{
const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";
@@ -444,7 +444,7 @@ void TextCtrl::disable() { dynamic_cast<wxTextCtrl*>(window)->Disable(); dynamic
#ifdef __WXGTK__
void TextCtrl::change_field_value(wxEvent& event)
{
- if (bChangedValueEvent = event.GetEventType()==wxEVT_KEY_UP)
+ if (bChangedValueEvent = (event.GetEventType()==wxEVT_KEY_UP))
on_change_field();
event.Skip();
};
@@ -768,7 +768,7 @@ void Choice::set_selection()
size_t idx = 0;
for (auto el : m_opt.enum_values)
{
- if (el.compare(text_value) == 0)
+ if (el == text_value)
break;
++idx;
}
@@ -789,7 +789,7 @@ void Choice::set_selection()
size_t idx = 0;
for (auto el : m_opt.enum_values)
{
- if (el.compare(text_value) == 0)
+ if (el == text_value)
break;
++idx;
}
@@ -804,7 +804,7 @@ void Choice::set_selection()
size_t idx = 0;
for (auto el : m_opt.enum_values)
{
- if (el.compare(text_value) == 0)
+ if (el == text_value)
break;
++idx;
}
@@ -813,6 +813,7 @@ void Choice::set_selection()
field->SetSelection(idx);
break;
}
+ default: break;
}
}
@@ -823,7 +824,7 @@ void Choice::set_value(const std::string& value, bool change_event) //! Redunda
size_t idx=0;
for (auto el : m_opt.enum_values)
{
- if (el.compare(value) == 0)
+ if (el == value)
break;
++idx;
}
@@ -853,10 +854,10 @@ void Choice::set_value(const boost::any& value, bool change_event)
text_value = wxString::Format(_T("%i"), int(boost::any_cast<int>(value)));
else
text_value = boost::any_cast<wxString>(value);
- auto idx = 0;
+ size_t idx = 0;
for (auto el : m_opt.enum_values)
{
- if (el.compare(text_value) == 0)
+ if (el == text_value)
break;
++idx;
}
@@ -887,7 +888,7 @@ void Choice::set_value(const boost::any& value, bool change_event)
size_t idx = 0;
for (auto el : m_opt.enum_values)
{
- if (el.compare(key) == 0)
+ if (el == key)
break;
++idx;
}
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 71bacd815..edb9c7830 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -60,10 +60,6 @@
#endif // ENABLE_RENDER_STATISTICS
static const float TRACKBALLSIZE = 0.8f;
-static const float GROUND_Z = -0.02f;
-
-static const float GIZMO_RESET_BUTTON_HEIGHT = 22.0f;
-static const float GIZMO_RESET_BUTTON_WIDTH = 70.f;
static const float DEFAULT_BG_DARK_COLOR[3] = { 0.478f, 0.478f, 0.478f };
static const float DEFAULT_BG_LIGHT_COLOR[3] = { 0.753f, 0.753f, 0.753f };
@@ -845,22 +841,23 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_values(const GCodePrevie
{
auto& config = wxGetApp().preset_bundle->project_config;
const std::vector<double>& color_print_values = config.option<ConfigOptionFloats>("colorprint_heights")->values;
- const size_t values_cnt = color_print_values.size();
- if (values_cnt > 0) {
+
+ if (!color_print_values.empty()) {
std::vector<double> print_zs = canvas.get_current_print_zs(true);
- size_t z = 0;
- for (size_t i = 0; i < values_cnt; ++i)
+ for (auto cp_value : color_print_values)
{
- double prev_z = -1.0;
- for ( ; z < print_zs.size(); ++z)
- if (fabs(color_print_values[i] - print_zs[z]) < EPSILON) {
- prev_z = z > 0 ? print_zs[z - 1] : 0.;
- break;
- }
- if (prev_z < 0)
+ auto lower_b = std::lower_bound(print_zs.begin(), print_zs.end(), cp_value - DoubleSlider::epsilon());
+
+ if (lower_b == print_zs.end())
continue;
- cp_legend_values.push_back(std::pair<double, double>(prev_z, color_print_values[i]));
+ double current_z = *lower_b;
+ double previous_z = lower_b == print_zs.begin() ? 0.0 : *(--lower_b);
+
+ // to avoid duplicate values, check adding values
+ if (cp_legend_values.empty() ||
+ !(cp_legend_values.back().first == previous_z && cp_legend_values.back().second == current_z) )
+ cp_legend_values.push_back(std::pair<double, double>(previous_z, current_z));
}
}
}
@@ -901,11 +898,11 @@ bool GLCanvas3D::LegendTexture::generate(const GCodePreviewData& preview_data, c
// Disabling ClearType works, but the font returned is very different (much thicker) from the default.
// msw_disable_cleartype(font);
- bool cleartype = is_font_cleartype(font);
+// bool cleartype = is_font_cleartype(font);
#else
// select default font
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Scale(scale_gl);
- bool cleartype = false;
+// bool cleartype = false;
#endif /* __WXMSW__ */
memDC.SetFont(font);
@@ -1126,6 +1123,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar
, m_retina_helper(nullptr)
#endif
, m_in_render(false)
+ , m_render_enabled(true)
, m_bed(bed)
, m_camera(camera)
, m_view_toolbar(view_toolbar)
@@ -1330,13 +1328,13 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject
void GLCanvas3D::update_instance_printable_state_for_object(const size_t obj_idx)
{
ModelObject* model_object = m_model->objects[obj_idx];
- for (int inst_idx = 0; inst_idx < model_object->instances.size(); inst_idx++)
+ for (int inst_idx = 0; inst_idx < (int)model_object->instances.size(); ++inst_idx)
{
ModelInstance* instance = model_object->instances[inst_idx];
for (GLVolume* volume : m_volumes.volumes)
{
- if ((volume->object_idx() == obj_idx) && (volume->instance_idx() == inst_idx))
+ if ((volume->object_idx() == (int)obj_idx) && (volume->instance_idx() == inst_idx))
volume->printable = instance->printable;
}
}
@@ -1512,7 +1510,7 @@ void GLCanvas3D::update_volumes_colors_by_extruder()
void GLCanvas3D::render()
{
- if (m_in_render)
+ if (!m_render_enabled || m_in_render)
{
// if called recursively, return
m_dirty = true;
@@ -1672,7 +1670,7 @@ void GLCanvas3D::ensure_on_bed(unsigned int object_idx)
for (GLVolume* volume : m_volumes.volumes)
{
- if ((volume->object_idx() == object_idx) && !volume->is_modifier)
+ if ((volume->object_idx() == (int)object_idx) && !volume->is_modifier)
{
double min_z = volume->transformed_convex_hull_bounding_box().min(2);
std::pair<int, int> instance = std::make_pair(volume->object_idx(), volume->instance_idx());
@@ -1968,8 +1966,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
}
}
- // stores the current volumes count
- size_t volumes_count = m_volumes.volumes.size();
+// // stores the current volumes count
+// size_t volumes_count = m_volumes.volumes.size();
for (size_t istep = 0; istep < sla_steps.size(); ++istep)
if (!instances[istep].empty())
@@ -1978,7 +1976,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
for (GLVolume* volume : m_volumes.volumes)
- if (volume->object_idx() < m_model->objects.size() && m_model->objects[volume->object_idx()]->instances[volume->instance_idx()]->is_printable())
+ if (volume->object_idx() < (int)m_model->objects.size() && m_model->objects[volume->object_idx()]->instances[volume->instance_idx()]->is_printable())
volume->set_sla_shift_z(shift_zs[volume->object_idx()]);
}
@@ -3733,7 +3731,7 @@ bool GLCanvas3D::_init_undoredo_toolbar()
item.right.render_callback = [this](float left, float right, float, float) { if (m_canvas != nullptr) _render_undo_redo_stack(true, 0.5f * (left + right)); };
item.enabling_callback = [this]()->bool {
bool can_undo = wxGetApp().plater()->can_undo();
- unsigned int id = m_undoredo_toolbar.get_item_id("undo");
+ int id = m_undoredo_toolbar.get_item_id("undo");
std::string curr_additional_tooltip;
m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip);
@@ -3765,7 +3763,7 @@ bool GLCanvas3D::_init_undoredo_toolbar()
item.right.render_callback = [this](float left, float right, float, float) { if (m_canvas != nullptr) _render_undo_redo_stack(false, 0.5f * (left + right)); };
item.enabling_callback = [this]()->bool {
bool can_redo = wxGetApp().plater()->can_redo();
- unsigned int id = m_undoredo_toolbar.get_item_id("redo");
+ int id = m_undoredo_toolbar.get_item_id("redo");
std::string curr_additional_tooltip;
m_undoredo_toolbar.get_additional_tooltip(id, curr_additional_tooltip);
@@ -3908,7 +3906,7 @@ void GLCanvas3D::_picking_pass() const
m_gizmos.set_hover_id(-1);
}
else
- m_gizmos.set_hover_id(inside && volume_id <= GLGizmoBase::BASE_ID ? (GLGizmoBase::BASE_ID - volume_id) : -1);
+ m_gizmos.set_hover_id(inside && (unsigned int)volume_id <= GLGizmoBase::BASE_ID ? ((int)GLGizmoBase::BASE_ID - volume_id) : -1);
_update_volumes_hover_state();
}
@@ -4858,7 +4856,7 @@ void GLCanvas3D::_load_wipe_tower_toolpaths(const std::vector<std::string>& str_
ctxt.print = print;
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
if (print->wipe_tower_data().priming && print->config().single_extruder_multi_material_priming)
- for (int i=0; i<print->wipe_tower_data().priming.get()->size(); ++i)
+ for (int i=0; i<(int)print->wipe_tower_data().priming.get()->size(); ++i)
ctxt.priming.emplace_back(print->wipe_tower_data().priming.get()->at(i));
if (print->wipe_tower_data().final_purge)
ctxt.final.emplace_back(*print->wipe_tower_data().final_purge.get());
@@ -5037,7 +5035,7 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
}
case GCodePreviewData::Extrusion::ColorPrint:
{
- const size_t color_cnt = tool_colors.size() / 4;
+ int color_cnt = (int)tool_colors.size() / 4;
int val = int(value);
while (val >= color_cnt)
diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp
index 0beef094b..202d3ef77 100644
--- a/src/slic3r/GUI/GLCanvas3D.hpp
+++ b/src/slic3r/GUI/GLCanvas3D.hpp
@@ -403,6 +403,7 @@ private:
std::unique_ptr<RetinaHelper> m_retina_helper;
#endif
bool m_in_render;
+ bool m_render_enabled;
LegendTexture m_legend_texture;
WarningTexture m_warning_texture;
wxTimer m_timer;
@@ -433,7 +434,6 @@ private:
bool m_initialized;
bool m_apply_zoom_to_volumes_filter;
mutable std::vector<int> m_hover_volume_idxs;
- bool m_warning_texture_enabled;
bool m_legend_texture_enabled;
bool m_picking_enabled;
bool m_moving_enabled;
@@ -533,6 +533,9 @@ public:
void enable_dynamic_background(bool enable);
void allow_multisample(bool allow);
+ void enable_render(bool enable) { m_render_enabled = enable; }
+ bool is_render_enabled() const { return m_render_enabled; }
+
void zoom_to_bed();
void zoom_to_volumes();
void zoom_to_selection();
@@ -641,11 +644,9 @@ public:
void start_keeping_dirty() { m_keep_dirty = true; }
void stop_keeping_dirty() { m_keep_dirty = false; }
- unsigned int get_main_toolbar_item_id(const std::string& name) const { return m_main_toolbar.get_item_id(name); }
- void force_main_toolbar_left_action(unsigned int item_id) { m_main_toolbar.force_left_action(item_id, *this); }
- void force_main_toolbar_right_action(unsigned int item_id) { m_main_toolbar.force_right_action(item_id, *this); }
- void get_undoredo_toolbar_additional_tooltip(unsigned int item_id, std::string& text) { return m_undoredo_toolbar.get_additional_tooltip(item_id, text); }
- void set_undoredo_toolbar_additional_tooltip(unsigned int item_id, const std::string& text) { m_undoredo_toolbar.set_additional_tooltip(item_id, text); }
+ int get_main_toolbar_item_id(const std::string& name) const { return m_main_toolbar.get_item_id(name); }
+ void force_main_toolbar_left_action(int item_id) { m_main_toolbar.force_left_action(item_id, *this); }
+ void force_main_toolbar_right_action(int item_id) { m_main_toolbar.force_right_action(item_id, *this); }
bool has_toolpaths_to_export() const;
void export_toolpaths_to_obj(const char* filename) const;
diff --git a/src/slic3r/GUI/GLCanvas3DManager.cpp b/src/slic3r/GUI/GLCanvas3DManager.cpp
index 59a34d8cd..5fbefcc6e 100644
--- a/src/slic3r/GUI/GLCanvas3DManager.cpp
+++ b/src/slic3r/GUI/GLCanvas3DManager.cpp
@@ -359,9 +359,7 @@ bool GLCanvas3DManager::init(GLCanvas3D& canvas)
void GLCanvas3DManager::detect_multisample(int* attribList)
{
int wxVersion = wxMAJOR_VERSION * 10000 + wxMINOR_VERSION * 100 + wxRELEASE_NUMBER;
- const AppConfig* app_config = GUI::get_app_config();
bool enable_multisample = wxVersion >= 30003;
-
s_multisample = (enable_multisample && wxGLCanvas::IsDisplaySupported(attribList)) ? MS_Enabled : MS_Disabled;
// Alternative method: it was working on previous version of wxWidgets but not with the latest, at least on Windows
// s_multisample = enable_multisample && wxGLCanvas::IsExtensionSupported("WGL_ARB_multisample");
diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp
index 4fdf12489..55ca5f723 100644
--- a/src/slic3r/GUI/GLTexture.cpp
+++ b/src/slic3r/GUI/GLTexture.cpp
@@ -56,7 +56,7 @@ bool GLTexture::Compressor::unsent_compressed_data_available() const
{
if (m_levels.empty())
return false;
- // Querying the atomic m_num_levels_compressed value synchronizes processor caches, so that the dat of m_levels modified by the worker thread are accessible to the calling thread.
+ // Querying the atomic m_num_levels_compressed value synchronizes processor caches, so that the data of m_levels modified by the worker thread are accessible to the calling thread.
unsigned int num_compressed = m_num_levels_compressed;
for (unsigned int i = 0; i < num_compressed; ++ i)
if (! m_levels[i].sent_to_gpu && ! m_levels[i].compressed_data.empty())
@@ -89,8 +89,8 @@ void GLTexture::Compressor::send_compressed_data_to_gpu()
}
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
- if (num_compressed == (unsigned int)m_levels.size())
- // Finalize the worker thread, close it.
+ if (num_compressed == (int)m_levels.size())
+ // Finalize the worker thread, close it.
this->reset();
}
diff --git a/src/slic3r/GUI/GLToolbar.cpp b/src/slic3r/GUI/GLToolbar.cpp
index 63387bf2d..51d787d9d 100644
--- a/src/slic3r/GUI/GLToolbar.cpp
+++ b/src/slic3r/GUI/GLToolbar.cpp
@@ -345,9 +345,9 @@ bool GLToolbar::is_any_item_pressed() const
return false;
}
-unsigned int GLToolbar::get_item_id(const std::string& name) const
+int GLToolbar::get_item_id(const std::string& name) const
{
- for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i)
+ for (int i = 0; i < (int)m_items.size(); ++i)
{
if (m_items[i]->get_name() == name)
return i;
@@ -356,19 +356,9 @@ unsigned int GLToolbar::get_item_id(const std::string& name) const
return -1;
}
-void GLToolbar::force_left_action(unsigned int item_id, GLCanvas3D& parent)
-{
- do_action(GLToolbarItem::Left, item_id, parent, false);
-}
-
-void GLToolbar::force_right_action(unsigned int item_id, GLCanvas3D& parent)
-{
- do_action(GLToolbarItem::Right, item_id, parent, false);
-}
-
-void GLToolbar::get_additional_tooltip(unsigned int item_id, std::string& text)
+void GLToolbar::get_additional_tooltip(int item_id, std::string& text)
{
- if (item_id < (unsigned int)m_items.size())
+ if ((0 <= item_id) && (item_id < (int)m_items.size()))
{
GLToolbarItem* item = m_items[item_id];
if (item != nullptr)
@@ -381,9 +371,9 @@ void GLToolbar::get_additional_tooltip(unsigned int item_id, std::string& text)
text = L("");
}
-void GLToolbar::set_additional_tooltip(unsigned int item_id, const std::string& text)
+void GLToolbar::set_additional_tooltip(int item_id, const std::string& text)
{
- if (item_id < (unsigned int)m_items.size())
+ if ((0 <= item_id) && (item_id < (int)m_items.size()))
{
GLToolbarItem* item = m_items[item_id];
if (item != nullptr)
@@ -466,7 +456,7 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
if ((item_id != -2) && !m_items[item_id]->is_separator() && ((m_pressed_toggable_id == -1) || (m_items[item_id]->get_last_action_type() == GLToolbarItem::Left)))
{
// mouse is inside an icon
- do_action(GLToolbarItem::Left, (unsigned int)item_id, parent, true);
+ do_action(GLToolbarItem::Left, item_id, parent, true);
parent.set_as_dirty();
}
}
@@ -483,7 +473,7 @@ bool GLToolbar::on_mouse(wxMouseEvent& evt, GLCanvas3D& parent)
if ((item_id != -2) && !m_items[item_id]->is_separator() && ((m_pressed_toggable_id == -1) || (m_items[item_id]->get_last_action_type() == GLToolbarItem::Right)))
{
// mouse is inside an icon
- do_action(GLToolbarItem::Right, (unsigned int)item_id, parent, true);
+ do_action(GLToolbarItem::Right, item_id, parent, true);
parent.set_as_dirty();
}
}
@@ -556,11 +546,11 @@ float GLToolbar::get_main_size() const
return size * m_layout.scale;
}
-void GLToolbar::do_action(GLToolbarItem::EActionType type, unsigned int item_id, GLCanvas3D& parent, bool check_hover)
+void GLToolbar::do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas3D& parent, bool check_hover)
{
if ((m_pressed_toggable_id == -1) || (m_pressed_toggable_id == item_id))
{
- if (item_id < (unsigned int)m_items.size())
+ if ((0 <= item_id) && (item_id < (int)m_items.size()))
{
GLToolbarItem* item = m_items[item_id];
if ((item != nullptr) && !item->is_separator() && (!check_hover || item->is_hovered()))
@@ -871,11 +861,10 @@ int GLToolbar::contains_mouse_horizontal(const Vec2d& mouse_pos, const GLCanvas3
float left = m_layout.left + scaled_border;
float top = m_layout.top - scaled_border;
- int id = -1;
-
- for (GLToolbarItem* item : m_items)
+
+ for (size_t id=0; id<m_items.size(); ++id)
{
- ++id;
+ GLToolbarItem* item = m_items[id];
if (!item->is_visible())
continue;
@@ -946,11 +935,9 @@ int GLToolbar::contains_mouse_vertical(const Vec2d& mouse_pos, const GLCanvas3D&
float left = m_layout.left + scaled_border;
float top = m_layout.top - scaled_border;
- int id = -1;
-
- for (GLToolbarItem* item : m_items)
+ for (size_t id=0; id<m_items.size(); ++id)
{
- ++id;
+ GLToolbarItem* item = m_items[id];
if (!item->is_visible())
continue;
@@ -1246,7 +1233,7 @@ bool GLToolbar::update_items_enabled_state()
{
bool ret = false;
- for (unsigned int i = 0; i < (unsigned int)m_items.size(); ++i)
+ for (int i = 0; i < (int)m_items.size(); ++i)
{
GLToolbarItem* item = m_items[i];
ret |= item->update_enabled_state();
diff --git a/src/slic3r/GUI/GLToolbar.hpp b/src/slic3r/GUI/GLToolbar.hpp
index 527317e58..07da836fc 100644
--- a/src/slic3r/GUI/GLToolbar.hpp
+++ b/src/slic3r/GUI/GLToolbar.hpp
@@ -254,7 +254,7 @@ private:
MouseCapture m_mouse_capture;
std::string m_tooltip;
- unsigned int m_pressed_toggable_id;
+ int m_pressed_toggable_id;
public:
GLToolbar(EType type, const std::string& name);
@@ -293,15 +293,15 @@ public:
bool is_any_item_pressed() const;
- unsigned int get_item_id(const std::string& name) const;
+ int get_item_id(const std::string& name) const;
- void force_left_action(unsigned int item_id, GLCanvas3D& parent);
- void force_right_action(unsigned int item_id, GLCanvas3D& parent);
+ void force_left_action(int item_id, GLCanvas3D& parent) { do_action(GLToolbarItem::Left, item_id, parent, false); }
+ void force_right_action(int item_id, GLCanvas3D& parent) { do_action(GLToolbarItem::Right, item_id, parent, false); }
const std::string& get_tooltip() const { return m_tooltip; }
- void get_additional_tooltip(unsigned int item_id, std::string& text);
- void set_additional_tooltip(unsigned int item_id, const std::string& text);
+ void get_additional_tooltip(int item_id, std::string& text);
+ void set_additional_tooltip(int item_id, const std::string& text);
// returns true if any item changed its state
bool update_items_state();
@@ -317,7 +317,7 @@ private:
float get_height_horizontal() const;
float get_height_vertical() const;
float get_main_size() const;
- void do_action(GLToolbarItem::EActionType type, unsigned int item_id, GLCanvas3D& parent, bool check_hover);
+ void do_action(GLToolbarItem::EActionType type, int item_id, GLCanvas3D& parent, bool check_hover);
std::string update_hover_state(const Vec2d& mouse_pos, GLCanvas3D& parent);
std::string update_hover_state_horizontal(const Vec2d& mouse_pos, GLCanvas3D& parent);
std::string update_hover_state_vertical(const Vec2d& mouse_pos, GLCanvas3D& parent);
diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp
index 826f2d6fc..f94372667 100644
--- a/src/slic3r/GUI/GUI.cpp
+++ b/src/slic3r/GUI/GUI.cpp
@@ -262,7 +262,7 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
}
catch (const std::exception & /* e */)
{
- int i = 0;//no reason, just experiment
+ // int i = 0;//no reason, just experiment
}
}
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 1b2da4769..80c02ea78 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -302,8 +302,9 @@ bool GUI_App::on_init_inner()
* change min hight of object list to the normal min value (15 * wxGetApp().em_unit())
* after first whole Mainframe updating/layouting
*/
- if (obj_list()->GetMinSize().GetY() > 15 * em_unit())
- obj_list()->SetMinSize(wxSize(-1, 15 * em_unit()));
+ const int list_min_height = 15 * em_unit();
+ if (obj_list()->GetMinSize().GetY() > list_min_height)
+ obj_list()->SetMinSize(wxSize(-1, list_min_height));
update_mode(); // update view mode after fix of the object_list size
@@ -474,8 +475,9 @@ void GUI_App::recreate_GUI()
* change min hight of object list to the normal min value (15 * wxGetApp().em_unit())
* after first whole Mainframe updating/layouting
*/
- if (obj_list()->GetMinSize().GetY() > 15 * em_unit())
- obj_list()->SetMinSize(wxSize(-1, 15 * em_unit()));
+ const int list_min_height = 15 * em_unit();
+ if (obj_list()->GetMinSize().GetY() > list_min_height)
+ obj_list()->SetMinSize(wxSize(-1, list_min_height));
update_mode();
@@ -908,11 +910,13 @@ bool GUI_App::check_unsaved_changes(const wxString &header)
wxString dirty;
PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology();
for (Tab *tab : tabs_list)
- if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty())
+ if (tab->supports_printer_technology(printer_technology) && tab->current_preset_is_dirty()) {
if (dirty.empty())
dirty = tab->title();
else
dirty += wxString(", ") + tab->title();
+ }
+
if (dirty.empty())
// No changes, the application may close or reload presets.
return true;
@@ -1085,7 +1089,7 @@ void GUI_App::window_pos_restore(wxTopLevelWindow* window, const std::string &na
void GUI_App::window_pos_sanitize(wxTopLevelWindow* window)
{
- unsigned display_idx = wxDisplay::GetFromWindow(window);
+ /*unsigned*/int display_idx = wxDisplay::GetFromWindow(window);
wxRect display;
if (display_idx == wxNOT_FOUND) {
display = wxDisplay(0u).GetClientArea();
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 7ba26f471..a79426ed2 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -29,7 +29,7 @@ namespace GUI
wxDEFINE_EVENT(EVT_OBJ_LIST_OBJECT_SELECT, SimpleEvent);
// pt_FFF
-SettingsBundle FREQ_SETTINGS_BUNDLE_FFF =
+static SettingsBundle FREQ_SETTINGS_BUNDLE_FFF =
{
{ L("Layers and Perimeters"), { "layer_height" , "perimeters", "top_solid_layers", "bottom_solid_layers" } },
{ L("Infill") , { "fill_density", "fill_pattern" } },
@@ -40,13 +40,13 @@ SettingsBundle FREQ_SETTINGS_BUNDLE_FFF =
};
// pt_SLA
-SettingsBundle FREQ_SETTINGS_BUNDLE_SLA =
+static SettingsBundle FREQ_SETTINGS_BUNDLE_SLA =
{
{ L("Pad and Support") , { "supports_enable", "pad_enable" } }
};
// Note: id accords to type of the sub-object (adding volume), so sequence of the menu items is important
-std::vector<std::pair<std::string, std::string>> ADD_VOLUME_MENU_ITEMS = {
+static std::vector<std::pair<std::string, std::string>> ADD_VOLUME_MENU_ITEMS = {
// menu_item Name menu_item bitmap name
{L("Add part"), "add_part" }, // ~ModelVolumeType::MODEL_PART
{L("Add modifier"), "add_modifier"}, // ~ModelVolumeType::PARAMETER_MODIFIER
@@ -126,7 +126,7 @@ ObjectList::ObjectList(wxWindow* parent) :
#ifdef __WXMSW__
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
int new_selected_column = -1;
-#endif __WXMSW__
+#endif //__WXMSW__
if (wxGetKeyState(WXK_SHIFT))
{
wxDataViewItemArray sels;
@@ -149,12 +149,12 @@ ObjectList::ObjectList(wxWindow* parent) :
wxUIActionSimulator sim;
sim.Char(WXK_RETURN);
}
-#endif __WXMSW__
+#endif //__WXMSW__
m_last_selected_item = new_selected_item;
}
#ifdef __WXMSW__
m_last_selected_column = new_selected_column;
-#endif __WXMSW__
+#endif //__WXMSW__
selection_changed();
#ifndef __WXMSW__
@@ -192,7 +192,7 @@ ObjectList::ObjectList(wxWindow* parent) :
this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->undo(); }, wxID_UNDO);
this->Bind(wxEVT_MENU, [this](wxCommandEvent &evt) { this->redo(); }, wxID_REDO);
}
-#else __WXOSX__
+#else //__WXOSX__
Bind(wxEVT_CHAR, [this](wxKeyEvent& event) { key_event(event); }); // doesn't work on OSX
#endif
@@ -281,9 +281,9 @@ void ObjectList::create_popup_menus()
create_instance_popupmenu(&m_menu_instance);
}
-void ObjectList::get_selected_item_indexes(int& obj_idx, int& vol_idx, const wxDataViewItem& input_item/* = wxDataViewItem(0)*/)
+void ObjectList::get_selected_item_indexes(int& obj_idx, int& vol_idx, const wxDataViewItem& input_item/* = wxDataViewItem(nullptr)*/)
{
- const wxDataViewItem item = input_item == wxDataViewItem(0) ? GetSelection() : input_item;
+ const wxDataViewItem item = input_item == wxDataViewItem(nullptr) ? GetSelection() : input_item;
if (!item)
{
@@ -422,7 +422,7 @@ DynamicPrintConfig& ObjectList::get_item_config(const wxDataViewItem& item) cons
(*m_objects)[obj_idx]->config;
}
-wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_count)
+wxDataViewColumn* ObjectList::create_objects_list_extruder_column(size_t extruders_count)
{
wxArrayString choices;
choices.Add(_(L("default")));
@@ -435,9 +435,9 @@ wxDataViewColumn* ObjectList::create_objects_list_extruder_column(int extruders_
return column;
}
-void ObjectList::update_extruder_values_for_items(const int max_extruder)
+void ObjectList::update_extruder_values_for_items(const size_t max_extruder)
{
- for (int i = 0; i < m_objects->size(); ++i)
+ for (size_t i = 0; i < m_objects->size(); ++i)
{
wxDataViewItem item = m_objects_model->GetItemById(i);
if (!item) continue;
@@ -453,7 +453,7 @@ void ObjectList::update_extruder_values_for_items(const int max_extruder)
m_objects_model->SetValue(extruder, item, colExtruder);
if (object->volumes.size() > 1) {
- for (auto id = 0; id < object->volumes.size(); id++) {
+ for (size_t id = 0; id < object->volumes.size(); id++) {
item = m_objects_model->GetItemByVolumeId(i, id);
if (!item) continue;
if (!object->volumes[id]->config.has("extruder") ||
@@ -468,7 +468,7 @@ void ObjectList::update_extruder_values_for_items(const int max_extruder)
}
}
-void ObjectList::update_objects_list_extruder_column(int extruders_count)
+void ObjectList::update_objects_list_extruder_column(size_t extruders_count)
{
if (!this) return; // #ys_FIXME
if (printer_technology() == ptSLA)
@@ -737,7 +737,7 @@ void ObjectList::paste_volumes_into_list(int obj_idx, const ModelVolumePtrs& vol
if (items.size() > 1)
{
m_selection_mode = smVolume;
- m_last_selected_item = wxDataViewItem(0);
+ m_last_selected_item = wxDataViewItem(nullptr);
}
select_items(items);
@@ -839,7 +839,7 @@ void ObjectList::show_context_menu()
wxMenu* menu = type & itInstance ? &m_menu_instance :
type & itLayer ? &m_menu_layer :
- m_objects_model->GetParent(item) != wxDataViewItem(0) ? &m_menu_part :
+ m_objects_model->GetParent(item) != wxDataViewItem(nullptr) ? &m_menu_part :
printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object;
if (!(type & itInstance))
@@ -910,9 +910,9 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
const bool mult_sel = multiple_selection();
- if (mult_sel && !selected_instances_of_same_object() ||
- !mult_sel && (GetSelection() != item ||
- m_objects_model->GetParent(item) == wxDataViewItem(0) ) ) {
+ if ((mult_sel && !selected_instances_of_same_object()) ||
+ (!mult_sel && (GetSelection() != item)) ||
+ m_objects_model->GetParent(item) == wxDataViewItem(nullptr) ) {
event.Veto();
return;
}
@@ -957,10 +957,10 @@ void ObjectList::OnBeginDrag(wxDataViewEvent &event)
bool ObjectList::can_drop(const wxDataViewItem& item) const
{
- return m_dragged_data.type() == itInstance && !item.IsOk() ||
- m_dragged_data.type() == itVolume && item.IsOk() &&
+ return (m_dragged_data.type() == itInstance && !item.IsOk()) ||
+ (m_dragged_data.type() == itVolume && item.IsOk() &&
m_objects_model->GetItemType(item) == itVolume &&
- m_dragged_data.obj_idx() == m_objects_model->GetObjectIdByItem(item);
+ m_dragged_data.obj_idx() == m_objects_model->GetObjectIdByItem(item));
}
void ObjectList::OnDropPossible(wxDataViewEvent &event)
@@ -1069,8 +1069,8 @@ const std::vector<std::string>& ObjectList::get_options_for_bundle(const wxStrin
static bool improper_category(const std::string& category, const int extruders_cnt, const bool is_object_settings = true)
{
return category.empty() ||
- extruders_cnt == 1 && (category == "Extruders" || category == "Wipe options" ) ||
- !is_object_settings && category == "Support material";
+ (extruders_cnt == 1 && (category == "Extruders" || category == "Wipe options" )) ||
+ (!is_object_settings && category == "Support material");
}
void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part)
@@ -1326,7 +1326,7 @@ void ObjectList::append_menu_items_add_volume(wxMenu* menu)
return;
}
- for (int type = mode == comExpert ? 0 : 1 ; type < ADD_VOLUME_MENU_ITEMS.size(); type++)
+ for (size_t type = (mode == comExpert ? 0 : 1) ; type < ADD_VOLUME_MENU_ITEMS.size(); type++)
{
auto& item = ADD_VOLUME_MENU_ITEMS[type];
@@ -1397,7 +1397,7 @@ wxMenuItem* ObjectList::append_menu_item_settings(wxMenu* menu_)
// Create new items for settings popupmenu
if (printer_technology() == ptFFF ||
- menu->GetMenuItems().size() > 0 && !menu->GetMenuItems().back()->IsSeparator())
+ (menu->GetMenuItems().size() > 0 && !menu->GetMenuItems().back()->IsSeparator()))
menu->SetFirstSeparator();
// Add frequently settings
@@ -1430,9 +1430,9 @@ wxMenuItem* ObjectList::append_menu_item_instance_to_object(wxMenu* menu, wxWind
[this](wxCommandEvent&) { split_instances(); }, "", menu, [](){return wxGetApp().plater()->can_set_instance_to_object(); }, parent);
}
-wxMenuItem* ObjectList::append_menu_item_printable(wxMenu* menu, wxWindow* parent)
+wxMenuItem* ObjectList::append_menu_item_printable(wxMenu* menu, wxWindow* /*parent*/)
{
- return append_menu_check_item(menu, wxID_ANY, _(L("Printable")), "", [this](wxCommandEvent&) {
+ return append_menu_check_item(menu, wxID_ANY, _(L("Printable")), "", [](wxCommandEvent&) {
wxGetApp().plater()->canvas3D()->get_selection().toggle_instance_printable_state();
}, menu);
}
@@ -1505,7 +1505,7 @@ void ObjectList::append_menu_item_delete(wxMenu* menu)
void ObjectList::append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu)
{
append_menu_item(menu, wxID_ANY, _(L("Scale to print volume")), _(L("Scale the selected object to fit the print volume")),
- [this](wxCommandEvent&) { wxGetApp().plater()->scale_selection_to_fit_print_volume(); }, "", menu);
+ [](wxCommandEvent&) { wxGetApp().plater()->scale_selection_to_fit_print_volume(); }, "", menu);
}
void ObjectList::create_object_popupmenu(wxMenu *menu)
@@ -1571,7 +1571,7 @@ void ObjectList::create_instance_popupmenu(wxMenu*menu)
* 2. Separate selected instances from the initial object to the separated object,
* if some (not all) instances are selected
*/
- wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [this](wxUpdateUIEvent& evt) {
+ wxGetApp().plater()->Bind(wxEVT_UPDATE_UI, [](wxUpdateUIEvent& evt) {
// evt.Enable(can_split_instances()); }, m_menu_item_split_instances->GetId());
evt.SetText(wxGetApp().plater()->canvas3D()->get_selection().is_single_full_object() ?
_(L("Set as a Separated Objects")) : _(L("Set as a Separated Object")));
@@ -1583,7 +1583,7 @@ wxMenu* ObjectList::create_settings_popupmenu(wxMenu *parent_menu)
wxMenu *menu = new wxMenu;
settings_menu_hierarchy settings_menu;
- const bool is_part = m_objects_model->GetParent(GetSelection()) != wxDataViewItem(0);
+ const bool is_part = m_objects_model->GetParent(GetSelection()) != wxDataViewItem(nullptr);
get_options_menu(settings_menu, is_part);
for (auto cat : settings_menu) {
@@ -1676,7 +1676,7 @@ void ObjectList::load_part( ModelObject* model_object,
wxArrayString input_files;
wxGetApp().import_model(parent, input_files);
- for (int i = 0; i < input_files.size(); ++i) {
+ for (size_t i = 0; i < input_files.size(); ++i) {
std::string input_file = input_files.Item(i).ToUTF8().data();
Model model;
@@ -1714,7 +1714,7 @@ void ObjectList::load_part( ModelObject* model_object,
void ObjectList::load_generic_subobject(const std::string& type_name, const ModelVolumeType type)
{
- const auto obj_idx = get_selected_obj_idx();
+ const int obj_idx = get_selected_obj_idx();
if (obj_idx < 0)
return;
@@ -1847,9 +1847,9 @@ void ObjectList::del_settings_from_config(const wxDataViewItem& parent_item)
{
const bool is_layer_settings = m_objects_model->GetItemType(parent_item) == itLayer;
- const int opt_cnt = m_config->keys().size();
- if (opt_cnt == 1 && m_config->has("extruder") ||
- is_layer_settings && opt_cnt == 2 && m_config->has("extruder") && m_config->has("layer_height"))
+ const size_t opt_cnt = m_config->keys().size();
+ if ((opt_cnt == 1 && m_config->has("extruder")) ||
+ (is_layer_settings && opt_cnt == 2 && m_config->has("extruder") && m_config->has("layer_height")))
return;
take_snapshot(_(L("Delete Settings")));
@@ -2047,13 +2047,13 @@ wxDataViewItem ObjectList::add_layer_root_item(const wxDataViewItem obj_item)
if (obj_idx < 0 ||
object(obj_idx)->layer_config_ranges.empty() ||
printer_technology() == ptSLA)
- return wxDataViewItem(0);
+ return wxDataViewItem(nullptr);
// create LayerRoot item
wxDataViewItem layers_item = m_objects_model->AddLayersRoot(obj_item);
// and create Layer item(s) according to the layer_config_ranges
- for (const auto range : object(obj_idx)->layer_config_ranges)
+ for (const auto& range : object(obj_idx)->layer_config_ranges)
add_layer_item(range.first, layers_item);
Expand(layers_item);
@@ -2145,7 +2145,7 @@ void ObjectList::part_selection_changed()
const auto item = GetSelection();
- if ( multiple_selection() || item && m_objects_model->GetItemType(item) == itInstanceRoot )
+ if ( multiple_selection() || (item && m_objects_model->GetItemType(item) == itInstanceRoot ))
{
og_name = _(L("Group manipulation"));
@@ -2157,7 +2157,7 @@ void ObjectList::part_selection_changed()
{
if (item)
{
- if (m_objects_model->GetParent(item) == wxDataViewItem(0)) {
+ if (m_objects_model->GetParent(item) == wxDataViewItem(nullptr)) {
obj_idx = m_objects_model->GetIdByItem(item);
og_name = _(L("Object manipulation"));
m_config = &(*m_objects)[obj_idx]->config;
@@ -2276,7 +2276,7 @@ SettingsBundle ObjectList::get_item_settings_bundle(const DynamicPrintConfig* co
// Add new SettingsItem for parent_item if it doesn't exist, or just update a digest according to new config
wxDataViewItem ObjectList::add_settings_item(wxDataViewItem parent_item, const DynamicPrintConfig* config)
{
- wxDataViewItem ret = wxDataViewItem(0);
+ wxDataViewItem ret = wxDataViewItem(nullptr);
if (!parent_item)
return ret;
@@ -2332,7 +2332,7 @@ void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed)
if (model_object->instances.size()>1)
{
std::vector<bool> print_idicator(model_object->instances.size());
- for (int i = 0; i < model_object->instances.size(); ++i)
+ for (size_t i = 0; i < model_object->instances.size(); ++i)
print_idicator[i] = model_object->instances[i]->printable;
const wxDataViewItem object_item = m_objects_model->GetItemById(obj_idx);
@@ -2359,7 +2359,7 @@ void ObjectList::delete_object_from_list()
auto item = GetSelection();
if (!item)
return;
- if (m_objects_model->GetParent(item) == wxDataViewItem(0))
+ if (m_objects_model->GetParent(item) == wxDataViewItem(nullptr))
select_item(m_objects_model->Delete(item));
else
select_item(m_objects_model->Delete(m_objects_model->GetParent(item)));
@@ -2516,7 +2516,7 @@ void ObjectList::remove()
wxDataViewItemArray sels;
GetSelections(sels);
- wxDataViewItem parent = wxDataViewItem(0);
+ wxDataViewItem parent = wxDataViewItem(nullptr);
if (sels.Count() == 1)
parent = delete_item(GetSelection());
@@ -2565,7 +2565,14 @@ static double get_min_layer_height(const int extruder_idx)
static double get_max_layer_height(const int extruder_idx)
{
const DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
- return config.opt_float("max_layer_height", extruder_idx <= 0 ? 0 : extruder_idx-1);
+ int extruder_idx_zero_based = extruder_idx <= 0 ? 0 : extruder_idx-1;
+ double max_layer_height = config.opt_float("max_layer_height", extruder_idx_zero_based);
+
+ // In case max_layer_height is set to zero, it should default to 75 % of nozzle diameter:
+ if (max_layer_height < EPSILON)
+ max_layer_height = 0.75 * config.opt_float("nozzle_diameter", extruder_idx_zero_based);
+
+ return max_layer_height;
}
void ObjectList::add_layer_range_after_current(const t_layer_height_range& current_range)
@@ -2583,7 +2590,7 @@ void ObjectList::add_layer_range_after_current(const t_layer_height_range& curre
{
take_snapshot(_(L("Add Height Range")));
- const t_layer_height_range& new_range = { last_range.second, last_range.second + 2.0f };
+ const t_layer_height_range& new_range = { last_range.second, last_range.second + 2. };
ranges[new_range] = get_default_layer_config(obj_idx);
add_layer_item(new_range, layers_item);
}
@@ -2606,7 +2613,7 @@ void ObjectList::add_layer_range_after_current(const t_layer_height_range& curre
if (delta < get_min_layer_height(old_config.opt_int("extruder"))/*0.05f*/) // next range division has no sense
return;
- const coordf_t midl_layer = next_range.first + 0.5f * delta;
+ const coordf_t midl_layer = next_range.first + 0.5 * delta;
t_layer_height_range new_range = { midl_layer, next_range.second };
@@ -2706,7 +2713,7 @@ bool ObjectList::edit_layer_range(const t_layer_height_range& range, const t_lay
if (root_item.IsOk())
// create Layer item(s) according to the layer_config_ranges
- for (const auto r : ranges)
+ for (const auto& r : ranges)
add_layer_item(r.first, root_item);
select_item(sel_type&itLayer ? m_objects_model->GetItemByLayerRange(obj_idx, new_range) : root_item);
@@ -3023,7 +3030,7 @@ void ObjectList::select_item_all_children()
// There is no selection before OR some object is selected => select all objects
if (!GetSelection() || m_objects_model->GetItemType(GetSelection()) == itObject) {
- for (int i = 0; i < m_objects->size(); i++)
+ for (size_t i = 0; i < m_objects->size(); i++)
sels.Add(m_objects_model->GetItemById(i));
m_selection_mode = smInstance;
}
@@ -3049,7 +3056,7 @@ void ObjectList::update_selection_mode()
// All items are unselected
if (!GetSelection())
{
- m_last_selected_item = wxDataViewItem(0);
+ m_last_selected_item = wxDataViewItem(nullptr);
m_selection_mode = smUndef;
return;
}
@@ -3091,9 +3098,9 @@ bool ObjectList::check_last_selection(wxString& msg_str)
if (impossible_multi_selection(itVolume, smVolume) ||
impossible_multi_selection(itLayer, smLayer ) ||
type & itSettings ||
- type & itVolume && !(m_selection_mode & smVolume ) ||
- type & itLayer && !(m_selection_mode & smLayer ) ||
- type & itInstance && !(m_selection_mode & smInstance)
+ (type & itVolume && !(m_selection_mode & smVolume )) ||
+ (type & itLayer && !(m_selection_mode & smLayer )) ||
+ (type & itInstance && !(m_selection_mode & smInstance))
)
{
// Inform user why selection isn't complited
@@ -3146,7 +3153,7 @@ void ObjectList::fix_multiselection_conflicts()
const ItemType item_type = m_selection_mode & smVolume ? itVolume : itLayer;
- for (const auto child : children)
+ for (const auto& child : children)
if (IsSelected(child) && m_objects_model->GetItemType(child) & item_type)
sels.Add(child);
@@ -3156,7 +3163,7 @@ void ObjectList::fix_multiselection_conflicts()
}
else
{
- for (const auto item : sels)
+ for (const auto& item : sels)
{
if (!IsSelected(item)) // if this item is unselected now (from previous actions)
continue;
@@ -3167,13 +3174,13 @@ void ObjectList::fix_multiselection_conflicts()
}
const wxDataViewItem& parent = m_objects_model->GetParent(item);
- if (parent != wxDataViewItem(0) && IsSelected(parent))
+ if (parent != wxDataViewItem(nullptr) && IsSelected(parent))
Unselect(parent);
else
{
wxDataViewItemArray unsels;
m_objects_model->GetAllChildren(item, unsels);
- for (const auto unsel_item : unsels)
+ for (const auto& unsel_item : unsels)
Unselect(unsel_item);
}
@@ -3188,7 +3195,7 @@ void ObjectList::fix_multiselection_conflicts()
show_info(this, msg_string, _(L("Info")));
if (!IsSelected(m_last_selected_item))
- m_last_selected_item = wxDataViewItem(0);
+ m_last_selected_item = wxDataViewItem(nullptr);
m_prevent_list_events = false;
}
@@ -3262,7 +3269,7 @@ void ObjectList::change_part_type()
void ObjectList::last_volume_is_deleted(const int obj_idx)
{
- if (obj_idx < 0 || obj_idx >= m_objects->size() || (*m_objects)[obj_idx]->volumes.size() != 1)
+ if (obj_idx < 0 || size_t(obj_idx) >= m_objects->size() || (*m_objects)[obj_idx]->volumes.size() != 1)
return;
auto volume = (*m_objects)[obj_idx]->volumes.front();
@@ -3329,7 +3336,7 @@ void ObjectList::update_object_list_by_printer_technology()
GetSelections(sel); // stash selection
wxDataViewItemArray object_items;
- m_objects_model->GetChildren(wxDataViewItem(0), object_items);
+ m_objects_model->GetChildren(wxDataViewItem(nullptr), object_items);
for (auto& object_item : object_items) {
// Update Settings Item for object
@@ -3400,7 +3407,7 @@ void ObjectList::instances_to_separated_object(const int obj_idx, const std::set
// create new object from selected instance
ModelObject* model_object = (*m_objects)[obj_idx]->get_model()->add_object(*(*m_objects)[obj_idx]);
- for (int inst_idx = model_object->instances.size() - 1; inst_idx >= 0; inst_idx--)
+ for (int inst_idx = int(model_object->instances.size()) - 1; inst_idx >= 0; inst_idx--)
{
if (find(inst_idxs.begin(), inst_idxs.end(), inst_idx) != inst_idxs.end())
continue;
@@ -3594,7 +3601,7 @@ void ObjectList::OnEditingStarted(wxDataViewEvent &event)
{
m_last_selected_column = -1;
}
-#endif __WXMSW__
+#endif //__WXMSW__
void ObjectList::OnEditingDone(wxDataViewEvent &event)
{
@@ -3613,7 +3620,7 @@ void ObjectList::OnEditingDone(wxDataViewEvent &event)
// Workaround for entering the column editing mode on Windows. Simulate keyboard enter when another column of the active line is selected.
// Here the last active column is forgotten, so when leaving the editing mode, the next mouse click will not enter the editing mode of the newly selected column.
m_last_selected_column = -1;
-#endif __WXMSW__
+#endif //__WXMSW__
}
void ObjectList::show_multi_selection_menu()
diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp
index d19a1002d..13d1106fc 100644
--- a/src/slic3r/GUI/GUI_ObjectList.hpp
+++ b/src/slic3r/GUI/GUI_ObjectList.hpp
@@ -182,15 +182,15 @@ public:
void create_objects_ctrl();
void create_popup_menus();
- wxDataViewColumn* create_objects_list_extruder_column(int extruders_count);
- void update_objects_list_extruder_column(int extruders_count);
+ wxDataViewColumn* create_objects_list_extruder_column(size_t extruders_count);
+ void update_objects_list_extruder_column(size_t extruders_count);
// show/hide "Extruder" column for Objects List
void set_extruder_column_hidden(const bool hide) const;
// update extruder in current config
void update_extruder_in_config(const wxDataViewItem& item);
// update changed name in the object model
void update_name_in_model(const wxDataViewItem& item) const;
- void update_extruder_values_for_items(const int max_extruder);
+ void update_extruder_values_for_items(const size_t max_extruder);
void init_icons();
void msw_rescale_icons();
diff --git a/src/slic3r/GUI/GUI_ObjectManipulation.cpp b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
index 1f1de4003..695c81b5f 100644
--- a/src/slic3r/GUI/GUI_ObjectManipulation.cpp
+++ b/src/slic3r/GUI/GUI_ObjectManipulation.cpp
@@ -668,7 +668,7 @@ void ObjectManipulation::update_mirror_buttons_visibility()
wxGetApp().CallAfter([this, new_states]{
for (int i=0; i<3; ++i) {
if (new_states[i] != m_mirror_buttons[i].second) {
- const ScalableBitmap* bmp;
+ const ScalableBitmap* bmp = nullptr;
switch (new_states[i]) {
case mbHidden : bmp = &m_mirror_bitmap_hidden; m_mirror_buttons[i].first->Enable(false); break;
case mbShown : bmp = &m_mirror_bitmap_off; m_mirror_buttons[i].first->Enable(true); break;
diff --git a/src/slic3r/GUI/GUI_ObjectSettings.cpp b/src/slic3r/GUI/GUI_ObjectSettings.cpp
index c90e1e4ed..0c10c5460 100644
--- a/src/slic3r/GUI/GUI_ObjectSettings.cpp
+++ b/src/slic3r/GUI/GUI_ObjectSettings.cpp
@@ -116,7 +116,7 @@ bool ObjectSettings::update_settings_list()
auto optgroup = std::make_shared<ConfigOptionsGroup>(m_og->ctrl_parent(), _(cat.first), config, false, extra_column);
optgroup->label_width = 15;
- optgroup->sidetext_width = 5.5;
+ optgroup->sidetext_width = 5;
optgroup->m_on_change = [this, config](const t_config_option_key& opt_id, const boost::any& value) {
this->update_config_values(config);
@@ -241,4 +241,4 @@ void ObjectSettings::msw_rescale()
}
} //namespace GUI
-} //namespace Slic3r \ No newline at end of file
+} //namespace Slic3r
diff --git a/src/slic3r/GUI/GUI_ObjectSettings.hpp b/src/slic3r/GUI/GUI_ObjectSettings.hpp
index 61d90600b..a5724811a 100644
--- a/src/slic3r/GUI/GUI_ObjectSettings.hpp
+++ b/src/slic3r/GUI/GUI_ObjectSettings.hpp
@@ -5,11 +5,11 @@
#include <vector>
#include <wx/panel.h>
#include "wxExtensions.hpp"
-#include "libslic3r/PrintConfig.hpp"
class wxBoxSizer;
namespace Slic3r {
+class DynamicPrintConfig;
namespace GUI {
class ConfigOptionsGroup;
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 2b9da6aa0..7c761ed5f 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -640,9 +640,10 @@ void Preview::update_double_slider(const std::vector<double>& layers_z, bool kee
bool snap_to_min = force_sliders_full_range || m_slider->is_lower_at_min();
bool snap_to_max = force_sliders_full_range || m_slider->is_higher_at_max();
- std::vector<std::pair<int, double>> values;
- fill_slider_values(values, layers_z);
- m_slider->SetSliderValues(values);
+ std::vector<double> &ticks_from_config = (wxGetApp().preset_bundle->project_config.option<ConfigOptionFloats>("colorprint_heights"))->values;
+ check_slider_values(ticks_from_config, layers_z);
+
+ m_slider->SetSliderValues(layers_z);
assert(m_slider->GetMinValue() == 0);
m_slider->SetMaxValue(layers_z.empty() ? 0 : layers_z.size() - 1);
@@ -662,9 +663,6 @@ void Preview::update_double_slider(const std::vector<double>& layers_z, bool kee
}
m_slider->SetSelectionSpan(idx_low, idx_high);
- const auto& config = wxGetApp().preset_bundle->project_config;
- const std::vector<double> &ticks_from_config = (config.option<ConfigOptionFloats>("colorprint_heights"))->values;
-
m_slider->SetTicksValues(ticks_from_config);
bool color_print_enable = (wxGetApp().plater()->printer_technology() == ptFFF);
@@ -676,26 +674,18 @@ void Preview::update_double_slider(const std::vector<double>& layers_z, bool kee
m_slider->EnableTickManipulation(color_print_enable);
}
-void Preview::fill_slider_values(std::vector<std::pair<int, double>> &values,
+void Preview::check_slider_values(std::vector<double>& ticks_from_config,
const std::vector<double> &layers_z)
{
- values.clear();
- for (int i = 0; i < layers_z.size(); ++i)
- {
- values.push_back(std::pair<int, double>(i + 1, layers_z[i]));
- }
-
// All ticks that would end up outside the slider range should be erased.
// TODO: this should be placed into more appropriate part of code,
// this function is e.g. not called when the last object is deleted
- std::vector<double> &ticks_from_config = (wxGetApp().preset_bundle->project_config.option<ConfigOptionFloats>("colorprint_heights"))->values;
unsigned int old_size = ticks_from_config.size();
ticks_from_config.erase(std::remove_if(ticks_from_config.begin(), ticks_from_config.end(),
- [values](double val)
+ [layers_z](double val)
{
- return (values.back().second < val &&
- // we can't ignore tick on last layer
- fabs(values.back().second - val) > DoubleSlider::epsilon());
+ auto it = std::lower_bound(layers_z.begin(), layers_z.end(), val - DoubleSlider::epsilon());
+ return it == layers_z.end();
}),
ticks_from_config.end());
if (ticks_from_config.size() != old_size)
diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp
index 401b17a4b..08d5991b4 100644
--- a/src/slic3r/GUI/GUI_Preview.hpp
+++ b/src/slic3r/GUI/GUI_Preview.hpp
@@ -155,7 +155,7 @@ private:
// Create/Update/Reset double slider on 3dPreview
void create_double_slider();
void update_double_slider(const std::vector<double>& layers_z, bool keep_z_range = false);
- void fill_slider_values(std::vector<std::pair<int, double>> &values,
+ void check_slider_values(std::vector<double> &ticks_from_config,
const std::vector<double> &layers_z);
void reset_double_slider();
// update DoubleSlider after keyDown in canvas
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
index 18053dcd6..da3042779 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
@@ -69,7 +69,6 @@ public:
enum EState
{
Off,
- Hover,
On,
Num_States
};
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
index c69d64134..9cd2ab6bb 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.hpp
@@ -44,12 +44,12 @@ public:
Vec3d get_flattening_normal() const;
protected:
- virtual bool on_init();
- virtual std::string on_get_name() const;
- virtual bool on_is_activable() const;
- virtual void on_start_dragging();
- virtual void on_render() const;
- virtual void on_render_for_picking() const;
+ virtual bool on_init() override;
+ virtual std::string on_get_name() const override;
+ virtual bool on_is_activable() const override;
+ virtual void on_start_dragging() override;
+ virtual void on_render() const override;
+ virtual void on_render_for_picking() const override;
virtual void on_set_state() override;
};
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
index 8733c9a11..c856e5465 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.hpp
@@ -87,16 +87,12 @@ protected:
virtual void on_set_state()
{
for (GLGizmoRotate& g : m_gizmos)
- {
g.set_state(m_state);
- }
}
virtual void on_set_hover_id()
{
for (int i = 0; i < 3; ++i)
- {
m_gizmos[i].set_hover_id((m_hover_id == i) ? 0 : -1);
- }
}
virtual void on_enable_grabber(unsigned int id)
{
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
index bf540cb00..a685fb774 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
@@ -329,6 +329,7 @@ void GLGizmoScale3D::do_scale_along_axis(Axis axis, const UpdateData& data)
case X: { local_offset_vec = local_offset * Vec3d::UnitX(); break; }
case Y: { local_offset_vec = local_offset * Vec3d::UnitY(); break; }
case Z: { local_offset_vec = local_offset * Vec3d::UnitZ(); break; }
+ default: break;
}
m_offset = m_offsets_transform * local_offset_vec;
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index 28d569761..0a5c21cce 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -12,7 +12,9 @@
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
#include "slic3r/GUI/GUI_ObjectList.hpp"
+#include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/PresetBundle.hpp"
+#include "libslic3r/SLAPrint.hpp"
#include "libslic3r/Tesselate.hpp"
@@ -306,7 +308,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
}
else {
render_color[3] = 1.f;
- if ((m_hover_id == i && m_editing_mode)) { // ignore hover state unless editing mode is active
+ if ((size_t(m_hover_id) == i && m_editing_mode)) { // ignore hover state unless editing mode is active
render_color[0] = 0.f;
render_color[1] = 1.0f;
render_color[2] = 1.0f;
@@ -328,7 +330,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
glsafe(::glPushMatrix());
- glsafe(::glTranslated(support_point.pos(0), support_point.pos(1), support_point.pos(2)));
+ glsafe(::glTranslatef(support_point.pos(0), support_point.pos(1), support_point.pos(2)));
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
if (vol->is_left_handed())
@@ -345,16 +347,16 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
Eigen::AngleAxisd aa(q);
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)));
- const float cone_radius = 0.25f; // mm
- const float cone_height = 0.75f;
+ const double cone_radius = 0.25; // mm
+ const double cone_height = 0.75;
glsafe(::glPushMatrix());
glsafe(::glTranslatef(0.f, 0.f, support_point.head_front_radius * RenderPointScale));
- ::gluCylinder(m_quadric, 0.f, cone_radius, cone_height, 24, 1);
+ ::gluCylinder(m_quadric, 0., cone_radius, cone_height, 24, 1);
glsafe(::glTranslatef(0.f, 0.f, cone_height));
::gluDisk(m_quadric, 0.0, cone_radius, 24, 1);
glsafe(::glPopMatrix());
}
- ::gluSphere(m_quadric, support_point.head_front_radius * RenderPointScale, 24, 12);
+ ::gluSphere(m_quadric, (double)support_point.head_front_radius * RenderPointScale, 24, 12);
if (vol->is_left_handed())
glFrontFace(GL_CCW);
@@ -775,7 +777,7 @@ std::vector<const ConfigOption*> GLGizmoSlaSupports::get_config_options(const st
}
-void GLGizmoSlaSupports::update_cache_entry_normal(unsigned int i) const
+void GLGizmoSlaSupports::update_cache_entry_normal(size_t i) const
{
int idx = 0;
Eigen::Matrix<float, 1, 3> pp = m_editing_cache[i].support_point.pos;
@@ -1098,9 +1100,6 @@ std::string GLGizmoSlaSupports::on_get_name() const
void GLGizmoSlaSupports::on_set_state()
{
- if (m_state == Hover)
- return;
-
// m_model_object pointer can be invalid (for instance because of undo/redo action),
// we should recover it from the object id
m_model_object = nullptr;
@@ -1111,6 +1110,9 @@ void GLGizmoSlaSupports::on_set_state()
}
}
+ if (m_state == m_old_state)
+ return;
+
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on")));
if (is_mesh_update_necessary())
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
index feb2455cb..d2451f64e 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp
@@ -11,7 +11,6 @@
#include "slic3r/GUI/I18N.hpp" // ...and redefine again when we are done with the igl code
#include "libslic3r/SLA/SLACommon.hpp"
-#include "libslic3r/SLAPrint.hpp"
#include <wx/dialog.h>
#include <cereal/types/vector.hpp>
@@ -31,7 +30,7 @@ private:
ObjectID m_model_object_id = 0;
int m_active_instance = -1;
float m_active_instance_bb_radius; // to cache the bb
- mutable float m_z_shift = 0.f;
+ mutable double m_z_shift = 0.f;
bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal);
const float RenderPointScale = 1.f;
@@ -78,7 +77,7 @@ private:
public:
GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
- virtual ~GLGizmoSlaSupports();
+ ~GLGizmoSlaSupports() override;
void set_sla_support_data(ModelObject* model_object, const Selection& selection);
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
void delete_selected_points(bool force = false);
@@ -90,21 +89,19 @@ public:
void reslice_SLA_supports(bool postpone_error_messages = false) const;
private:
- bool on_init();
- void on_update(const UpdateData& data);
- virtual void on_render() const;
- virtual void on_render_for_picking() const;
+ bool on_init() override;
+ void on_update(const UpdateData& data) override;
+ void on_render() const override;
+ void on_render_for_picking() const override;
//void render_selection_rectangle() const;
void render_points(const Selection& selection, bool picking = false) const;
void render_clipping_plane(const Selection& selection) const;
bool is_mesh_update_necessary() const;
void update_mesh();
- void update_cache_entry_normal(unsigned int i) const;
+ void update_cache_entry_normal(size_t i) const;
bool unsaved_changes() const;
- EState m_no_hover_state = Off;
- EState m_no_hover_old_state = Off;
bool m_lock_unique_islands = false;
bool m_editing_mode = false; // Is editing mode active?
bool m_old_editing_state = false; // To keep track of whether the user toggled between the modes (needed for imgui refreshes).
@@ -157,20 +154,21 @@ private:
protected:
void on_set_state() override;
- virtual void on_set_hover_id()
+ void on_set_hover_id() override
+
{
if (! m_editing_mode || (int)m_editing_cache.size() <= m_hover_id)
m_hover_id = -1;
}
void on_start_dragging() override;
void on_stop_dragging() override;
- virtual void on_render_input_window(float x, float y, float bottom_limit) override;
+ void on_render_input_window(float x, float y, float bottom_limit) override;
- virtual std::string on_get_name() const;
- virtual bool on_is_activable() const;
- virtual bool on_is_selectable() const;
- virtual void on_load(cereal::BinaryInputArchive& ar) override;
- virtual void on_save(cereal::BinaryOutputArchive& ar) const override;
+ std::string on_get_name() const override;
+ bool on_is_activable() const override;
+ bool on_is_selectable() const override;
+ void on_load(cereal::BinaryInputArchive& ar) override;
+ void on_save(cereal::BinaryOutputArchive& ar) const override;
};
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
index 3bad1b0a3..16fa30fa7 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp
@@ -29,9 +29,49 @@ GLGizmosManager::GLGizmosManager(GLCanvas3D& parent)
{
}
-GLGizmosManager::~GLGizmosManager()
+std::vector<size_t> GLGizmosManager::get_selectable_idxs() const
{
- reset();
+ std::vector<size_t> out;
+ for (size_t i=0; i<m_gizmos.size(); ++i)
+ if (m_gizmos[i]->is_selectable())
+ out.push_back(i);
+ return out;
+}
+
+std::vector<size_t> GLGizmosManager::get_activable_idxs() const
+{
+ std::vector<size_t> out;
+ for (size_t i=0; i<m_gizmos.size(); ++i)
+ if (m_gizmos[i]->is_activable())
+ out.push_back(i);
+ return out;
+}
+
+size_t GLGizmosManager::get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const
+{
+ if (! m_enabled)
+ return Undefined;
+
+ float cnv_h = (float)m_parent.get_canvas_size().get_height();
+ float height = get_total_overlay_height();
+ float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
+ float scaled_border = m_overlay_border * m_overlay_scale;
+ float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
+ float scaled_stride_y = scaled_icons_size + scaled_gap_y;
+ float top_y = 0.5f * (cnv_h - height) + scaled_border;
+
+ // is mouse horizontally in the area?
+ if ((scaled_border <= (float)mouse_pos(0) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size))) {
+ // which icon is it on?
+ size_t from_top = (size_t)((float)mouse_pos(1) - top_y)/scaled_stride_y;
+ // is it really on the icon or already past the border?
+ if ((float)mouse_pos(1) <= top_y + from_top*scaled_stride_y + scaled_icons_size) {
+ std::vector<size_t> selectable = get_selectable_idxs();
+ if (from_top < selectable.size())
+ return selectable[from_top];
+ }
+ }
+ return Undefined;
}
bool GLGizmosManager::init()
@@ -45,77 +85,25 @@ bool GLGizmosManager::init()
if (!m_background_texture.metadata.filename.empty())
{
if (!m_background_texture.texture.load_from_file(resources_dir() + "/icons/" + m_background_texture.metadata.filename, false, GLTexture::SingleThreaded, false))
- {
- reset();
return false;
- }
}
- GLGizmoBase* gizmo = new GLGizmoMove3D(m_parent, "move.svg", 0);
- if (gizmo == nullptr)
- return false;
-
- if (!gizmo->init())
- return false;
-
- m_gizmos.insert(GizmosMap::value_type(Move, gizmo));
-
- gizmo = new GLGizmoScale3D(m_parent, "scale.svg", 1);
- if (gizmo == nullptr)
- return false;
-
- if (!gizmo->init())
- return false;
-
- m_gizmos.insert(GizmosMap::value_type(Scale, gizmo));
-
- gizmo = new GLGizmoRotate3D(m_parent, "rotate.svg", 2);
- if (gizmo == nullptr)
- {
- reset();
- return false;
- }
-
- if (!gizmo->init())
- {
- reset();
- return false;
- }
-
- m_gizmos.insert(GizmosMap::value_type(Rotate, gizmo));
-
- gizmo = new GLGizmoFlatten(m_parent, "place.svg", 3);
- if (gizmo == nullptr)
- return false;
-
- if (!gizmo->init()) {
- reset();
- return false;
- }
-
- m_gizmos.insert(GizmosMap::value_type(Flatten, gizmo));
-
- gizmo = new GLGizmoCut(m_parent, "cut.svg", 4);
- if (gizmo == nullptr)
- return false;
-
- if (!gizmo->init()) {
- reset();
- return false;
- }
-
- m_gizmos.insert(GizmosMap::value_type(Cut, gizmo));
-
- gizmo = new GLGizmoSlaSupports(m_parent, "sla_supports.svg", 5);
- if (gizmo == nullptr)
- return false;
+ m_gizmos.emplace_back(new GLGizmoMove3D(m_parent, "move.svg", 0));
+ m_gizmos.emplace_back(new GLGizmoScale3D(m_parent, "scale.svg", 1));
+ m_gizmos.emplace_back(new GLGizmoRotate3D(m_parent, "rotate.svg", 2));
+ m_gizmos.emplace_back(new GLGizmoFlatten(m_parent, "place.svg", 3));
+ m_gizmos.emplace_back(new GLGizmoCut(m_parent, "cut.svg", 4));
+ m_gizmos.emplace_back(new GLGizmoSlaSupports(m_parent, "sla_supports.svg", 5));
- if (!gizmo->init()) {
- reset();
- return false;
+ for (auto& gizmo : m_gizmos) {
+ if (! gizmo->init()) {
+ m_gizmos.clear();
+ return false;
+ }
}
- m_gizmos.insert(GizmosMap::value_type(SlaSupports, gizmo));
+ m_current = Undefined;
+ m_hover = Undefined;
return true;
}
@@ -140,65 +128,39 @@ void GLGizmosManager::set_overlay_scale(float scale)
void GLGizmosManager::refresh_on_off_state()
{
- if (m_serializing)
+ if (m_serializing || m_current == Undefined || m_gizmos.empty())
return;
- GizmosMap::iterator it = m_gizmos.find(m_current);
- if ((it != m_gizmos.end()) && (it->second != nullptr))
- {
- if (!it->second->is_activable())
- {
- it->second->set_state(GLGizmoBase::Off);
- m_current = Undefined;
- }
- }
+ if (m_current != Undefined && ! m_gizmos[m_current]->is_activable())
+ activate_gizmo(Undefined);
}
void GLGizmosManager::reset_all_states()
{
- if (!m_enabled)
- return;
-
- if (m_serializing)
+ if (! m_enabled || m_serializing)
return;
- for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
- {
- if (it->second != nullptr)
- {
- it->second->set_state(GLGizmoBase::Off);
- it->second->set_hover_id(-1);
- }
- }
-
- m_current = Undefined;
+ activate_gizmo(Undefined);
+ m_hover = Undefined;
}
void GLGizmosManager::set_hover_id(int id)
{
- if (!m_enabled)
+ if (!m_enabled || m_current == Undefined)
return;
- for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
- {
- if ((it->second != nullptr) && (it->second->get_state() == GLGizmoBase::On))
- it->second->set_hover_id(id);
- }
+ m_gizmos[m_current]->set_hover_id(id);
}
void GLGizmosManager::enable_grabber(EType type, unsigned int id, bool enable)
{
- if (!m_enabled)
+ if (!m_enabled || type == Undefined || m_gizmos.empty())
return;
- GizmosMap::const_iterator it = m_gizmos.find(type);
- if (it != m_gizmos.end())
- {
- if (enable)
- it->second->enable_grabber(id);
- else
- it->second->disable_grabber(id);
- }
+ if (enable)
+ m_gizmos[type]->enable_grabber(id);
+ else
+ m_gizmos[type]->disable_grabber(id);
}
void GLGizmosManager::update(const Linef3& mouse_ray, const Point& mouse_pos)
@@ -269,8 +231,9 @@ bool GLGizmosManager::is_running() const
if (!m_enabled)
return false;
- GLGizmoBase* curr = get_current();
- return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false;
+ //GLGizmoBase* curr = get_current();
+ //return (curr != nullptr) ? (curr->get_state() == GLGizmoBase::On) : false;
+ return m_current != Undefined;
}
bool GLGizmosManager::handle_shortcut(int key)
@@ -283,43 +246,12 @@ bool GLGizmosManager::handle_shortcut(int key)
bool handled = false;
- for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
- {
- if ((it->second == nullptr) || !it->second->is_selectable())
- continue;
+ for (size_t idx : get_selectable_idxs()) {
+ int it_key = m_gizmos[idx]->get_shortcut_key();
- int it_key = it->second->get_shortcut_key();
-
- if (it->second->is_activable() && ((it_key == key - 64) || (it_key == key - 96)))
- {
- if ((it->second->get_state() == GLGizmoBase::On))
- {
- it->second->set_state(GLGizmoBase::Off);
- if (it->second->get_state() == GLGizmoBase::Off) {
- m_current = Undefined;
- }
+ if (m_gizmos[idx]->is_activable() && ((it_key == key - 64) || (it_key == key - 96))) {
+ activate_gizmo(m_current == idx ? Undefined : (EType)idx);
handled = true;
- }
- else if ((it->second->get_state() == GLGizmoBase::Off))
- {
- // Before turning anything on, turn everything else off to see if
- // nobody refuses. Only then activate the gizmo.
- bool can_open = true;
- for (GizmosMap::iterator i = m_gizmos.begin(); i != m_gizmos.end(); ++i) {
- if (i->first != it->first) {
- if (m_current == i->first && i->second->get_state() != GLGizmoBase::Off ) {
- i->second->set_state(GLGizmoBase::Off);
- if (i->second->get_state() != GLGizmoBase::Off)
- can_open = false;
- }
- }
- }
- if (can_open) {
- it->second->set_state(GLGizmoBase::On);
- m_current = it->first;
- }
- handled = true;
- }
}
}
@@ -328,31 +260,25 @@ bool GLGizmosManager::handle_shortcut(int key)
bool GLGizmosManager::is_dragging() const
{
- if (!m_enabled)
+ if (! m_enabled || m_current == Undefined)
return false;
- GLGizmoBase* curr = get_current();
- return (curr != nullptr) ? curr->is_dragging() : false;
+ return m_gizmos[m_current]->is_dragging();
}
void GLGizmosManager::start_dragging()
{
- if (!m_enabled)
+ if (! m_enabled || m_current == Undefined)
return;
-
- GLGizmoBase* curr = get_current();
- if (curr != nullptr)
- curr->start_dragging();
+ m_gizmos[m_current]->start_dragging();
}
void GLGizmosManager::stop_dragging()
{
- if (!m_enabled)
+ if (! m_enabled || m_current == Undefined)
return;
- GLGizmoBase* curr = get_current();
- if (curr != nullptr)
- curr->stop_dragging();
+ m_gizmos[m_current]->stop_dragging();
}
Vec3d GLGizmosManager::get_displacement() const
@@ -360,8 +286,7 @@ Vec3d GLGizmosManager::get_displacement() const
if (!m_enabled)
return Vec3d::Zero();
- GizmosMap::const_iterator it = m_gizmos.find(Move);
- return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoMove3D*>(it->second)->get_displacement() : Vec3d::Zero();
+ return dynamic_cast<GLGizmoMove3D*>(m_gizmos[Move].get())->get_displacement();
}
Vec3d GLGizmosManager::get_scale() const
@@ -369,126 +294,101 @@ Vec3d GLGizmosManager::get_scale() const
if (!m_enabled)
return Vec3d::Ones();
- GizmosMap::const_iterator it = m_gizmos.find(Scale);
- return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoScale3D*>(it->second)->get_scale() : Vec3d::Ones();
+ return dynamic_cast<GLGizmoScale3D*>(m_gizmos[Scale].get())->get_scale();
}
void GLGizmosManager::set_scale(const Vec3d& scale)
{
- if (!m_enabled)
+ if (!m_enabled || m_gizmos.empty())
return;
- GizmosMap::const_iterator it = m_gizmos.find(Scale);
- if (it != m_gizmos.end())
- reinterpret_cast<GLGizmoScale3D*>(it->second)->set_scale(scale);
+ dynamic_cast<GLGizmoScale3D*>(m_gizmos[Scale].get())->set_scale(scale);
}
Vec3d GLGizmosManager::get_scale_offset() const
{
- if (!m_enabled)
+ if (!m_enabled || m_gizmos.empty())
return Vec3d::Zero();
- GizmosMap::const_iterator it = m_gizmos.find(Scale);
- return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoScale3D*>(it->second)->get_offset() : Vec3d::Zero();
+ return dynamic_cast<GLGizmoScale3D*>(m_gizmos[Scale].get())->get_offset();
}
Vec3d GLGizmosManager::get_rotation() const
{
- if (!m_enabled)
+ if (!m_enabled || m_gizmos.empty())
return Vec3d::Zero();
- GizmosMap::const_iterator it = m_gizmos.find(Rotate);
- return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoRotate3D*>(it->second)->get_rotation() : Vec3d::Zero();
+ return dynamic_cast<GLGizmoRotate3D*>(m_gizmos[Rotate].get())->get_rotation();
}
void GLGizmosManager::set_rotation(const Vec3d& rotation)
{
- if (!m_enabled)
+ if (!m_enabled || m_gizmos.empty())
return;
-
- GizmosMap::const_iterator it = m_gizmos.find(Rotate);
- if (it != m_gizmos.end())
- reinterpret_cast<GLGizmoRotate3D*>(it->second)->set_rotation(rotation);
+ dynamic_cast<GLGizmoRotate3D*>(m_gizmos[Rotate].get())->set_rotation(rotation);
}
Vec3d GLGizmosManager::get_flattening_normal() const
{
- if (!m_enabled)
+ if (!m_enabled || m_gizmos.empty())
return Vec3d::Zero();
- GizmosMap::const_iterator it = m_gizmos.find(Flatten);
- return (it != m_gizmos.end()) ? reinterpret_cast<GLGizmoFlatten*>(it->second)->get_flattening_normal() : Vec3d::Zero();
+ return dynamic_cast<GLGizmoFlatten*>(m_gizmos[Flatten].get())->get_flattening_normal();
}
void GLGizmosManager::set_flattening_data(const ModelObject* model_object)
{
- if (!m_enabled)
+ if (!m_enabled || m_gizmos.empty())
return;
- GizmosMap::const_iterator it = m_gizmos.find(Flatten);
- if (it != m_gizmos.end())
- reinterpret_cast<GLGizmoFlatten*>(it->second)->set_flattening_data(model_object);
+ dynamic_cast<GLGizmoFlatten*>(m_gizmos[Flatten].get())->set_flattening_data(model_object);
}
void GLGizmosManager::set_sla_support_data(ModelObject* model_object)
{
- if (!m_enabled)
+ if (!m_enabled || m_gizmos.empty())
return;
- GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
- if (it != m_gizmos.end())
- reinterpret_cast<GLGizmoSlaSupports*>(it->second)->set_sla_support_data(model_object, m_parent.get_selection());
+ dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->set_sla_support_data(model_object, m_parent.get_selection());
}
// Returns true if the gizmo used the event to do something, false otherwise.
bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down)
{
- if (!m_enabled)
+ if (!m_enabled || m_gizmos.empty())
return false;
- GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
- if (it != m_gizmos.end())
- return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
-
- return false;
+ return dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->gizmo_event(action, mouse_position, shift_down, alt_down, control_down);
}
ClippingPlane GLGizmosManager::get_sla_clipping_plane() const
{
- if (!m_enabled || m_current != SlaSupports)
+ if (!m_enabled || m_current != SlaSupports || m_gizmos.empty())
return ClippingPlane::ClipsNothing();
- GizmosMap::const_iterator it = m_gizmos.find(SlaSupports);
- if (it != m_gizmos.end())
- return reinterpret_cast<GLGizmoSlaSupports*>(it->second)->get_sla_clipping_plane();
-
- return ClippingPlane::ClipsNothing();
+ return dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->get_sla_clipping_plane();
}
bool GLGizmosManager::wants_reslice_supports_on_undo() const
{
return (m_current == SlaSupports
- && dynamic_cast<const GLGizmoSlaSupports*>(m_gizmos.at(SlaSupports))->has_backend_supports());
+ && dynamic_cast<const GLGizmoSlaSupports*>(m_gizmos.at(SlaSupports).get())->has_backend_supports());
}
void GLGizmosManager::render_current_gizmo() const
{
- if (!m_enabled)
+ if (!m_enabled || m_current == Undefined)
return;
- GLGizmoBase* curr = get_current();
- if (curr != nullptr)
- curr->render();
+ m_gizmos[m_current]->render();
}
void GLGizmosManager::render_current_gizmo_for_picking_pass() const
{
- if (!m_enabled)
+ if (! m_enabled || m_current == Undefined)
return;
- GLGizmoBase* curr = get_current();
- if (curr != nullptr)
- curr->render_for_picking();
+ m_gizmos[m_current]->render_for_picking();
}
void GLGizmosManager::render_overlay() const
@@ -547,7 +447,7 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
// if the button down was done on this toolbar, prevent from dragging into the scene
processed = true;
- if (!overlay_contains_mouse(mouse_pos))
+ if (get_gizmo_idx_from_mouse(mouse_pos) == Undefined)
{
// mouse is outside the toolbar
m_tooltip = "";
@@ -557,14 +457,12 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
if ((m_current == SlaSupports) && gizmo_event(SLAGizmoEventType::LeftDown, mouse_pos, evt.ShiftDown(), evt.AltDown(), evt.ControlDown()))
// the gizmo got the event and took some action, there is no need to do anything more
processed = true;
- else if (!selection.is_empty() && grabber_contains_mouse())
- {
+ else if (!selection.is_empty() && grabber_contains_mouse()) {
update_data();
selection.start_dragging();
start_dragging();
- if (m_current == Flatten)
- {
+ if (m_current == Flatten) {
// Rotate the object so the normal points downward:
m_parent.do_flatten(get_flattening_normal(), L("Gizmo-Place on Face"));
wxGetApp().obj_manipul()->set_dirty();
@@ -634,25 +532,14 @@ bool GLGizmosManager::on_mouse(wxMouseEvent& evt)
}
else if (evt.LeftUp() && is_dragging())
{
- switch (m_current)
- {
- case Move:
- {
- m_parent.do_move(L("Gizmo-Move"));
- break;
- }
- case Scale:
- {
- m_parent.do_scale(L("Gizmo-Scale"));
- break;
- }
- case Rotate:
- {
- m_parent.do_rotate(L("Gizmo-Rotate"));
- break;
- }
- default:
- break;
+ switch (m_current) {
+ case Move : m_parent.do_move(L("Gizmo-Move"));
+ break;
+ case Scale : m_parent.do_scale(L("Gizmo-Scale"));
+ break;
+ case Rotate : m_parent.do_rotate(L("Gizmo-Rotate"));
+ break;
+ default : break;
}
stop_dragging();
@@ -842,7 +729,7 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
{
if (m_current == SlaSupports)
{
- GLGizmoSlaSupports* gizmo = reinterpret_cast<GLGizmoSlaSupports*>(get_current());
+ GLGizmoSlaSupports* gizmo = dynamic_cast<GLGizmoSlaSupports*>(get_current());
if (keyCode == WXK_SHIFT)
{
@@ -863,7 +750,8 @@ bool GLGizmosManager::on_key(wxKeyEvent& evt)
}
else if (evt.GetEventType() == wxEVT_KEY_DOWN)
{
- if ((m_current == SlaSupports) && ((keyCode == WXK_SHIFT) || (keyCode == WXK_ALT)) && reinterpret_cast<GLGizmoSlaSupports*>(get_current())->is_in_editing_mode())
+ if ((m_current == SlaSupports) && ((keyCode == WXK_SHIFT) || (keyCode == WXK_ALT))
+ && dynamic_cast<GLGizmoSlaSupports*>(get_current())->is_in_editing_mode())
{
// m_parent.set_cursor(GLCanvas3D::Cross);
processed = true;
@@ -882,18 +770,7 @@ void GLGizmosManager::update_after_undo_redo(const UndoRedo::Snapshot& snapshot)
m_serializing = false;
if (m_current == SlaSupports
&& snapshot.snapshot_data.flags & UndoRedo::SnapshotData::RECALCULATE_SLA_SUPPORTS)
- dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports])->reslice_SLA_supports(true);
-}
-
-void GLGizmosManager::reset()
-{
- for (GizmosMap::value_type& gizmo : m_gizmos)
- {
- delete gizmo.second;
- gizmo.second = nullptr;
- }
-
- m_gizmos.clear();
+ dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->reslice_SLA_supports(true);
}
void GLGizmosManager::render_background(float left, float top, float right, float bottom, float border) const
@@ -911,7 +788,7 @@ void GLGizmosManager::render_background(float left, float top, float right, floa
float internal_top = top - border;
float internal_bottom = bottom + border;
- float left_uv = 0.0f;
+ // float left_uv = 0.0f;
float right_uv = 1.0f;
float top_uv = 1.0f;
float bottom_uv = 0.0f;
@@ -981,33 +858,32 @@ void GLGizmosManager::do_render_overlay() const
float scaled_icons_size = m_overlay_icons_size * m_overlay_scale * inv_zoom;
float scaled_stride_y = scaled_icons_size + scaled_gap_y;
unsigned int icons_texture_id = m_icons_texture.get_id();
- unsigned int tex_width = m_icons_texture.get_width();
- unsigned int tex_height = m_icons_texture.get_height();
- float inv_tex_width = (tex_width != 0) ? 1.0f / (float)tex_width : 0.0f;
- float inv_tex_height = (tex_height != 0) ? 1.0f / (float)tex_height : 0.0f;
+ int tex_width = m_icons_texture.get_width();
+ int tex_height = m_icons_texture.get_height();
+ float inv_tex_width = (tex_width != 0) ? 1.0f / tex_width : 0.0f;
+ float inv_tex_height = (tex_height != 0) ? 1.0f / tex_height : 0.0f;
if ((icons_texture_id == 0) || (tex_width <= 0) || (tex_height <= 0))
return;
- for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
+ for (size_t idx : get_selectable_idxs())
{
- if ((it->second == nullptr) || !it->second->is_selectable())
- continue;
+ GLGizmoBase* gizmo = m_gizmos[idx].get();
- unsigned int sprite_id = it->second->get_sprite_id();
- GLGizmoBase::EState state = it->second->get_state();
+ unsigned int sprite_id = gizmo->get_sprite_id();
+ int icon_idx = m_current == idx ? 2 : (m_hover == idx ? 1 : 0);
float u_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_width;
float v_icon_size = m_overlay_icons_size * m_overlay_scale * inv_tex_height;
float v_top = sprite_id * v_icon_size;
- float u_left = state * u_icon_size;
+ float u_left = icon_idx * u_icon_size;
float v_bottom = v_top + v_icon_size;
float u_right = u_left + u_icon_size;
GLTexture::render_sub_texture(icons_texture_id, top_x, top_x + scaled_icons_size, top_y - scaled_icons_size, top_y, { { u_left, v_bottom }, { u_right, v_bottom }, { u_right, v_top }, { u_left, v_top } });
- if (it->second->get_state() == GLGizmoBase::On) {
- float toolbar_top = (float)cnv_h - m_parent.get_view_toolbar_height();
- it->second->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top);
+ if (idx == m_current) {
+ float toolbar_top = cnv_h - m_parent.get_view_toolbar_height();
+ gizmo->render_input_window(width, 0.5f * cnv_h - top_y * zoom, toolbar_top);
}
top_y -= scaled_stride_y;
}
@@ -1021,13 +897,14 @@ float GLGizmosManager::get_total_overlay_height() const
float scaled_stride_y = scaled_icons_size + scaled_gap_y;
float height = 2.0f * scaled_border;
- for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
+ /*for (size_t idx=0; idx<m_gizmos.size(); ++idx)
{
- if ((it->second == nullptr) || !it->second->is_selectable())
+ if ((m_gizmos[idx] == nullptr) || !m_gizmos[idx]->is_selectable())
continue;
height += scaled_stride_y;
- }
+ }*/
+ height += get_selectable_idxs().size() * scaled_stride_y;
return height - scaled_gap_y;
}
@@ -1039,19 +916,21 @@ float GLGizmosManager::get_total_overlay_width() const
GLGizmoBase* GLGizmosManager::get_current() const
{
- GizmosMap::const_iterator it = m_gizmos.find(m_current);
- return (it != m_gizmos.end()) ? it->second : nullptr;
+ if (m_current==Undefined || m_gizmos.empty())
+ return nullptr;
+ else
+ return m_gizmos[m_current].get();
}
bool GLGizmosManager::generate_icons_texture() const
{
std::string path = resources_dir() + "/icons/";
std::vector<std::string> filenames;
- for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
+ for (size_t idx=0; idx<m_gizmos.size(); ++idx)
{
- if (it->second != nullptr)
+ if (m_gizmos[idx] != nullptr)
{
- const std::string& icon_filename = it->second->get_icon_filename();
+ const std::string& icon_filename = m_gizmos[idx]->get_icon_filename();
if (!icon_filename.empty())
filenames.push_back(path + icon_filename);
}
@@ -1074,74 +953,9 @@ void GLGizmosManager::update_on_off_state(const Vec2d& mouse_pos)
if (!m_enabled)
return;
- float cnv_h = (float)m_parent.get_canvas_size().get_height();
- float height = get_total_overlay_height();
-
- float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
- float scaled_border = m_overlay_border * m_overlay_scale;
- float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
- float scaled_stride_y = scaled_icons_size + scaled_gap_y;
- float top_y = 0.5f * (cnv_h - height) + scaled_border;
-
- auto inside = [scaled_border, scaled_icons_size, &mouse_pos](float top_y) {
- return (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
- };
-
- bool could_activate = true;
- for (std::pair<const GLGizmosManager::EType, GLGizmoBase*> &type_and_gizmo : m_gizmos)
- {
- GLGizmoBase *gizmo = type_and_gizmo.second;
- if ((gizmo == nullptr) || !gizmo->is_selectable())
- continue;
-
- if (! (gizmo->is_activable() && inside(top_y))) {
- gizmo->set_state(GLGizmoBase::Off);
- if (gizmo->get_state() != GLGizmoBase::Off) {
- // Gizmo refused to leave it's active state. Don't try to select
- could_activate = false;
- }
- }
-
- top_y += scaled_stride_y;
- }
-
- // We may change m_current soon. If we did it during following loop, gizmos that take undo/redo snapshots
- // in their on_set_state function could snapshot a state with the new gizmo already active.
- // Therefore, just remember what needs to be done and actually change m_current afterwards.
- EType new_current = m_current;
- top_y = 0.5f * (cnv_h - height) + scaled_border;
- for (std::pair<const GLGizmosManager::EType, GLGizmoBase*> &type_and_gizmo : m_gizmos)
- {
- GLGizmoBase *gizmo = type_and_gizmo.second;
- if ((gizmo == nullptr) || !gizmo->is_selectable())
- continue;
-
- if (gizmo->is_activable() && inside(top_y))
- {
- if ((gizmo->get_state() == GLGizmoBase::On))
- {
- gizmo->set_state(GLGizmoBase::Off);
- if (gizmo->get_state() == GLGizmoBase::Off) {
- gizmo->set_state(GLGizmoBase::Hover);
- new_current = Undefined;
- }
- }
- else if ((gizmo->get_state() == GLGizmoBase::Hover) && could_activate)
- {
- gizmo->set_state(GLGizmoBase::On);
- new_current = type_and_gizmo.first;
- }
- }
-
- top_y += scaled_stride_y;
- }
- m_current = new_current;
-
- if (could_activate) {
- GizmosMap::iterator it = m_gizmos.find(m_current);
- if ((it != m_gizmos.end()) && (it->second != nullptr) && (it->second->get_state() != GLGizmoBase::On))
- it->second->set_state(GLGizmoBase::On);
- }
+ size_t idx = get_gizmo_idx_from_mouse(mouse_pos);
+ if (idx != Undefined && m_gizmos[idx]->is_activable() && m_hover == idx)
+ activate_gizmo(m_current == idx ? Undefined : (EType)idx);
}
std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos)
@@ -1151,60 +965,37 @@ std::string GLGizmosManager::update_hover_state(const Vec2d& mouse_pos)
if (!m_enabled)
return name;
- float cnv_h = (float)m_parent.get_canvas_size().get_height();
- float height = get_total_overlay_height();
- float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
- float scaled_border = m_overlay_border * m_overlay_scale;
- float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
- float scaled_stride_y = scaled_icons_size + scaled_gap_y;
- float top_y = 0.5f * (cnv_h - height) + scaled_border;
-
- for (GizmosMap::iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
- {
- if ((it->second == nullptr) || !it->second->is_selectable())
- continue;
-
- bool inside = (scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size);
- if (inside)
- name = it->second->get_name();
+ m_hover = Undefined;
- if (it->second->is_activable() && (it->second->get_state() != GLGizmoBase::On))
- it->second->set_state(inside ? GLGizmoBase::Hover : GLGizmoBase::Off);
+ size_t idx = get_gizmo_idx_from_mouse(mouse_pos);
+ if (idx != Undefined) {
+ name = m_gizmos[idx]->get_name();
- top_y += scaled_stride_y;
+ if (m_gizmos[idx]->is_activable())
+ m_hover = (EType)idx;
}
return name;
}
-bool GLGizmosManager::overlay_contains_mouse(const Vec2d& mouse_pos) const
+void GLGizmosManager::activate_gizmo(EType type)
{
- if (!m_enabled)
- return false;
-
- float cnv_h = (float)m_parent.get_canvas_size().get_height();
- float height = get_total_overlay_height();
-
- float scaled_icons_size = m_overlay_icons_size * m_overlay_scale;
- float scaled_border = m_overlay_border * m_overlay_scale;
- float scaled_gap_y = m_overlay_gap_y * m_overlay_scale;
- float scaled_stride_y = scaled_icons_size + scaled_gap_y;
- float top_y = 0.5f * (cnv_h - height) + scaled_border;
-
- for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it)
- {
- if ((it->second == nullptr) || !it->second->is_selectable())
- continue;
-
- if ((scaled_border <= (float)mouse_pos(0)) && ((float)mouse_pos(0) <= scaled_border + scaled_icons_size) && (top_y <= (float)mouse_pos(1)) && ((float)mouse_pos(1) <= top_y + scaled_icons_size))
- return true;
+ if (m_gizmos.empty() || m_current == type)
+ return;
- top_y += scaled_stride_y;
+ if (m_current != Undefined) {
+ m_gizmos[m_current]->set_state(GLGizmoBase::Off);
+ if (m_gizmos[m_current]->get_state() != GLGizmoBase::Off)
+ return; // gizmo refused to be turned off, do nothing.
}
- return false;
+ if (type != Undefined)
+ m_gizmos[type]->set_state(GLGizmoBase::On);
+
+ m_current = type;
}
+
bool GLGizmosManager::grabber_contains_mouse() const
{
if (!m_enabled)
diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
index c0adeb957..f649c98b2 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp
@@ -54,25 +54,30 @@ public:
enum EType : unsigned char
{
- Undefined,
Move,
Scale,
Rotate,
Flatten,
Cut,
SlaSupports,
- Num_Types
+ Undefined
};
private:
GLCanvas3D& m_parent;
bool m_enabled;
- typedef std::map<EType, GLGizmoBase*> GizmosMap;
- GizmosMap m_gizmos;
+ std::vector<std::unique_ptr<GLGizmoBase>> m_gizmos;
mutable GLTexture m_icons_texture;
mutable bool m_icons_texture_dirty;
BackgroundTexture m_background_texture;
EType m_current;
+ EType m_hover;
+
+ std::vector<size_t> get_selectable_idxs() const;
+ std::vector<size_t> get_activable_idxs() const;
+ size_t get_gizmo_idx_from_mouse(const Vec2d& mouse_pos) const;
+
+ void activate_gizmo(EType type);
float m_overlay_icons_size;
float m_overlay_scale;
@@ -98,7 +103,6 @@ private:
public:
explicit GLGizmosManager(GLCanvas3D& parent);
- ~GLGizmosManager();
bool init();
@@ -112,16 +116,8 @@ public:
ar(m_current);
- GLGizmoBase* curr = get_current();
- for (GizmosMap::const_iterator it = m_gizmos.begin(); it != m_gizmos.end(); ++it) {
- GLGizmoBase* gizmo = it->second;
- if (gizmo != nullptr) {
- gizmo->set_hover_id(-1);
- gizmo->set_state((it->second == curr) ? GLGizmoBase::On : GLGizmoBase::Off);
- if (gizmo == curr)
- gizmo->load(ar);
- }
- }
+ if (m_current != Undefined)
+ m_gizmos[m_current]->load(ar);
}
template<class Archive>
@@ -132,9 +128,8 @@ public:
ar(m_current);
- GLGizmoBase* curr = get_current();
- if (curr != nullptr)
- curr->save(ar);
+ if (m_current != Undefined && !m_gizmos.empty())
+ m_gizmos[m_current]->save(ar);
}
bool is_enabled() const { return m_enabled; }
@@ -195,8 +190,6 @@ public:
void update_after_undo_redo(const UndoRedo::Snapshot& snapshot);
private:
- void reset();
-
void render_background(float left, float top, float right, float bottom, float border) const;
void do_render_overlay() const;
@@ -209,7 +202,6 @@ private:
void update_on_off_state(const Vec2d& mouse_pos);
std::string update_hover_state(const Vec2d& mouse_pos);
- bool overlay_contains_mouse(const Vec2d& mouse_pos) const;
bool grabber_contains_mouse() const;
};
diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp
index aa1e3d500..28bd0242b 100644
--- a/src/slic3r/GUI/MainFrame.hpp
+++ b/src/slic3r/GUI/MainFrame.hpp
@@ -50,8 +50,9 @@ class MainFrame : public DPIFrame
wxString m_qs_last_input_file = wxEmptyString;
wxString m_qs_last_output_file = wxEmptyString;
wxString m_last_config = wxEmptyString;
-
- wxMenuItem* m_menu_item_repeat { nullptr };
+#if 0
+ wxMenuItem* m_menu_item_repeat { nullptr }; // doesn't used now
+#endif
wxMenuItem* m_menu_item_reslice_now { nullptr };
PrintHostQueueDialog *m_printhost_queue_dlg;
diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp
index c17569c11..c032aac72 100644
--- a/src/slic3r/GUI/OptionsGroup.cpp
+++ b/src/slic3r/GUI/OptionsGroup.cpp
@@ -457,8 +457,9 @@ void ConfigOptionsGroup::Show(const bool show)
bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) {
if (m_options_mode.empty())
return true;
- if (m_grid_sizer->GetEffectiveRowsCount() != m_options_mode.size() &&
- m_options_mode.size() == 1)
+ int opt_mode_size = m_options_mode.size();
+ if (m_grid_sizer->GetEffectiveRowsCount() != opt_mode_size &&
+ opt_mode_size == 1)
return m_options_mode[0] <= mode;
Show(true);
@@ -476,7 +477,7 @@ bool ConfigOptionsGroup::update_visibility(ConfigOptionMode mode) {
coef+= cols;
}
- if (hidden_row_cnt == m_options_mode.size()) {
+ if (hidden_row_cnt == opt_mode_size) {
sizer->ShowItems(false);
return false;
}
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index ef6a7d3c5..3075d11ed 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -510,24 +510,27 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) :
option.opt.sidetext = "";
line.append_option(option);
- auto wiping_dialog_btn = [config, this](wxWindow* parent) {
+ auto wiping_dialog_btn = [this](wxWindow* parent) {
m_wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
m_wiping_dialog_button->SetFont(wxGetApp().normal_font());
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(m_wiping_dialog_button, 0, wxALIGN_CENTER_VERTICAL);
m_wiping_dialog_button->Bind(wxEVT_BUTTON, ([parent](wxCommandEvent& e)
{
- auto &config = wxGetApp().preset_bundle->project_config;
- const std::vector<double> &init_matrix = (config.option<ConfigOptionFloats>("wiping_volumes_matrix"))->values;
- const std::vector<double> &init_extruders = (config.option<ConfigOptionFloats>("wiping_volumes_extruders"))->values;
+ auto &project_config = wxGetApp().preset_bundle->project_config;
+ const std::vector<double> &init_matrix = (project_config.option<ConfigOptionFloats>("wiping_volumes_matrix"))->values;
+ const std::vector<double> &init_extruders = (project_config.option<ConfigOptionFloats>("wiping_volumes_extruders"))->values;
- WipingDialog dlg(parent, cast<float>(init_matrix), cast<float>(init_extruders));
+ const DynamicPrintConfig* config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
+ const std::vector<std::string> &extruder_colours = (config->option<ConfigOptionStrings>("extruder_colour"))->values;
+
+ WipingDialog dlg(parent, cast<float>(init_matrix), cast<float>(init_extruders), extruder_colours);
if (dlg.ShowModal() == wxID_OK) {
std::vector<float> matrix = dlg.get_matrix();
std::vector<float> extruders = dlg.get_extruders();
- (config.option<ConfigOptionFloats>("wiping_volumes_matrix"))->values = std::vector<double>(matrix.begin(), matrix.end());
- (config.option<ConfigOptionFloats>("wiping_volumes_extruders"))->values = std::vector<double>(extruders.begin(), extruders.end());
+ (project_config.option<ConfigOptionFloats>("wiping_volumes_matrix"))->values = std::vector<double>(matrix.begin(), matrix.end());
+ (project_config.option<ConfigOptionFloats>("wiping_volumes_extruders"))->values = std::vector<double>(extruders.begin(), extruders.end());
wxPostEvent(parent, SimpleEvent(EVT_SCHEDULE_BACKGROUND_PROCESS, parent));
}
}));
@@ -880,7 +883,7 @@ void Sidebar::init_filament_combo(PresetComboBox **combo, const int extr_idx) {
sizer_filaments->Add(combo_and_btn_sizer, 1, wxEXPAND | wxBOTTOM, 1);
}
-void Sidebar::remove_unused_filament_combos(const int current_extruder_count)
+void Sidebar::remove_unused_filament_combos(const size_t current_extruder_count)
{
if (current_extruder_count >= p->combos_filament.size())
return;
@@ -923,9 +926,9 @@ void Sidebar::update_presets(Preset::Type preset_type)
switch (preset_type) {
case Preset::TYPE_FILAMENT:
{
- const int extruder_cnt = print_tech != ptFFF ? 1 :
+ const size_t extruder_cnt = print_tech != ptFFF ? 1 :
dynamic_cast<ConfigOptionFloats*>(preset_bundle.printers.get_edited_preset().config.option("nozzle_diameter"))->values.size();
- const int filament_cnt = p->combos_filament.size() > extruder_cnt ? extruder_cnt : p->combos_filament.size();
+ const size_t filament_cnt = p->combos_filament.size() > extruder_cnt ? extruder_cnt : p->combos_filament.size();
if (filament_cnt == 1) {
// Single filament printer, synchronize the filament presets.
@@ -1048,7 +1051,7 @@ wxButton* Sidebar::get_wiping_dialog_button()
return p->frequently_changed_parameters->get_wiping_dialog_button();
}
-void Sidebar::update_objects_list_extruder_column(int extruders_count)
+void Sidebar::update_objects_list_extruder_column(size_t extruders_count)
{
p->object_list->update_objects_list_extruder_column(extruders_count);
}
@@ -1072,8 +1075,6 @@ void Sidebar::show_info_sizer()
return;
}
- const ModelInstance* model_instance = !model_object->instances.empty() ? model_object->instances.front() : nullptr;
-
auto size = model_object->bounding_box().size();
p->object_info->info_size->SetLabel(wxString::Format("%.2f x %.2f x %.2f",size(0), size(1), size(2)));
p->object_info->info_materials->SetLabel(wxString::Format("%d", static_cast<int>(model_object->materials_count())));
@@ -1936,6 +1937,7 @@ private:
* */
std::string m_last_fff_printer_profile_name;
std::string m_last_sla_printer_profile_name;
+ bool m_update_objects_list_on_loading{ true };
};
const std::regex Plater::priv::pattern_bundle(".*[.](amf|amf[.]xml|zip[.]amf|3mf|prusa)", std::regex::icase);
@@ -2285,20 +2287,20 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
if (! is_project_file) {
if (model.looks_like_multipart_object()) {
- wxMessageDialog dlg(q, _(L(
+ wxMessageDialog msg_dlg(q, _(L(
"This file contains several objects positioned at multiple heights. "
"Instead of considering them as multiple objects, should I consider\n"
"this file as a single object having multiple parts?\n"
)), _(L("Multi-part object detected")), wxICON_WARNING | wxYES | wxNO);
- if (dlg.ShowModal() == wxID_YES) {
+ if (msg_dlg.ShowModal() == wxID_YES) {
model.convert_multipart_object(nozzle_dmrs->values.size());
}
}
}
else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf) && model_has_advanced_features(model)) {
- wxMessageDialog dlg(q, _(L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?\n")),
+ wxMessageDialog msg_dlg(q, _(L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?\n")),
_(L("Detected advanced data")), wxICON_WARNING | wxYES | wxNO);
- if (dlg.ShowModal() == wxID_YES)
+ if (msg_dlg.ShowModal() == wxID_YES)
{
Slic3r::GUI::wxGetApp().save_mode(comAdvanced);
view3D->set_as_dirty();
@@ -2337,12 +2339,12 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
}
if (new_model != nullptr && new_model->objects.size() > 1) {
- wxMessageDialog dlg(q, _(L(
+ wxMessageDialog msg_dlg(q, _(L(
"Multiple objects were loaded for a multi-material printer.\n"
"Instead of considering them as multiple objects, should I consider\n"
"these files to represent a single object having multiple parts?\n"
)), _(L("Multi-part object detected")), wxICON_WARNING | wxYES | wxNO);
- if (dlg.ShowModal() == wxID_YES) {
+ if (msg_dlg.ShowModal() == wxID_YES) {
new_model->convert_multipart_object(nozzle_dmrs->values.size());
}
@@ -2460,8 +2462,11 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode
_(L("Object too large?")));
}
- for (const size_t idx : obj_idxs) {
- wxGetApp().obj_list()->add_object_to_list(idx);
+ if (m_update_objects_list_on_loading)
+ {
+ for (const size_t idx : obj_idxs) {
+ wxGetApp().obj_list()->add_object_to_list(idx);
+ }
}
update();
@@ -3084,25 +3089,49 @@ void Plater::priv::reload_from_disk()
{
Plater::TakeSnapshot snapshot(q, _(L("Reload from Disk")));
- const auto &selection = get_selection();
+ auto& selection = get_selection();
const auto obj_orig_idx = selection.get_object_idx();
if (selection.is_wipe_tower() || obj_orig_idx == -1) { return; }
+ int instance_idx = selection.get_instance_idx();
auto *object_orig = model.objects[obj_orig_idx];
std::vector<fs::path> input_paths(1, object_orig->input_file);
+ // disable render to avoid to show intermediate states
+ view3D->get_canvas3d()->enable_render(false);
+
+ // disable update of objects list while loading to avoid to show intermediate states
+ m_update_objects_list_on_loading = false;
+
const auto new_idxs = load_files(input_paths, true, false);
+ if (new_idxs.empty())
+ {
+ // error while loading
+ view3D->get_canvas3d()->enable_render(true);
+ return;
+ }
- for (const auto idx : new_idxs) {
+ for (const auto idx : new_idxs)
+ {
ModelObject *object = model.objects[idx];
+ object->config.apply(object_orig->config);
object->clear_instances();
- for (const ModelInstance *instance : object_orig->instances) {
+ for (const ModelInstance *instance : object_orig->instances)
+ {
object->add_instance(*instance);
}
- if (object->volumes.size() == object_orig->volumes.size()) {
- for (size_t i = 0; i < object->volumes.size(); i++) {
+ for (const ModelVolume* v : object_orig->volumes)
+ {
+ if (v->is_modifier())
+ object->add_volume(*v);
+ }
+
+ if (object->volumes.size() == object_orig->volumes.size())
+ {
+ for (size_t i = 0; i < object->volumes.size(); i++)
+ {
object->volumes[i]->config.apply(object_orig->volumes[i]->config);
}
}
@@ -3110,7 +3139,33 @@ void Plater::priv::reload_from_disk()
// XXX: Restore more: layer_height_ranges, layer_height_profile (?)
}
+ // re-enable update of objects list
+ m_update_objects_list_on_loading = true;
+
+ // puts the new objects into the list
+ for (const auto idx : new_idxs)
+ {
+ wxGetApp().obj_list()->add_object_to_list(idx);
+ }
+
remove(obj_orig_idx);
+
+ // new GLVolumes have been created at this point, so update their printable state
+ for (size_t i = 0; i < model.objects.size(); ++i)
+ {
+ view3D->get_canvas3d()->update_instance_printable_state_for_object(i);
+ }
+
+ // re-enable render
+ view3D->get_canvas3d()->enable_render(true);
+
+ // the previous call to remove() clears the selection
+ // select newly added objects
+ selection.clear();
+ for (const auto idx : new_idxs)
+ {
+ selection.add_instance((unsigned int)idx - 1, instance_idx, false);
+ }
}
void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/)
@@ -3265,6 +3320,7 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
else
this->update_sla_scene();
break;
+ default: break;
}
} else if (evt.status.flags & PrintBase::SlicingStatus::RELOAD_SLA_PREVIEW) {
// Update the SLA preview. Only called if not RELOAD_SLA_SUPPORT_POINTS, as the block above will refresh the preview anyways.
@@ -3284,6 +3340,7 @@ void Plater::priv::on_slicing_completed(wxCommandEvent &)
else
this->update_sla_scene();
break;
+ default: break;
}
}
@@ -3330,6 +3387,7 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
else
this->update_sla_scene();
break;
+ default: break;
}
if (canceled) {
@@ -4655,7 +4713,7 @@ void Plater::undo_redo_topmost_string_getter(const bool is_undo, std::string& ou
out_text = "";
}
-void Plater::on_extruders_change(int num_extruders)
+void Plater::on_extruders_change(size_t num_extruders)
{
auto& choices = sidebar().combos_filament();
@@ -4664,7 +4722,7 @@ void Plater::on_extruders_change(int num_extruders)
wxWindowUpdateLocker noUpdates_scrolled_panel(&sidebar()/*.scrolled_panel()*/);
- int i = choices.size();
+ size_t i = choices.size();
while ( i < num_extruders )
{
PresetComboBox* choice/*{ nullptr }*/;
@@ -4851,7 +4909,7 @@ void Plater::changed_objects(const std::vector<size_t>& object_idxs)
if (object_idxs.empty())
return;
- for (int obj_idx : object_idxs)
+ for (size_t obj_idx : object_idxs)
{
if (obj_idx < p->model.objects.size())
// recenter and re - align to Z = 0
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index 2d104bc46..6b488fef1 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -89,7 +89,7 @@ public:
~Sidebar();
void init_filament_combo(PresetComboBox **combo, const int extr_idx);
- void remove_unused_filament_combos(const int current_extruder_count);
+ void remove_unused_filament_combos(const size_t current_extruder_count);
void update_all_preset_comboboxes();
void update_presets(Slic3r::Preset::Type preset_type);
void update_mode_sizer() const;
@@ -105,7 +105,7 @@ public:
ConfigOptionsGroup* og_freq_chng_params(const bool is_fff);
wxButton* get_wiping_dialog_button();
- void update_objects_list_extruder_column(int extruders_count);
+ void update_objects_list_extruder_column(size_t extruders_count);
void show_info_sizer();
void show_sliced_info_sizer(const bool show);
void enable_buttons(bool enable);
@@ -209,7 +209,7 @@ public:
void enter_gizmos_stack();
void leave_gizmos_stack();
- void on_extruders_change(int extruders_count);
+ void on_extruders_change(size_t extruders_count);
void on_config_change(const DynamicPrintConfig &config);
// On activating the parent window.
void on_activate();
diff --git a/src/slic3r/GUI/PresetBundle.cpp b/src/slic3r/GUI/PresetBundle.cpp
index 79d49f13a..d9e90333c 100644
--- a/src/slic3r/GUI/PresetBundle.cpp
+++ b/src/slic3r/GUI/PresetBundle.cpp
@@ -366,7 +366,7 @@ void PresetBundle::load_selections(const AppConfig &config, const std::string &p
this->filament_presets = { filaments.get_selected_preset_name() };
for (unsigned int i = 1; i < 1000; ++ i) {
char name[64];
- sprintf(name, "filament_%d", i);
+ sprintf(name, "filament_%u", i);
if (! config.has("presets", name))
break;
this->filament_presets.emplace_back(remove_ini_suffix(config.get("presets", name)));
@@ -388,11 +388,12 @@ void PresetBundle::export_selections(AppConfig &config)
config.clear_section("presets");
config.set("presets", "print", prints.get_selected_preset_name());
config.set("presets", "filament", filament_presets.front());
- for (int i = 1; i < filament_presets.size(); ++i) {
+ for (unsigned i = 1; i < filament_presets.size(); ++i) {
char name[64];
- sprintf(name, "filament_%d", i);
+ sprintf(name, "filament_%u", i);
config.set("presets", name, filament_presets[i]);
}
+
config.set("presets", "sla_print", sla_prints.get_selected_preset_name());
config.set("presets", "sla_material", sla_materials.get_selected_preset_name());
config.set("presets", "printer", printers.get_selected_preset_name());
@@ -697,6 +698,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
config.option<ConfigOptionString>("default_sla_print_profile", true);
config.option<ConfigOptionString>("default_sla_material_profile", true);
break;
+ default: break;
}
// 1) Create a name from the file name.
@@ -778,7 +780,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
Preset *loaded = nullptr;
if (is_external)
loaded = &this->filaments.load_external_preset(name_or_path, name,
- (i < old_filament_profile_names->values.size()) ? old_filament_profile_names->values[i] : "",
+ (i < int(old_filament_profile_names->values.size())) ? old_filament_profile_names->values[i] : "",
std::move(cfg), i == 0);
else {
// Used by the config wizard when creating a custom setup.
@@ -805,6 +807,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
load_preset(this->sla_materials, 1, "sla_material_settings_id");
load_preset(this->printers, 2, "printer_settings_id");
break;
+ default: break;
}
this->update_compatible(false);
@@ -1260,7 +1263,7 @@ void PresetBundle::update_multi_material_filament_presets()
// Now verify if wiping_volumes_matrix has proper size (it is used to deduce number of extruders in wipe tower generator):
std::vector<double> old_matrix = this->project_config.option<ConfigOptionFloats>("wiping_volumes_matrix")->values;
- size_t old_number_of_extruders = int(sqrt(old_matrix.size())+EPSILON);
+ size_t old_number_of_extruders = size_t(sqrt(old_matrix.size())+EPSILON);
if (num_extruders != old_number_of_extruders) {
// First verify if purging volumes presets for each extruder matches number of extruders
std::vector<double>& extruders = this->project_config.option<ConfigOptionFloats>("wiping_volumes_extruders")->values;
@@ -1349,6 +1352,7 @@ void PresetBundle::update_compatible(bool select_other_if_incompatible)
[&prefered_sla_material_profile](const std::string& profile_name){ return profile_name == prefered_sla_material_profile; });
break;
}
+ default: break;
}
}
diff --git a/src/slic3r/GUI/PresetHints.cpp b/src/slic3r/GUI/PresetHints.cpp
index 8b7d54538..a02772c4d 100644
--- a/src/slic3r/GUI/PresetHints.cpp
+++ b/src/slic3r/GUI/PresetHints.cpp
@@ -89,7 +89,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
double bridge_flow_ratio = print_config.opt_float("bridge_flow_ratio");
double perimeter_speed = print_config.opt_float("perimeter_speed");
double external_perimeter_speed = print_config.get_abs_value("external_perimeter_speed", perimeter_speed);
- double gap_fill_speed = print_config.opt_float("gap_fill_speed");
+ // double gap_fill_speed = print_config.opt_float("gap_fill_speed");
double infill_speed = print_config.opt_float("infill_speed");
double small_perimeter_speed = print_config.get_abs_value("small_perimeter_speed", perimeter_speed);
double solid_infill_speed = print_config.get_abs_value("solid_infill_speed", infill_speed);
@@ -123,7 +123,7 @@ std::string PresetHints::maximum_volumetric_flow_description(const PresetBundle
// Current filament values
double filament_diameter = filament_config.opt_float("filament_diameter", 0);
double filament_crossection = M_PI * 0.25 * filament_diameter * filament_diameter;
- double extrusion_multiplier = filament_config.opt_float("extrusion_multiplier", 0);
+ // double extrusion_multiplier = filament_config.opt_float("extrusion_multiplier", 0);
// The following value will be annotated by this hint, so it does not take part in the calculation.
// double filament_max_volumetric_speed = filament_config.opt_float("filament_max_volumetric_speed", 0);
diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp
index 09bd65682..d08389537 100644
--- a/src/slic3r/GUI/PrintHostDialogs.cpp
+++ b/src/slic3r/GUI/PrintHostDialogs.cpp
@@ -250,7 +250,7 @@ void PrintHostQueueDialog::on_list_select()
void PrintHostQueueDialog::on_progress(Event &evt)
{
- wxCHECK_RET(evt.job_id < job_list->GetItemCount(), "Out of bounds access to job list");
+ wxCHECK_RET(evt.job_id < (size_t)job_list->GetItemCount(), "Out of bounds access to job list");
if (evt.progress < 100) {
set_state(evt.job_id, ST_PROGRESS);
@@ -265,7 +265,7 @@ void PrintHostQueueDialog::on_progress(Event &evt)
void PrintHostQueueDialog::on_error(Event &evt)
{
- wxCHECK_RET(evt.job_id < job_list->GetItemCount(), "Out of bounds access to job list");
+ wxCHECK_RET(evt.job_id < (size_t)job_list->GetItemCount(), "Out of bounds access to job list");
set_state(evt.job_id, ST_ERROR);
@@ -280,7 +280,7 @@ void PrintHostQueueDialog::on_error(Event &evt)
void PrintHostQueueDialog::on_cancel(Event &evt)
{
- wxCHECK_RET(evt.job_id < job_list->GetItemCount(), "Out of bounds access to job list");
+ wxCHECK_RET(evt.job_id < (size_t)job_list->GetItemCount(), "Out of bounds access to job list");
set_state(evt.job_id, ST_CANCELLED);
job_list->SetValue(wxVariant(0), evt.job_id, COL_PROGRESS);
diff --git a/src/slic3r/GUI/PrintHostDialogs.hpp b/src/slic3r/GUI/PrintHostDialogs.hpp
index 427c4f6bf..e5f96f2b6 100644
--- a/src/slic3r/GUI/PrintHostDialogs.hpp
+++ b/src/slic3r/GUI/PrintHostDialogs.hpp
@@ -37,7 +37,6 @@ public:
private:
wxTextCtrl *txt_filename;
wxCheckBox *box_print;
- bool can_start_print;
};
diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp
index 9c1a84615..40fbbbac6 100644
--- a/src/slic3r/GUI/Selection.cpp
+++ b/src/slic3r/GUI/Selection.cpp
@@ -310,7 +310,7 @@ void Selection::remove_volume(unsigned int object_idx, unsigned int volume_idx)
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
GLVolume* v = (*m_volumes)[i];
- if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx))
+ if ((v->object_idx() == (int)object_idx) && (v->volume_idx() == (int)volume_idx))
do_remove_volume(i);
}
@@ -992,7 +992,7 @@ void Selection::translate(unsigned int object_idx, const Vec3d& displacement)
for (unsigned int i : m_list)
{
GLVolume* v = (*m_volumes)[i];
- if (v->object_idx() == object_idx)
+ if (v->object_idx() == (int)object_idx)
v->set_instance_offset(v->get_instance_offset() + displacement);
}
@@ -1037,7 +1037,7 @@ void Selection::translate(unsigned int object_idx, unsigned int instance_idx, co
for (unsigned int i : m_list)
{
GLVolume* v = (*m_volumes)[i];
- if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
+ if ((v->object_idx() == (int)object_idx) && (v->instance_idx() == (int)instance_idx))
v->set_instance_offset(v->get_instance_offset() + displacement);
}
@@ -1063,7 +1063,7 @@ void Selection::translate(unsigned int object_idx, unsigned int instance_idx, co
continue;
GLVolume* v = (*m_volumes)[j];
- if ((v->object_idx() != object_idx) || (v->instance_idx() != instance_idx))
+ if ((v->object_idx() != object_idx) || (v->instance_idx() != (int)instance_idx))
continue;
v->set_instance_offset(v->get_instance_offset() + displacement);
@@ -1154,7 +1154,7 @@ void Selection::erase()
for (const ItemForDelete& i : items_set) {
if (i.type == ItemType::itVolume) {
const int vol_in_obj_cnt = volumes_in_obj.find(i.obj_idx) == volumes_in_obj.end() ? 0 : volumes_in_obj.at(i.obj_idx);
- if (vol_in_obj_cnt == m_model->objects[i.obj_idx]->volumes.size()) {
+ if (vol_in_obj_cnt == (int)m_model->objects[i.obj_idx]->volumes.size()) {
if (i.sub_obj_idx == vol_in_obj_cnt - 1)
items.emplace_back(ItemType::itObject, i.obj_idx, 0);
continue;
@@ -1389,7 +1389,7 @@ std::vector<unsigned int> Selection::get_volume_idxs_from_object(unsigned int ob
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
- if ((*m_volumes)[i]->object_idx() == object_idx)
+ if ((*m_volumes)[i]->object_idx() == (int)object_idx)
idxs.push_back(i);
}
@@ -1403,7 +1403,7 @@ std::vector<unsigned int> Selection::get_volume_idxs_from_instance(unsigned int
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
const GLVolume* v = (*m_volumes)[i];
- if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
+ if ((v->object_idx() == (int)object_idx) && (v->instance_idx() == (int)instance_idx))
idxs.push_back(i);
}
@@ -1417,9 +1417,9 @@ std::vector<unsigned int> Selection::get_volume_idxs_from_volume(unsigned int ob
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
const GLVolume* v = (*m_volumes)[i];
- if ((v->object_idx() == object_idx) && (v->volume_idx() == volume_idx))
+ if ((v->object_idx() == (int)object_idx) && (v->volume_idx() == (int)volume_idx))
{
- if ((instance_idx != -1) && (v->instance_idx() == instance_idx))
+ if (((int)instance_idx != -1) && (v->instance_idx() == (int)instance_idx))
idxs.push_back(i);
}
}
@@ -1607,7 +1607,7 @@ void Selection::update_type()
}
else
{
- int sels_cntr = 0;
+ unsigned int sels_cntr = 0;
for (ObjectIdxsToInstanceIdxsMap::iterator it = m_cache.content.begin(); it != m_cache.content.end(); ++it)
{
const ModelObject* model_object = m_model->objects[it->first];
@@ -1759,7 +1759,7 @@ void Selection::do_remove_instance(unsigned int object_idx, unsigned int instanc
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
GLVolume* v = (*m_volumes)[i];
- if ((v->object_idx() == object_idx) && (v->instance_idx() == instance_idx))
+ if ((v->object_idx() == (int)object_idx) && (v->instance_idx() == (int)instance_idx))
do_remove_volume(i);
}
}
@@ -1769,7 +1769,7 @@ void Selection::do_remove_object(unsigned int object_idx)
for (unsigned int i = 0; i < (unsigned int)m_volumes->size(); ++i)
{
GLVolume* v = (*m_volumes)[i];
- if (v->object_idx() == object_idx)
+ if (v->object_idx() == (int)object_idx)
do_remove_volume(i);
}
}
@@ -1836,7 +1836,6 @@ void Selection::render_synchronized_volumes() const
{
const GLVolume* volume = (*m_volumes)[i];
int object_idx = volume->object_idx();
- int instance_idx = volume->instance_idx();
int volume_idx = volume->volume_idx();
for (unsigned int j = 0; j < (unsigned int)m_volumes->size(); ++j)
{
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index d9cf56f03..c87626a48 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -232,7 +232,7 @@ void Tab::create_preset_tab()
//! select_preset(m_presets_choice->GetStringSelection().ToUTF8().data());
//! we doing next:
int selected_item = m_presets_choice->GetSelection();
- if (m_selected_preset_item == selected_item && !m_presets->current_is_dirty())
+ if (m_selected_preset_item == size_t(selected_item) && !m_presets->current_is_dirty())
return;
if (selected_item >= 0) {
std::string selected_string = m_presets_choice->GetString(selected_item).ToUTF8().data();
@@ -489,7 +489,7 @@ template<class T>
void add_correct_opts_to_options_list(const std::string &opt_key, std::map<std::string, int>& map, Tab *tab, const int& value)
{
T *opt_cur = static_cast<T*>(tab->m_config->option(opt_key));
- for (int i = 0; i < opt_cur->values.size(); i++)
+ for (size_t i = 0; i < opt_cur->values.size(); i++)
map.emplace(opt_key + "#" + std::to_string(i), value);
}
@@ -995,6 +995,7 @@ void Tab::update_preset_description_line()
description_line += "\n\n\t" + _(L("default SLA print profile")) + ": \n\t\t" + default_sla_print_profile;
break;
}
+ default: break;
}
}
}
@@ -1263,251 +1264,9 @@ void TabPrint::update()
if (m_preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA)
return; // ys_FIXME
- /*
- // #ys_FIXME_to_delete
- //! Temporary workaround for the correct updates of the TextCtrl (like "layer_height"):
- // KillFocus() for the wxSpinCtrl use CallAfter function. So,
- // to except the duplicate call of the update() after dialog->ShowModal(),
- // let check if this process is already started.
- if (is_msg_dlg_already_exist)
- return;
- */
-
m_update_cnt++;
// Freeze();
- /* #ys_FIXME_delete_after_testing (refactoring)
- *
- // layer_height shouldn't be equal to zero
- if (m_config->opt_float("layer_height") < EPSILON)
- {
- const wxString msg_text = _(L("Zero layer height is not valid.\n\nThe layer height will be reset to 0.01."));
- wxMessageDialog dialog(parent(), msg_text, _(L("Layer height")), wxICON_WARNING | wxOK);
- DynamicPrintConfig new_conf = *m_config;
- is_msg_dlg_already_exist = true;
- dialog.ShowModal();
- new_conf.set_key_value("layer_height", new ConfigOptionFloat(0.01));
- load_config(new_conf);
- is_msg_dlg_already_exist = false;
- }
-
- if (fabs(m_config->option<ConfigOptionFloatOrPercent>("first_layer_height")->value - 0) < EPSILON)
- {
- const wxString msg_text = _(L("Zero first layer height is not valid.\n\nThe first layer height will be reset to 0.01."));
- wxMessageDialog dialog(parent(), msg_text, _(L("First layer height")), wxICON_WARNING | wxOK);
- DynamicPrintConfig new_conf = *m_config;
- is_msg_dlg_already_exist = true;
- dialog.ShowModal();
- new_conf.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(0.01, false));
- load_config(new_conf);
- is_msg_dlg_already_exist = false;
- }
-
- double fill_density = m_config->option<ConfigOptionPercent>("fill_density")->value;
-
- if (m_config->opt_bool("spiral_vase") &&
- !(m_config->opt_int("perimeters") == 1 && m_config->opt_int("top_solid_layers") == 0 &&
- fill_density == 0)) {
- wxString msg_text = _(L("The Spiral Vase mode requires:\n"
- "- one perimeter\n"
- "- no top solid layers\n"
- "- 0% fill density\n"
- "- no support material\n"
- "- no ensure_vertical_shell_thickness\n"
- "\nShall I adjust those settings in order to enable Spiral Vase?"));
- wxMessageDialog dialog(parent(), msg_text, _(L("Spiral Vase")), wxICON_WARNING | wxYES | wxNO);
- DynamicPrintConfig new_conf = *m_config;
- if (dialog.ShowModal() == wxID_YES) {
- new_conf.set_key_value("perimeters", new ConfigOptionInt(1));
- new_conf.set_key_value("top_solid_layers", new ConfigOptionInt(0));
- new_conf.set_key_value("fill_density", new ConfigOptionPercent(0));
- new_conf.set_key_value("support_material", new ConfigOptionBool(false));
- new_conf.set_key_value("support_material_enforce_layers", new ConfigOptionInt(0));
- new_conf.set_key_value("ensure_vertical_shell_thickness", new ConfigOptionBool(false));
- fill_density = 0;
- }
- else {
- new_conf.set_key_value("spiral_vase", new ConfigOptionBool(false));
- }
- load_config(new_conf);
- on_value_change("fill_density", fill_density);
- }
-
- if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") &&
- m_config->opt_float("support_material_contact_distance") > 0. &&
- (m_config->opt_int("support_material_extruder") != 0 || m_config->opt_int("support_material_interface_extruder") != 0)) {
- wxString msg_text = _(L("The Wipe Tower currently supports the non-soluble supports only\n"
- "if they are printed with the current extruder without triggering a tool change.\n"
- "(both support_material_extruder and support_material_interface_extruder need to be set to 0).\n"
- "\nShall I adjust those settings in order to enable the Wipe Tower?"));
- wxMessageDialog dialog(parent(), msg_text, _(L("Wipe Tower")), wxICON_WARNING | wxYES | wxNO);
- DynamicPrintConfig new_conf = *m_config;
- if (dialog.ShowModal() == wxID_YES) {
- new_conf.set_key_value("support_material_extruder", new ConfigOptionInt(0));
- new_conf.set_key_value("support_material_interface_extruder", new ConfigOptionInt(0));
- }
- else
- new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false));
- load_config(new_conf);
- }
-
- if (m_config->opt_bool("wipe_tower") && m_config->opt_bool("support_material") &&
- m_config->opt_float("support_material_contact_distance") == 0 &&
- !m_config->opt_bool("support_material_synchronize_layers")) {
- wxString msg_text = _(L("For the Wipe Tower to work with the soluble supports, the support layers\n"
- "need to be synchronized with the object layers.\n"
- "\nShall I synchronize support layers in order to enable the Wipe Tower?"));
- wxMessageDialog dialog(parent(), msg_text, _(L("Wipe Tower")), wxICON_WARNING | wxYES | wxNO);
- DynamicPrintConfig new_conf = *m_config;
- if (dialog.ShowModal() == wxID_YES) {
- new_conf.set_key_value("support_material_synchronize_layers", new ConfigOptionBool(true));
- }
- else
- new_conf.set_key_value("wipe_tower", new ConfigOptionBool(false));
- load_config(new_conf);
- }
-
- if (m_config->opt_bool("support_material")) {
- // Ask only once.
- if (!m_support_material_overhangs_queried) {
- m_support_material_overhangs_queried = true;
- if (!m_config->opt_bool("overhangs")/* != 1* /) {
- wxString msg_text = _(L("Supports work better, if the following feature is enabled:\n"
- "- Detect bridging perimeters\n"
- "\nShall I adjust those settings for supports?"));
- wxMessageDialog dialog(parent(), msg_text, _(L("Support Generator")), wxICON_WARNING | wxYES | wxNO | wxCANCEL);
- DynamicPrintConfig new_conf = *m_config;
- auto answer = dialog.ShowModal();
- if (answer == wxID_YES) {
- // Enable "detect bridging perimeters".
- new_conf.set_key_value("overhangs", new ConfigOptionBool(true));
- } else if (answer == wxID_NO) {
- // Do nothing, leave supports on and "detect bridging perimeters" off.
- } else if (answer == wxID_CANCEL) {
- // Disable supports.
- new_conf.set_key_value("support_material", new ConfigOptionBool(false));
- m_support_material_overhangs_queried = false;
- }
- load_config(new_conf);
- }
- }
- }
- else {
- m_support_material_overhangs_queried = false;
- }
-
- if (m_config->option<ConfigOptionPercent>("fill_density")->value == 100) {
- auto fill_pattern = m_config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->value;
- std::string str_fill_pattern = "";
- t_config_enum_values map_names = m_config->option<ConfigOptionEnum<InfillPattern>>("fill_pattern")->get_enum_values();
- for (auto it : map_names) {
- if (fill_pattern == it.second) {
- str_fill_pattern = it.first;
- break;
- }
- }
- if (!str_fill_pattern.empty()) {
- const std::vector<std::string> &external_fill_pattern = m_config->def()->get("top_fill_pattern")->enum_values;
- bool correct_100p_fill = false;
- for (const std::string &fill : external_fill_pattern)
- {
- if (str_fill_pattern == fill)
- correct_100p_fill = true;
- }
- // get fill_pattern name from enum_labels for using this one at dialog_msg
- str_fill_pattern = _utf8(m_config->def()->get("fill_pattern")->enum_labels[fill_pattern]);
- if (!correct_100p_fill) {
- wxString msg_text = GUI::from_u8((boost::format(_utf8(L("The %1% infill pattern is not supposed to work at 100%% density.\n\n"
- "Shall I switch to rectilinear fill pattern?"))) % str_fill_pattern).str());
- wxMessageDialog dialog(parent(), msg_text, _(L("Infill")), wxICON_WARNING | wxYES | wxNO);
- DynamicPrintConfig new_conf = *m_config;
- if (dialog.ShowModal() == wxID_YES) {
- new_conf.set_key_value("fill_pattern", new ConfigOptionEnum<InfillPattern>(ipRectilinear));
- fill_density = 100;
- }
- else
- fill_density = m_presets->get_selected_preset().config.option<ConfigOptionPercent>("fill_density")->value;
- new_conf.set_key_value("fill_density", new ConfigOptionPercent(fill_density));
- load_config(new_conf);
- on_value_change("fill_density", fill_density);
- }
- }
- }
-
- bool have_perimeters = m_config->opt_int("perimeters") > 0;
- for (auto el : {"extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs",
- "seam_position", "external_perimeters_first", "external_perimeter_extrusion_width",
- "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" })
- get_field(el)->toggle(have_perimeters);
-
- bool have_infill = m_config->option<ConfigOptionPercent>("fill_density")->value > 0;
- // infill_extruder uses the same logic as in Print::extruders()
- for (auto el : {"fill_pattern", "infill_every_layers", "infill_only_where_needed",
- "solid_infill_every_layers", "solid_infill_below_area", "infill_extruder" })
- get_field(el)->toggle(have_infill);
-
- bool have_solid_infill = m_config->opt_int("top_solid_layers") > 0 || m_config->opt_int("bottom_solid_layers") > 0;
- // solid_infill_extruder uses the same logic as in Print::extruders()
- for (auto el : {"top_fill_pattern", "bottom_fill_pattern", "infill_first", "solid_infill_extruder",
- "solid_infill_extrusion_width", "solid_infill_speed" })
- get_field(el)->toggle(have_solid_infill);
-
- for (auto el : {"fill_angle", "bridge_angle", "infill_extrusion_width",
- "infill_speed", "bridge_speed" })
- get_field(el)->toggle(have_infill || have_solid_infill);
-
- get_field("gap_fill_speed")->toggle(have_perimeters && have_infill);
-
- bool have_top_solid_infill = m_config->opt_int("top_solid_layers") > 0;
- for (auto el : { "top_infill_extrusion_width", "top_solid_infill_speed" })
- get_field(el)->toggle(have_top_solid_infill);
-
- bool have_default_acceleration = m_config->opt_float("default_acceleration") > 0;
- for (auto el : {"perimeter_acceleration", "infill_acceleration",
- "bridge_acceleration", "first_layer_acceleration" })
- get_field(el)->toggle(have_default_acceleration);
-
- bool have_skirt = m_config->opt_int("skirts") > 0 || m_config->opt_float("min_skirt_length") > 0;
- for (auto el : { "skirt_distance", "skirt_height" })
- get_field(el)->toggle(have_skirt);
-
- bool have_brim = m_config->opt_float("brim_width") > 0;
- // perimeter_extruder uses the same logic as in Print::extruders()
- get_field("perimeter_extruder")->toggle(have_perimeters || have_brim);
-
- bool have_raft = m_config->opt_int("raft_layers") > 0;
- bool have_support_material = m_config->opt_bool("support_material") || have_raft;
- bool have_support_material_auto = have_support_material && m_config->opt_bool("support_material_auto");
- bool have_support_interface = m_config->opt_int("support_material_interface_layers") > 0;
- bool have_support_soluble = have_support_material && m_config->opt_float("support_material_contact_distance") == 0;
- for (auto el : {"support_material_pattern", "support_material_with_sheath",
- "support_material_spacing", "support_material_angle", "support_material_interface_layers",
- "dont_support_bridges", "support_material_extrusion_width", "support_material_contact_distance",
- "support_material_xy_spacing" })
- get_field(el)->toggle(have_support_material);
- get_field("support_material_threshold")->toggle(have_support_material_auto);
-
- for (auto el : {"support_material_interface_spacing", "support_material_interface_extruder",
- "support_material_interface_speed", "support_material_interface_contact_loops" })
- get_field(el)->toggle(have_support_material && have_support_interface);
- get_field("support_material_synchronize_layers")->toggle(have_support_soluble);
-
- get_field("perimeter_extrusion_width")->toggle(have_perimeters || have_skirt || have_brim);
- get_field("support_material_extruder")->toggle(have_support_material || have_skirt);
- get_field("support_material_speed")->toggle(have_support_material || have_brim || have_skirt);
-
- bool have_sequential_printing = m_config->opt_bool("complete_objects");
- for (auto el : { "extruder_clearance_radius", "extruder_clearance_height" })
- get_field(el)->toggle(have_sequential_printing);
-
- bool have_ooze_prevention = m_config->opt_bool("ooze_prevention");
- get_field("standby_temperature_delta")->toggle(have_ooze_prevention);
-
- bool have_wipe_tower = m_config->opt_bool("wipe_tower");
- for (auto el : { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging"})
- get_field(el)->toggle(have_wipe_tower);
- */
-
m_config_manipulation.update_print_fff_config(m_config, true);
m_recommended_thin_wall_thickness_description_line->SetText(
@@ -2049,7 +1808,7 @@ void TabPrinter::build_fff()
optgroup->append_single_option_line("single_extruder_multi_material");
optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value) {
- size_t extruders_count = boost::any_cast<int>(optgroup->get_value("extruders_count"));
+ size_t extruders_count = boost::any_cast<size_t>(optgroup->get_value("extruders_count"));
wxTheApp->CallAfter([this, opt_key, value, extruders_count]() {
if (opt_key == "extruders_count" || opt_key == "single_extruder_multi_material") {
extruders_count_changed(extruders_count);
@@ -2469,7 +2228,7 @@ void TabPrinter::build_unregular_pages()
// Add/delete Kinematics page according to is_marlin_flavor
size_t existed_page = 0;
- for (int i = n_before_extruders; i < m_pages.size(); ++i) // first make sure it's not there already
+ for (size_t i = n_before_extruders; i < m_pages.size(); ++i) // first make sure it's not there already
if (m_pages[i]->title().find(_(L("Machine limits"))) != std::string::npos) {
if (!is_marlin_flavor || m_rebuild_kinematics_page)
m_pages.erase(m_pages.begin() + i);
@@ -2494,7 +2253,7 @@ void TabPrinter::build_unregular_pages()
(m_has_single_extruder_MM_page && m_extruders_count == 1))
{
// if we have a single extruder MM setup, add a page with configuration options:
- for (int i = 0; i < m_pages.size(); ++i) // first make sure it's not there already
+ for (size_t i = 0; i < m_pages.size(); ++i) // first make sure it's not there already
if (m_pages[i]->title().find(_(L("Single extruder MM setup"))) != std::string::npos) {
m_pages.erase(m_pages.begin() + i);
break;
@@ -2640,8 +2399,8 @@ void TabPrinter::on_preset_loaded()
{
// update the extruders count field
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(m_config->option("nozzle_diameter"));
- int extruders_count = nozzle_diameter->values.size();
- set_value("extruders_count", extruders_count);
+ size_t extruders_count = nozzle_diameter->values.size();
+ set_value("extruders_count", int(extruders_count));
// update the GUI field according to the number of nozzle diameters supplied
extruders_count_changed(extruders_count);
}
@@ -2779,7 +2538,7 @@ void TabPrinter::update_fff()
DynamicPrintConfig new_conf = *m_config;
if (dialog.ShowModal() == wxID_YES) {
auto wipe = static_cast<ConfigOptionBools*>(m_config->option("wipe")->clone());
- for (int w = 0; w < wipe->values.size(); w++)
+ for (size_t w = 0; w < wipe->values.size(); w++)
wipe->values[w] = false;
new_conf.set_key_value("wipe", wipe);
}
@@ -3826,84 +3585,6 @@ void TabSLAPrint::update()
m_update_cnt++;
- /* #ys_FIXME_delete_after_testing (refactoring)
- *
- bool supports_en = m_config->opt_bool("supports_enable");
-
- get_field("support_head_front_diameter")->toggle(supports_en);
- get_field("support_head_penetration")->toggle(supports_en);
- get_field("support_head_width")->toggle(supports_en);
- get_field("support_pillar_diameter")->toggle(supports_en);
- get_field("support_pillar_connection_mode")->toggle(supports_en);
- get_field("support_buildplate_only")->toggle(supports_en);
- get_field("support_base_diameter")->toggle(supports_en);
- get_field("support_base_height")->toggle(supports_en);
- get_field("support_base_safety_distance")->toggle(supports_en);
- get_field("support_critical_angle")->toggle(supports_en);
- get_field("support_max_bridge_length")->toggle(supports_en);
- get_field("support_max_pillar_link_distance")->toggle(supports_en);
- get_field("support_points_density_relative")->toggle(supports_en);
- get_field("support_points_minimal_distance")->toggle(supports_en);
-
- bool pad_en = m_config->opt_bool("pad_enable");
-
- get_field("pad_wall_thickness")->toggle(pad_en);
- get_field("pad_wall_height")->toggle(pad_en);
- get_field("pad_max_merge_distance")->toggle(pad_en);
- // get_field("pad_edge_radius")->toggle(supports_en);
- get_field("pad_wall_slope")->toggle(pad_en);
- get_field("pad_around_object")->toggle(pad_en);
-
- double head_penetration = m_config->opt_float("support_head_penetration");
- double head_width = m_config->opt_float("support_head_width");
- if (head_penetration > head_width) {
- wxString msg_text = _(
- L("Head penetration should not be greater than the head width."));
-
- wxMessageDialog dialog(parent(),
- msg_text,
- _(L("Invalid Head penetration")),
- wxICON_WARNING | wxOK);
-
- DynamicPrintConfig new_conf = *m_config;
- if (dialog.ShowModal() == wxID_OK) {
- new_conf.set_key_value("support_head_penetration",
- new ConfigOptionFloat(head_width));
- }
-
- load_config(new_conf);
- }
-
- double pinhead_d = m_config->opt_float("support_head_front_diameter");
- double pillar_d = m_config->opt_float("support_pillar_diameter");
- if (pinhead_d > pillar_d) {
- wxString msg_text = _(L(
- "Pinhead diameter should be smaller than the pillar diameter."));
-
- wxMessageDialog dialog (parent(),
- msg_text,
- _(L("Invalid pinhead diameter")),
- wxICON_WARNING | wxOK);
-
- DynamicPrintConfig new_conf = *m_config;
- if (dialog.ShowModal() == wxID_OK) {
- new_conf.set_key_value("support_head_front_diameter",
- new ConfigOptionFloat(pillar_d / 2.0));
- }
-
- load_config(new_conf);
- }
-
- bool has_suppad = pad_en && supports_en;
- bool zero_elev = m_config->opt_bool("pad_around_object") && has_suppad;
-
- get_field("support_object_elevation")->toggle(supports_en && !zero_elev);
- get_field("pad_object_gap")->toggle(zero_elev);
- get_field("pad_object_connector_stride")->toggle(zero_elev);
- get_field("pad_object_connector_width")->toggle(zero_elev);
- get_field("pad_object_connector_penetration")->toggle(zero_elev);
-*/
-
m_config_manipulation.update_print_sla_config(m_config, true);
m_update_cnt--;
diff --git a/src/slic3r/GUI/Tab.hpp b/src/slic3r/GUI/Tab.hpp
index f57558c45..ee6937652 100644
--- a/src/slic3r/GUI/Tab.hpp
+++ b/src/slic3r/GUI/Tab.hpp
@@ -321,7 +321,6 @@ protected:
class TabPrint : public Tab
{
- bool is_msg_dlg_already_exist {false};
public:
TabPrint(wxNotebook* parent) :
// Tab(parent, _(L("Print Settings")), L("print")) {}
diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp
index a1a113066..d2a5e185a 100644
--- a/src/slic3r/GUI/UpdateDialogs.cpp
+++ b/src/slic3r/GUI/UpdateDialogs.cpp
@@ -34,10 +34,8 @@ static const std::string CONFIG_UPDATE_WIKI_URL("https://github.com/prusa3d/Prus
// MsgUpdateSlic3r
-MsgUpdateSlic3r::MsgUpdateSlic3r(const Semver &ver_current, const Semver &ver_online) :
- MsgDialog(nullptr, _(L("Update available")), wxString::Format(_(L("New version of %s is available")), SLIC3R_APP_NAME)),
- ver_current(ver_current),
- ver_online(ver_online)
+MsgUpdateSlic3r::MsgUpdateSlic3r(const Semver &ver_current, const Semver &ver_online)
+ : MsgDialog(nullptr, _(L("Update available")), wxString::Format(_(L("New version of %s is available")), SLIC3R_APP_NAME))
{
const bool dev_version = ver_online.prerelease() != nullptr;
diff --git a/src/slic3r/GUI/UpdateDialogs.hpp b/src/slic3r/GUI/UpdateDialogs.hpp
index 4b61b84c2..a916e0145 100644
--- a/src/slic3r/GUI/UpdateDialogs.hpp
+++ b/src/slic3r/GUI/UpdateDialogs.hpp
@@ -31,8 +31,6 @@ public:
bool disable_version_check() const;
private:
- const Semver &ver_current;
- const Semver &ver_online;
wxCheckBox *cbox;
};
diff --git a/src/slic3r/GUI/WipeTowerDialog.cpp b/src/slic3r/GUI/WipeTowerDialog.cpp
index 894b1ee62..460683f77 100644
--- a/src/slic3r/GUI/WipeTowerDialog.cpp
+++ b/src/slic3r/GUI/WipeTowerDialog.cpp
@@ -1,6 +1,7 @@
#include <algorithm>
#include <sstream>
#include "WipeTowerDialog.hpp"
+#include "PresetBundle.hpp"
#include "GUI.hpp"
#include "I18N.hpp"
#include "GUI_App.hpp"
@@ -137,11 +138,11 @@ std::string RammingPanel::get_parameters()
// Parent dialog for purging volume adjustments - it fathers WipingPanel widget (that contains all controls) and a button to toggle simple/advanced mode:
-WipingDialog::WipingDialog(wxWindow* parent,const std::vector<float>& matrix, const std::vector<float>& extruders)
+WipingDialog::WipingDialog(wxWindow* parent, const std::vector<float>& matrix, const std::vector<float>& extruders, const std::vector<std::string>& extruder_colours)
: wxDialog(parent, wxID_ANY, _(L("Wipe tower - Purging volume adjustment")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE/* | wxRESIZE_BORDER*/)
{
auto widget_button = new wxButton(this,wxID_ANY,"-",wxPoint(0,0),wxDefaultSize);
- m_panel_wiping = new WipingPanel(this,matrix,extruders, widget_button);
+ m_panel_wiping = new WipingPanel(this,matrix,extruders, extruder_colours, widget_button);
auto main_sizer = new wxBoxSizer(wxVERTICAL);
@@ -180,7 +181,7 @@ void WipingPanel::format_sizer(wxSizer* sizer, wxPanel* page, wxGridSizer* grid_
}
// This panel contains all control widgets for both simple and advanced mode (these reside in separate sizers)
-WipingPanel::WipingPanel(wxWindow* parent, const std::vector<float>& matrix, const std::vector<float>& extruders, wxButton* widget_button)
+WipingPanel::WipingPanel(wxWindow* parent, const std::vector<float>& matrix, const std::vector<float>& extruders, const std::vector<std::string>& extruder_colours, wxButton* widget_button)
: wxPanel(parent,wxID_ANY, wxDefaultPosition, wxDefaultSize/*,wxBORDER_RAISED*/)
{
m_widget_button = widget_button; // pointer to the button in parent dialog
@@ -188,6 +189,12 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector<float>& matrix, con
m_number_of_extruders = (int)(sqrt(matrix.size())+0.001);
+ for (const std::string& color : extruder_colours) {
+ unsigned char rgb[3];
+ Slic3r::PresetBundle::parse_color(color, rgb);
+ m_colours.push_back(wxColor(rgb[0], rgb[1], rgb[2]));
+ }
+
// Create two switched panels with their own sizers
m_sizer_simple = new wxBoxSizer(wxVERTICAL);
m_sizer_advanced = new wxBoxSizer(wxVERTICAL);
@@ -211,14 +218,36 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector<float>& matrix, con
edit_boxes[i][j]->SetValue(wxString("") << int(matrix[m_number_of_extruders*j + i]));
}
}
+
+ const int clr_icon_side = edit_boxes.front().front()->GetSize().y;
+ const auto icon_size = wxSize(clr_icon_side, clr_icon_side);
+
m_gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("")));
- for (unsigned int i = 0; i < m_number_of_extruders; ++i)
- m_gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("") << i + 1), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
for (unsigned int i = 0; i < m_number_of_extruders; ++i) {
- m_gridsizer_advanced->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("") << i + 1), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
- for (unsigned int j = 0; j < m_number_of_extruders; ++j)
- m_gridsizer_advanced->Add(edit_boxes[j][i], 0);
- }
+ auto hsizer = new wxBoxSizer(wxHORIZONTAL);
+ hsizer->AddSpacer(20);
+ hsizer->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("") << i + 1), 0, wxALIGN_CENTER);
+ wxWindow* w = new wxWindow(m_page_advanced, wxID_ANY, wxDefaultPosition, icon_size, wxBORDER_SIMPLE);
+ w->SetCanFocus(false);
+ w->SetBackgroundColour(m_colours[i]);
+ hsizer->AddStretchSpacer();
+ hsizer->Add(w);
+ m_gridsizer_advanced->Add(hsizer, 1, wxEXPAND);
+ }
+ for (unsigned int i = 0; i < m_number_of_extruders; ++i) {
+ auto hsizer = new wxBoxSizer(wxHORIZONTAL);
+ wxWindow* w = new wxWindow(m_page_advanced, wxID_ANY, wxDefaultPosition, icon_size, wxBORDER_SIMPLE);
+ w->SetCanFocus(false);
+ w->SetBackgroundColour(m_colours[i]);
+ hsizer->AddSpacer(20);
+ hsizer->Add(new wxStaticText(m_page_advanced, wxID_ANY, wxString("") << i + 1), 0, wxALIGN_CENTER | wxALIGN_CENTER_VERTICAL);
+ hsizer->AddStretchSpacer();
+ hsizer->Add(w);
+ m_gridsizer_advanced->Add(hsizer, 1, wxEXPAND);
+
+ for (unsigned int j = 0; j < m_number_of_extruders; ++j)
+ m_gridsizer_advanced->Add(edit_boxes[j][i], 0);
+ }
// collect and format sizer
format_sizer(m_sizer_advanced, m_page_advanced, m_gridsizer_advanced,
@@ -237,7 +266,16 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::vector<float>& matrix, con
for (unsigned int i=0;i<m_number_of_extruders;++i) {
m_old.push_back(new wxSpinCtrl(m_page_simple,wxID_ANY,wxEmptyString,wxDefaultPosition, wxSize(ITEM_WIDTH(), -1),wxSP_ARROW_KEYS|wxALIGN_RIGHT,0,300,extruders[2*i]));
m_new.push_back(new wxSpinCtrl(m_page_simple,wxID_ANY,wxEmptyString,wxDefaultPosition, wxSize(ITEM_WIDTH(), -1),wxSP_ARROW_KEYS|wxALIGN_RIGHT,0,300,extruders[2*i+1]));
- gridsizer_simple->Add(new wxStaticText(m_page_simple, wxID_ANY, wxString(_(L("Tool #"))) << i + 1 << ": "), 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+
+ auto hsizer = new wxBoxSizer(wxHORIZONTAL);
+ wxWindow* w = new wxWindow(m_page_simple, wxID_ANY, wxDefaultPosition, icon_size, wxBORDER_SIMPLE);
+ w->SetCanFocus(false);
+ w->SetBackgroundColour(m_colours[i]);
+ hsizer->Add(w, wxALIGN_CENTER_VERTICAL);
+ hsizer->AddSpacer(10);
+ hsizer->Add(new wxStaticText(m_page_simple, wxID_ANY, wxString(_(L("Tool #"))) << i + 1 << ": "), 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+
+ gridsizer_simple->Add(hsizer, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL);
gridsizer_simple->Add(m_old.back(),0);
gridsizer_simple->Add(m_new.back(),0);
}
diff --git a/src/slic3r/GUI/WipeTowerDialog.hpp b/src/slic3r/GUI/WipeTowerDialog.hpp
index d858062da..84b9921de 100644
--- a/src/slic3r/GUI/WipeTowerDialog.hpp
+++ b/src/slic3r/GUI/WipeTowerDialog.hpp
@@ -46,7 +46,7 @@ private:
class WipingPanel : public wxPanel {
public:
- WipingPanel(wxWindow* parent, const std::vector<float>& matrix, const std::vector<float>& extruders, wxButton* widget_button);
+ WipingPanel(wxWindow* parent, const std::vector<float>& matrix, const std::vector<float>& extruders, const std::vector<std::string>& extruder_colours, wxButton* widget_button);
std::vector<float> read_matrix_values();
std::vector<float> read_extruders_values();
void toggle_advanced(bool user_action = false);
@@ -59,6 +59,7 @@ private:
std::vector<wxSpinCtrl*> m_old;
std::vector<wxSpinCtrl*> m_new;
std::vector<std::vector<wxTextCtrl*>> edit_boxes;
+ std::vector<wxColour> m_colours;
unsigned int m_number_of_extruders = 0;
bool m_advanced = false;
wxPanel* m_page_simple = nullptr;
@@ -76,7 +77,7 @@ private:
class WipingDialog : public wxDialog {
public:
- WipingDialog(wxWindow* parent,const std::vector<float>& matrix, const std::vector<float>& extruders);
+ WipingDialog(wxWindow* parent, const std::vector<float>& matrix, const std::vector<float>& extruders, const std::vector<std::string>& extruder_colours);
std::vector<float> get_matrix() const { return m_output_matrix; }
std::vector<float> get_extruders() const { return m_output_extruders; }
diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp
index 06e9a7f90..5f1e779d6 100644
--- a/src/slic3r/GUI/wxExtensions.cpp
+++ b/src/slic3r/GUI/wxExtensions.cpp
@@ -752,7 +752,7 @@ static bool append_root_node(ObjectDataViewModelNode *parent_node,
if (inst_root_id < 0) {
if ((root_type&itInstanceRoot) ||
- (root_type&itLayerRoot) && get_root_idx(parent_node, itInstanceRoot)<0)
+ ( (root_type&itLayerRoot) && get_root_idx(parent_node, itInstanceRoot)<0) )
parent_node->Append(*root_node);
else if (root_type&itLayerRoot)
parent_node->Insert(*root_node, static_cast<unsigned int>(get_root_idx(parent_node, itInstanceRoot)));
@@ -940,7 +940,7 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item)
// node can be deleted by the Delete, let's check its type while we safely can
bool is_instance_root = (node->m_type & itInstanceRoot);
- for (int i = node->GetChildCount() - 1; i >= (is_instance_root ? 1 : 0); i--)
+ for (int i = int(node->GetChildCount() - 1); i >= (is_instance_root ? 1 : 0); i--)
Delete(wxDataViewItem(node->GetNthChild(i)));
return parent;
@@ -1020,7 +1020,7 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item)
{
int vol_cnt = 0;
int vol_idx = 0;
- for (int i = 0; i < node_parent->GetChildCount(); ++i) {
+ for (size_t i = 0; i < node_parent->GetChildCount(); ++i) {
if (node_parent->GetNthChild(i)->GetType() == itVolume) {
vol_idx = i;
vol_cnt++;
@@ -1059,7 +1059,7 @@ wxDataViewItem ObjectDataViewModel::Delete(const wxDataViewItem &item)
else
{
auto it = find(m_objects.begin(), m_objects.end(), node);
- auto id = it - m_objects.begin();
+ size_t id = it - m_objects.begin();
if (it != m_objects.end())
{
// Delete all sub-items
@@ -1230,7 +1230,7 @@ void ObjectDataViewModel::DeleteSettings(const wxDataViewItem& parent)
wxDataViewItem ObjectDataViewModel::GetItemById(int obj_idx)
{
- if (obj_idx >= m_objects.size())
+ if (size_t(obj_idx) >= m_objects.size())
{
printf("Error! Out of objects range.\n");
return wxDataViewItem(0);
@@ -1241,7 +1241,7 @@ wxDataViewItem ObjectDataViewModel::GetItemById(int obj_idx)
wxDataViewItem ObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volume_idx)
{
- if (obj_idx >= m_objects.size() || obj_idx < 0) {
+ if (size_t(obj_idx) >= m_objects.size()) {
printf("Error! Out of objects range.\n");
return wxDataViewItem(0);
}
@@ -1265,7 +1265,7 @@ wxDataViewItem ObjectDataViewModel::GetItemByVolumeId(int obj_idx, int volume_id
wxDataViewItem ObjectDataViewModel::GetItemById(const int obj_idx, const int sub_obj_idx, const ItemType parent_type)
{
- if (obj_idx >= m_objects.size() || obj_idx < 0) {
+ if (size_t(obj_idx) >= m_objects.size()) {
printf("Error! Out of objects range.\n");
return wxDataViewItem(0);
}
@@ -1294,7 +1294,7 @@ wxDataViewItem ObjectDataViewModel::GetItemByLayerId(int obj_idx, int layer_idx)
wxDataViewItem ObjectDataViewModel::GetItemByLayerRange(const int obj_idx, const t_layer_height_range& layer_range)
{
- if (obj_idx >= m_objects.size() || obj_idx < 0) {
+ if (size_t(obj_idx) >= m_objects.size()) {
printf("Error! Out of objects range.\n");
return wxDataViewItem(0);
}
@@ -1379,7 +1379,12 @@ void ObjectDataViewModel::GetItemInfo(const wxDataViewItem& item, ItemType& type
type = itUndef;
ObjectDataViewModelNode *node = (ObjectDataViewModelNode*)item.GetID();
- if (!node || node->GetIdx() <-1 || node->GetIdx() == -1 && !(node->GetType() & (itObject | itSettings | itInstanceRoot | itLayerRoot/* | itLayer*/)))
+ if (!node ||
+ node->GetIdx() <-1 ||
+ ( node->GetIdx() == -1 &&
+ !(node->GetType() & (itObject | itSettings | itInstanceRoot | itLayerRoot/* | itLayer*/))
+ )
+ )
return;
idx = node->GetIdx();
@@ -1406,13 +1411,13 @@ int ObjectDataViewModel::GetRowByItem(const wxDataViewItem& item) const
int row_num = 0;
- for (int i = 0; i < m_objects.size(); i++)
+ for (size_t i = 0; i < m_objects.size(); i++)
{
row_num++;
if (item == wxDataViewItem(m_objects[i]))
return row_num;
- for (int j = 0; j < m_objects[i]->GetChildCount(); j++)
+ for (size_t j = 0; j < m_objects[i]->GetChildCount(); j++)
{
row_num++;
ObjectDataViewModelNode* cur_node = m_objects[i]->GetNthChild(j);
@@ -1424,7 +1429,7 @@ int ObjectDataViewModel::GetRowByItem(const wxDataViewItem& item) const
if (cur_node->m_type == itInstanceRoot)
{
row_num++;
- for (int t = 0; t < cur_node->GetChildCount(); t++)
+ for (size_t t = 0; t < cur_node->GetChildCount(); t++)
{
row_num++;
if (item == wxDataViewItem(cur_node->GetNthChild(t)))
@@ -1498,7 +1503,7 @@ bool ObjectDataViewModel::SetValue(const wxVariant &variant, const wxDataViewIte
bool ObjectDataViewModel::SetValue(const wxVariant &variant, const int item_idx, unsigned int col)
{
- if (item_idx < 0 || item_idx >= m_objects.size())
+ if (size_t(item_idx) >= m_objects.size())
return false;
return m_objects[item_idx]->SetValue(variant, col);
@@ -1657,7 +1662,7 @@ wxDataViewItem ObjectDataViewModel::GetItemByType(const wxDataViewItem &parent_i
if (node->GetChildCount() == 0)
return wxDataViewItem(0);
- for (int i = 0; i < node->GetChildCount(); i++) {
+ for (size_t i = 0; i < node->GetChildCount(); i++) {
if (node->GetNthChild(i)->m_type == type)
return wxDataViewItem((void*)node->GetNthChild(i));
}
@@ -2140,7 +2145,7 @@ void DoubleSlider::draw_scroll_line(wxDC& dc, const int lower_pos, const int hig
wxCoord segm_end_x = is_horizontal() ? higher_pos : width*0.5 - 1;
wxCoord segm_end_y = is_horizontal() ? height*0.5 - 1 : higher_pos-1;
- for (int id = 0; id < m_line_pens.size(); id++)
+ for (size_t id = 0; id < m_line_pens.size(); id++)
{
dc.SetPen(*m_line_pens[id]);
dc.DrawLine(line_beg_x, line_beg_y, line_end_x, line_end_y);
@@ -2187,9 +2192,9 @@ double DoubleSlider::get_double_value(const SelectedSlider& selection)
return 0.0;
if (m_values.size() <= m_higher_value) {
correct_higher_value();
- return m_values.back().second;
+ return m_values.back();
}
- return m_values[selection == ssLower ? m_lower_value : m_higher_value].second;
+ return m_values[selection == ssLower ? m_lower_value : m_higher_value];
}
std::vector<double> DoubleSlider::GetTicksValues() const
@@ -2201,7 +2206,7 @@ std::vector<double> DoubleSlider::GetTicksValues() const
for (int tick : m_ticks) {
if (tick > val_size)
break;
- values.push_back(m_values[tick].second);
+ values.push_back(m_values[tick]);
}
return values;
@@ -2215,14 +2220,13 @@ void DoubleSlider::SetTicksValues(const std::vector<double>& heights)
const bool was_empty = m_ticks.empty();
m_ticks.clear();
- unsigned int i = 0;
for (auto h : heights) {
- while (i < m_values.size() && m_values[i].second - epsilon()/*1e-6*/ < h)
- ++i;
- // don't miss last layer if it is
- if (i == m_values.size() && fabs(m_values[i-1].second - h) > epsilon())
- return;
- m_ticks.insert(i-1);
+ auto it = std::lower_bound(m_values.begin(), m_values.end(), h - epsilon());
+
+ if (it == m_values.end())
+ continue;
+
+ m_ticks.insert(it-m_values.begin());
}
if (!was_empty && m_ticks.empty())
@@ -2342,13 +2346,14 @@ wxString DoubleSlider::get_label(const SelectedSlider& selection) const
const wxString str = m_values.empty() ?
wxNumberFormatter::ToString(m_label_koef*value, 2, wxNumberFormatter::Style_None) :
- wxNumberFormatter::ToString(m_values[value].second, 2, wxNumberFormatter::Style_None);
- return wxString::Format("%s\n(%d)", str, m_values.empty() ? value : m_values[value].first);
+ wxNumberFormatter::ToString(m_values[value], 2, wxNumberFormatter::Style_None);
+ return wxString::Format("%s\n(%d)", str, m_values.empty() ? value : value+1);
}
void DoubleSlider::draw_thumb_text(wxDC& dc, const wxPoint& pos, const SelectedSlider& selection) const
{
- if ((m_is_one_layer || m_higher_value==m_lower_value) && selection != m_selection || !selection)
+ if ( selection == ssUndef ||
+ ((m_is_one_layer || m_higher_value==m_lower_value) && selection != m_selection) )
return;
wxCoord text_width, text_height;
const wxString label = get_label(selection);
@@ -2489,7 +2494,7 @@ void DoubleSlider::draw_colored_band(wxDC& dc)
dc.SetBrush(clr);
dc.DrawRectangle(main_band);
- int i = 1;
+ size_t i = 1;
for (auto tick : m_ticks)
{
if (i == colors_cnt)
@@ -2680,7 +2685,7 @@ void DoubleSlider::correct_lower_value()
else if (m_lower_value > m_max_value)
m_lower_value = m_max_value;
- if (m_lower_value >= m_higher_value && m_lower_value <= m_max_value || m_is_one_layer)
+ if ((m_lower_value >= m_higher_value && m_lower_value <= m_max_value) || m_is_one_layer)
m_higher_value = m_lower_value;
}
@@ -2691,7 +2696,7 @@ void DoubleSlider::correct_higher_value()
else if (m_higher_value < m_min_value)
m_higher_value = m_min_value;
- if (m_higher_value <= m_lower_value && m_higher_value >= m_min_value || m_is_one_layer)
+ if ((m_higher_value <= m_lower_value && m_higher_value >= m_min_value) || m_is_one_layer)
m_lower_value = m_higher_value;
}
diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp
index 51faffda7..54d1bf7cb 100644
--- a/src/slic3r/GUI/wxExtensions.hpp
+++ b/src/slic3r/GUI/wxExtensions.hpp
@@ -385,9 +385,9 @@ class ObjectDataViewModel :public wxDataViewModel
{
std::vector<ObjectDataViewModelNode*> m_objects;
std::vector<wxBitmap*> m_volume_bmps;
- wxBitmap* m_warning_bmp;
+ wxBitmap* m_warning_bmp { nullptr };
- wxDataViewCtrl* m_ctrl{ nullptr };
+ wxDataViewCtrl* m_ctrl { nullptr };
public:
ObjectDataViewModel();
@@ -720,15 +720,17 @@ public:
const wxString& name = wxEmptyString);
~DoubleSlider() {}
- // permissible error for layer height
+ /* For exporting GCode in GCodeWriter is used XYZF_NUM(val) = PRECISION(val, 3) for XYZ values.
+ * So, let use same value as a permissible error for layer height.
+ */
static double epsilon() { return 0.0011;}
void msw_rescale();
int GetMinValue() const { return m_min_value; }
int GetMaxValue() const { return m_max_value; }
- double GetMinValueD() { return m_values.empty() ? 0. : m_values[m_min_value].second; }
- double GetMaxValueD() { return m_values.empty() ? 0. : m_values[m_max_value].second; }
+ double GetMinValueD() { return m_values.empty() ? 0. : m_values[m_min_value]; }
+ double GetMaxValueD() { return m_values.empty() ? 0. : m_values[m_max_value]; }
int GetLowerValue() const { return m_lower_value; }
int GetHigherValue() const { return m_higher_value; }
int GetActiveValue() const;
@@ -744,7 +746,7 @@ public:
void SetKoefForLabels(const double koef) {
m_label_koef = koef;
}
- void SetSliderValues(const std::vector<std::pair<int, double>>& values) {
+ void SetSliderValues(const std::vector<double>& values) {
m_values = values;
}
void ChangeOneLayerLock();
@@ -865,7 +867,7 @@ private:
std::vector<wxPen*> m_line_pens;
std::vector<wxPen*> m_segm_pens;
std::set<int> m_ticks;
- std::vector<std::pair<int,double>> m_values;
+ std::vector<double> m_values;
};
diff --git a/src/slic3r/Utils/UndoRedo.cpp b/src/slic3r/Utils/UndoRedo.cpp
index b3b2628e2..9c8d7a8c6 100644
--- a/src/slic3r/Utils/UndoRedo.cpp
+++ b/src/slic3r/Utils/UndoRedo.cpp
@@ -363,12 +363,14 @@ private:
MutableHistoryInterval& operator=(const MutableHistoryInterval &rhs);
};
+#ifdef SLIC3R_UNDOREDO_DEBUG
static inline std::string ptr_to_string(const void* ptr)
{
char buf[64];
sprintf(buf, "%p", ptr);
return buf;
}
+#endif
// Smaller objects (Model, ModelObject, ModelInstance, ModelVolume, DynamicPrintConfig)
// are mutable and there is not tracking of the changes, therefore a snapshot needs to be
diff --git a/xs/xsp/Filler.xsp b/xs/xsp/Filler.xsp
index 5f04e7348..34a6d33be 100644
--- a/xs/xsp/Filler.xsp
+++ b/xs/xsp/Filler.xsp
@@ -65,13 +65,6 @@ new_from_type(CLASS, type)
OUTPUT:
RETVAL
-void
-make_fill(CLASS, layer_region, out_append)
- char* CLASS;
- LayerRegion* layer_region;
- ExtrusionEntityCollection* out_append;
- CODE:
- make_fill(*layer_region, *out_append);
%}
};