This commit is contained in:
bubnikv 2019-09-09 17:47:41 +02:00
commit ac7bae8c5d
22 changed files with 199 additions and 182 deletions

View File

@ -162,24 +162,31 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first)
// Read a single facet from an ASCII .STL file // Read a single facet from an ASCII .STL file
// skip solid/endsolid // skip solid/endsolid
// (in this order, otherwise it won't work when they are paired in the middle of a file) // (in this order, otherwise it won't work when they are paired in the middle of a file)
fscanf(fp, "endsolid %*[^\n]\n"); fscanf(fp, " endsolid%*[^\n]\n");
fscanf(fp, "solid %*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid") fscanf(fp, " solid%*[^\n]\n"); // name might contain spaces so %*s doesn't work and it also can be empty (just "solid")
// Leading space in the fscanf format skips all leading white spaces including numerous new lines and tabs. // Leading space in the fscanf format skips all leading white spaces including numerous new lines and tabs.
int res_normal = fscanf(fp, " facet normal %31s %31s %31s ", normal_buf[0], normal_buf[1], normal_buf[2]); int res_normal = fscanf(fp, " facet normal %31s %31s %31s", normal_buf[0], normal_buf[1], normal_buf[2]);
assert(res_normal == 3); assert(res_normal == 3);
int res_outer_loop = fscanf(fp, " outer loop "); int res_outer_loop = fscanf(fp, " outer loop");
assert(res_outer_loop == 0); assert(res_outer_loop == 0);
int res_vertex1 = fscanf(fp, " vertex %f %f %f ", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2)); int res_vertex1 = fscanf(fp, " vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2));
assert(res_vertex1 == 3); assert(res_vertex1 == 3);
int res_vertex2 = fscanf(fp, " vertex %f %f %f ", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2)); int res_vertex2 = fscanf(fp, " vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2));
assert(res_vertex2 == 3); assert(res_vertex2 == 3);
// Trailing whitespace is there to eat all whitespaces and empty lines up to the next non-whitespace.
int res_vertex3 = fscanf(fp, " vertex %f %f %f ", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2)); int res_vertex3 = fscanf(fp, " vertex %f %f %f ", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2));
assert(res_vertex3 == 3); assert(res_vertex3 == 3);
int res_endloop = fscanf(fp, " endloop %*[^\n]\n"); // Some G-code generators tend to produce text after "endloop" and "endfacet". Just ignore it.
assert(res_endloop == 0); char buf[2048];
// There is a leading and trailing white space around endfacet to eat up all leading and trailing white spaces including numerous tabs and new lines. fgets(buf, 2047, fp);
int res_endfacet = fscanf(fp, " endfacet %*[^\n]\n"); bool endloop_ok = strncmp(buf, "endloop", 7) == 0 && (buf[7] == '\n' || buf[7] == ' ' || buf[7] == '\t');
if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || res_endloop != 0 || res_endfacet != 0) { assert(endloop_ok);
// Skip the trailing whitespaces and empty lines.
fscanf(fp, " ");
fgets(buf, 2047, fp);
bool endfacet_ok = strncmp(buf, "endfacet", 8) == 0 && (buf[8] == '\n' || buf[8] == ' ' || buf[8] == '\t');
assert(endfacet_ok);
if (res_normal != 3 || res_outer_loop != 0 || res_vertex1 != 3 || res_vertex2 != 3 || res_vertex3 != 3 || ! endloop_ok || ! endfacet_ok) {
BOOST_LOG_TRIVIAL(error) << "Something is syntactically very wrong with this ASCII STL! "; BOOST_LOG_TRIVIAL(error) << "Something is syntactically very wrong with this ASCII STL! ";
return false; return false;
} }

View File

@ -90,7 +90,7 @@ static speed_t serial_baud_lookup(long baud)
* If a non-standard BAUD rate is used, issue * If a non-standard BAUD rate is used, issue
* a warning (if we are verbose) and return the raw rate * a warning (if we are verbose) and return the raw rate
*/ */
avrdude_message(MSG_NOTICE, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld", avrdude_message(MSG_NOTICE, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld\n",
progname, baud); progname, baud);
return baud; return baud;
@ -110,7 +110,7 @@ static int ser_setspeed(union filedescriptor *fd, long baud)
*/ */
rc = tcgetattr(fd->ifd, &termios); rc = tcgetattr(fd->ifd, &termios);
if (rc < 0) { if (rc < 0) {
avrdude_message(MSG_INFO, "%s: ser_setspeed(): tcgetattr() failed", avrdude_message(MSG_INFO, "%s: ser_setspeed(): tcgetattr() failed\n",
progname); progname);
return -errno; return -errno;
} }

View File

@ -117,9 +117,9 @@ public:
virtual ConfigOption* clone() const = 0; virtual ConfigOption* clone() const = 0;
// Set a value from a ConfigOption. The two options should be compatible. // Set a value from a ConfigOption. The two options should be compatible.
virtual void set(const ConfigOption *option) = 0; 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 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"); return 0; } 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"); return 0; } 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 void setInt(int /* val */) { throw std::runtime_error("Calling ConfigOption::setInt on a non-int ConfigOption"); }
virtual bool operator==(const ConfigOption &rhs) const = 0; virtual bool operator==(const ConfigOption &rhs) const = 0;
bool operator!=(const ConfigOption &rhs) const { return ! (*this == rhs); } 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(). // Is the value nil? That should only be possible if this->nullable().
virtual bool is_nil(size_t idx) const = 0; 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: protected:
// Used to verify type compatibility when assigning to / from a scalar ConfigOption. // Used to verify type compatibility when assigning to / from a scalar ConfigOption.
ConfigOptionType scalar_type() const { return static_cast<ConfigOptionType>(this->type() - coVectorType); } ConfigOptionType scalar_type() const { return static_cast<ConfigOptionType>(this->type() - coVectorType); }
@ -544,7 +550,7 @@ public:
static ConfigOptionType static_type() { return coInt; } static ConfigOptionType static_type() { return coInt; }
ConfigOptionType type() const override { return static_type(); } ConfigOptionType type() const override { return static_type(); }
int getInt() const override { return this->value; } 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); } ConfigOption* clone() const override { return new ConfigOptionInt(*this); }
bool operator==(const ConfigOptionInt &rhs) const { return this->value == rhs.value; } bool operator==(const ConfigOptionInt &rhs) const { return this->value == rhs.value; }
@ -702,7 +708,7 @@ public:
ConfigOption* clone() const override { return new ConfigOptionStrings(*this); } ConfigOption* clone() const override { return new ConfigOptionStrings(*this); }
ConfigOptionStrings& operator=(const ConfigOption *opt) { this->set(opt); return *this; } ConfigOptionStrings& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionStrings &rhs) const { return this->values == rhs.values; } 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 std::string serialize() const override
{ {
@ -917,7 +923,7 @@ public:
ConfigOption* clone() const override { return new ConfigOptionPoints(*this); } ConfigOption* clone() const override { return new ConfigOptionPoints(*this); }
ConfigOptionPoints& operator=(const ConfigOption *opt) { this->set(opt); return *this; } ConfigOptionPoints& operator=(const ConfigOption *opt) { this->set(opt); return *this; }
bool operator==(const ConfigOptionPoints &rhs) const { return this->values == rhs.values; } 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 std::string serialize() const override
{ {
@ -1502,7 +1508,7 @@ protected:
// Both opt_key and value may be modified by handle_legacy(). // 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(). // 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(). // 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: public:
// Non-virtual methods: // Non-virtual methods:
@ -1576,7 +1582,7 @@ public:
DynamicConfig() {} DynamicConfig() {}
DynamicConfig(const DynamicConfig& other) { *this = other; } DynamicConfig(const DynamicConfig& other) { *this = other; }
DynamicConfig(DynamicConfig&& other) : options(std::move(other.options)) { other.options.clear(); } 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. // Copy a content of one DynamicConfig to another DynamicConfig.
// If rhs.def() is not null, then it has to be equal to this->def(). // 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); } 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; } 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); } 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; } 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); } 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> 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; } ENUM opt_enum(const t_config_option_key &opt_key) const { return (ENUM)dynamic_cast<const ConfigOptionEnumGeneric*>(this->option(opt_key))->value; }

View File

@ -8,6 +8,8 @@
#include <limits> #include <limits>
#include <sstream> #include <sstream>
#define L(s) (s)
namespace Slic3r { namespace Slic3r {
void void
@ -318,4 +320,39 @@ ExtrusionLoop::min_mm3_per_mm() const
return min_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 "";
}
//std::string ExtrusionLoop::role_to_string(ExtrusionLoopRole role)
//{
// switch (role) {
// case elrDefault : return "elrDefault";
// case elrContourInternalPerimeter: return "elrContourInternalPerimeter";
// case elrSkirt : return "elrSkirt";
// default : assert(false);
// }
//};
} }

View File

@ -11,7 +11,7 @@ class ExPolygonCollection;
class ExtrusionEntityCollection; class ExtrusionEntityCollection;
class Extruder; class Extruder;
/* Each ExtrusionRole value identifies a distinct set of { extruder, speed } */ // Each ExtrusionRole value identifies a distinct set of { extruder, speed }
enum ExtrusionRole { enum ExtrusionRole {
erNone, erNone,
erPerimeter, erPerimeter,
@ -29,9 +29,17 @@ enum ExtrusionRole {
erCustom, erCustom,
// Extrusion role for a collection with multiple extrusion roles. // Extrusion role for a collection with multiple extrusion roles.
erMixed, erMixed,
erCount, erCount
}; };
// Special flags describing loop
enum ExtrusionLoopRole {
elrDefault,
elrContourInternalPerimeter,
elrSkirt,
};
inline bool is_perimeter(ExtrusionRole role) inline bool is_perimeter(ExtrusionRole role)
{ {
return role == erPerimeter return role == erPerimeter
@ -59,13 +67,6 @@ inline bool is_bridge(ExtrusionRole role) {
|| role == erOverhangPerimeter; || role == erOverhangPerimeter;
} }
/* Special flags describing loop */
enum ExtrusionLoopRole {
elrDefault,
elrContourInternalPerimeter,
elrSkirt,
};
class ExtrusionEntity class ExtrusionEntity
{ {
public: public:
@ -74,7 +75,7 @@ public:
virtual bool is_loop() const { return false; } virtual bool is_loop() const { return false; }
virtual bool can_reverse() const { return true; } virtual bool can_reverse() const { return true; }
virtual ExtrusionEntity* clone() const = 0; virtual ExtrusionEntity* clone() const = 0;
virtual ~ExtrusionEntity() {}; virtual ~ExtrusionEntity() {}
virtual void reverse() = 0; virtual void reverse() = 0;
virtual Point first_point() const = 0; virtual Point first_point() const = 0;
virtual Point last_point() const = 0; virtual Point last_point() const = 0;
@ -96,6 +97,8 @@ public:
virtual Polylines as_polylines() const { Polylines dst; this->collect_polylines(dst); return dst; } virtual Polylines as_polylines() const { Polylines dst; this->collect_polylines(dst); return dst; }
virtual double length() const = 0; virtual double length() const = 0;
virtual double total_volume() const = 0; virtual double total_volume() const = 0;
static std::string role_to_string(ExtrusionRole role);
}; };
typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr; typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;
@ -117,17 +120,17 @@ public:
// Id of the color, used for visualization purposed in the color printing case. // Id of the color, used for visualization purposed in the color printing case.
unsigned int cp_color_id; 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) : 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, 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(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(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(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(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=(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=(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); } ExtrusionPath* clone() const override { return new ExtrusionPath (*this); }
void reverse() { this->polyline.reverse(); } void reverse() override { this->polyline.reverse(); }
Point first_point() const override { return this->polyline.points.front(); } Point first_point() const override { return this->polyline.points.front(); }
Point last_point() const override { return this->polyline.points.back(); } Point last_point() const override { return this->polyline.points.back(); }
size_t size() const { return this->polyline.size(); } size_t size() const { return this->polyline.size(); }
@ -145,18 +148,18 @@ public:
ExtrusionRole role() const override { return m_role; } ExtrusionRole role() const override { return m_role; }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width. // 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. // 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. // 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. // 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. // 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 polygons_covered_by_width(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } { 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 polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } { 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. // 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; } double min_mm3_per_mm() const override { return this->mm3_per_mm; }
Polyline as_polyline() const { return this->polyline; } Polyline as_polyline() const override { return this->polyline; }
void collect_polylines(Polylines &dst) const override { if (! this->polyline.empty()) dst.emplace_back(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()); } double total_volume() const override { return mm3_per_mm * unscale<double>(length()); }
@ -174,37 +177,37 @@ class ExtrusionMultiPath : public ExtrusionEntity
public: public:
ExtrusionPaths paths; ExtrusionPaths paths;
ExtrusionMultiPath() {}; ExtrusionMultiPath() {}
ExtrusionMultiPath(const ExtrusionMultiPath &rhs) : paths(rhs.paths) {} ExtrusionMultiPath(const ExtrusionMultiPath &rhs) : paths(rhs.paths) {}
ExtrusionMultiPath(ExtrusionMultiPath &&rhs) : paths(std::move(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(const ExtrusionPath &path) { this->paths.push_back(path); }
ExtrusionMultiPath& operator=(const ExtrusionMultiPath &rhs) { this->paths = rhs.paths; return *this; } ExtrusionMultiPath& operator=(const ExtrusionMultiPath &rhs) { this->paths = rhs.paths; return *this; }
ExtrusionMultiPath& operator=(ExtrusionMultiPath &&rhs) { this->paths = std::move(rhs.paths); return *this; } ExtrusionMultiPath& operator=(ExtrusionMultiPath &&rhs) { this->paths = std::move(rhs.paths); return *this; }
bool is_loop() const { return false; } bool is_loop() const override { return false; }
bool can_reverse() const { return true; } bool can_reverse() const override { return true; }
ExtrusionMultiPath* clone() const { return new ExtrusionMultiPath(*this); } ExtrusionMultiPath* clone() const override { return new ExtrusionMultiPath(*this); }
void reverse(); void reverse() override;
Point first_point() const override { return this->paths.front().polyline.points.front(); } Point first_point() const override { return this->paths.front().polyline.points.front(); }
Point last_point() const override { return this->paths.back().polyline.points.back(); } Point last_point() const override { return this->paths.back().polyline.points.back(); }
double length() const override; double length() const override;
ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); } 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. // 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. // 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. // 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. // 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. // 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 polygons_covered_by_width(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } { 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 polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } { 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. // Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
double min_mm3_per_mm() const; double min_mm3_per_mm() const override;
Polyline as_polyline() const; 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)); } 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; } double total_volume() const override { double volume =0.; for (const auto& path : paths) volume += path.total_volume(); return volume; }
}; };
@ -215,19 +218,19 @@ class ExtrusionLoop : public ExtrusionEntity
public: public:
ExtrusionPaths paths; ExtrusionPaths paths;
ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : 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(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(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {}
ExtrusionLoop(const ExtrusionPath &path, ExtrusionLoopRole role = elrDefault) : 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) ExtrusionLoop(const ExtrusionPath &&path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
{ this->paths.emplace_back(std::move(path)); }; { this->paths.emplace_back(std::move(path)); }
bool is_loop() const { return true; } bool is_loop() const override{ return true; }
bool can_reverse() const { return false; } bool can_reverse() const override { return false; }
ExtrusionLoop* clone() const { return new ExtrusionLoop (*this); } ExtrusionLoop* clone() const override{ return new ExtrusionLoop (*this); }
bool make_clockwise(); bool make_clockwise();
bool make_counter_clockwise(); bool make_counter_clockwise();
void reverse(); void reverse() override;
Point first_point() const override { return this->paths.front().polyline.points.front(); } 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(); } Point last_point() const override { assert(first_point() == this->paths.back().polyline.points.back()); return first_point(); }
Polygon polygon() const; Polygon polygon() const;
@ -242,21 +245,23 @@ public:
ExtrusionLoopRole loop_role() const { return m_loop_role; } ExtrusionLoopRole loop_role() const { return m_loop_role; }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width. // 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. // 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. // 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. // 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. // 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 polygons_covered_by_width(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } { 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 polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } { 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. // Minimum volumetric velocity of this extrusion entity. Used by the constant nozzle pressure algorithm.
double min_mm3_per_mm() const; double min_mm3_per_mm() const override;
Polyline as_polyline() const { return this->polygon().split_at_first_point(); } 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)); } 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; } 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: private:
ExtrusionLoopRole m_loop_role; ExtrusionLoopRole m_loop_role;
}; };

View File

@ -1916,7 +1916,7 @@ void GCode::process_layer(
_write(file, gcode); _write(file, gcode);
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z << BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
", time estimator memory: " << ", 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: " << ", analyzer memory: " <<
format_memsize_MB(m_analyzer.memory_used()) << format_memsize_MB(m_analyzer.memory_used()) <<
log_memory_info(); log_memory_info();
@ -1997,38 +1997,6 @@ std::string GCode::change_layer(coordf_t print_z)
return gcode; 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. // 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. // The B-spline is re-scaled so it has value 1 at zero.
static inline float bspline_kernel(float x) static inline float bspline_kernel(float x)
@ -2411,8 +2379,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// extrude along the path // extrude along the path
std::string gcode; std::string gcode;
for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) { for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) {
// description += ExtrusionLoopRole2String(loop.loop_role()); // description += ExtrusionLoop::role_to_string(loop.loop_role());
// description += ExtrusionRole2String(path->role); // description += ExtrusionEntity::role_to_string(path->role);
path->simplify(SCALED_RESOLUTION); path->simplify(SCALED_RESOLUTION);
gcode += this->_extrude(*path, description, speed); gcode += this->_extrude(*path, description, speed);
} }
@ -2465,8 +2433,8 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
// extrude along the path // extrude along the path
std::string gcode; std::string gcode;
for (ExtrusionPath path : multipath.paths) { for (ExtrusionPath path : multipath.paths) {
// description += ExtrusionLoopRole2String(loop.loop_role()); // description += ExtrusionLoop::role_to_string(loop.loop_role());
// description += ExtrusionRole2String(path->role); // description += ExtrusionEntity::role_to_string(path->role);
path.simplify(SCALED_RESOLUTION); path.simplify(SCALED_RESOLUTION);
gcode += this->_extrude(path, description, speed); gcode += this->_extrude(path, description, speed);
} }
@ -2495,7 +2463,7 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string des
std::string GCode::extrude_path(ExtrusionPath path, std::string description, double speed) 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); path.simplify(SCALED_RESOLUTION);
std::string gcode = this->_extrude(path, description, speed); std::string gcode = this->_extrude(path, description, speed);
if (m_wipe.enable) { if (m_wipe.enable) {

View File

@ -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(0.0f, 0.0f, 0.0f, 1.0f), // erNone
Color(1.0f, 0.0f, 0.0f, 1.0f), // erPerimeter 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 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; const GCodePreviewData::Extrusion::EViewType GCodePreviewData::Extrusion::Default_View_Type = GCodePreviewData::Extrusion::FeatureType;
void GCodePreviewData::Extrusion::set_default() void GCodePreviewData::Extrusion::set_default()
{ {
view_type = Default_View_Type; 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) for (unsigned int i = 0; i < erCount; ++i)
{ role_names[i] = ExtrusionEntity::role_to_string(ExtrusionRole(i));
role_names[i] = Default_Extrusion_Role_Names[i];
}
role_flags = 0; 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; role_flags |= 1 << i;
}
} }
bool GCodePreviewData::Extrusion::is_role_flag_set(ExtrusionRole role) const 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) 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]) if (role_name == extrusion.role_names[i])
{ {

View File

@ -80,9 +80,8 @@ public:
Num_View_Types Num_View_Types
}; };
static const unsigned int Num_Extrusion_Roles = (unsigned int)erMixed + 1; static const Color Default_Extrusion_Role_Colors[erCount];
static const Color Default_Extrusion_Role_Colors[Num_Extrusion_Roles]; static const std::string Default_Extrusion_Role_Names[erCount];
static const std::string Default_Extrusion_Role_Names[Num_Extrusion_Roles];
static const EViewType Default_View_Type; static const EViewType Default_View_Type;
struct Layer struct Layer
@ -96,8 +95,8 @@ public:
typedef std::vector<Layer> LayersList; typedef std::vector<Layer> LayersList;
EViewType view_type; EViewType view_type;
Color role_colors[Num_Extrusion_Roles]; Color role_colors[erCount];
std::string role_names[Num_Extrusion_Roles]; std::string role_names[erCount];
LayersList layers; LayersList layers;
unsigned int role_flags; unsigned int role_flags;

View File

@ -529,8 +529,9 @@ void Model::convert_multipart_object(unsigned int max_extruders)
} }
} }
object->add_instance(); // commented-out to fix #2868
object->instances[0]->set_offset(object->raw_mesh_bounding_box().center()); // object->add_instance();
// object->instances[0]->set_offset(object->raw_mesh_bounding_box().center());
this->clear_objects(); this->clear_objects();
this->objects.push_back(object); this->objects.push_back(object);

View File

@ -57,7 +57,7 @@ wxBitmap* BitmapCache::insert(const std::string &bitmap_key, size_t width, size_
m_map[bitmap_key] = bitmap; m_map[bitmap_key] = bitmap;
} else { } else {
bitmap = it->second; 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); bitmap->Create(width, height);
} }
#ifndef BROKEN_ALPHA #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)); 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*/) const bool grayscale/* = false*/)
{ {
std::string bitmap_key = bitmap_name + ( height !=0 ? 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) image.GetWidth() == 0 || image.GetHeight() == 0)
return nullptr; return nullptr;
if (height != 0 && image.GetHeight() != height) if (height != 0 && unsigned(image.GetHeight()) != height)
width = int(0.5f + float(image.GetWidth()) * height / image.GetHeight()); width = unsigned(0.5f + float(image.GetWidth()) * height / image.GetHeight());
else if (width != 0 && image.GetWidth() != width) else if (width != 0 && unsigned(image.GetWidth()) != width)
height = int(0.5f + float(image.GetHeight()) * width / image.GetWidth()); height = unsigned(0.5f + float(image.GetHeight()) * width / image.GetWidth());
if (height != 0 && width != 0) if (height != 0 && width != 0)
image.Rescale(width, height, wxIMAGE_QUALITY_BILINEAR); image.Rescale(width, height, wxIMAGE_QUALITY_BILINEAR);

View File

@ -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); 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. // 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. // 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, 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); } 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); }

View File

@ -189,7 +189,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
case coFloatOrPercent: { case coFloatOrPercent: {
if (m_opt.type == coFloatOrPercent && !str.IsEmpty() && str.Last() != '%') if (m_opt.type == coFloatOrPercent && !str.IsEmpty() && str.Last() != '%')
{ {
double val; double val = 0.;
// Replace the first occurence of comma in decimal number. // Replace the first occurence of comma in decimal number.
str.Replace(",", ".", false); str.Replace(",", ".", false);
if (check_value && !str.ToCDouble(&val)) if (check_value && !str.ToCDouble(&val))
@ -198,7 +198,7 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
set_value(double_to_string(val), true); set_value(double_to_string(val), true);
} }
else if (check_value && ((m_opt.sidetext.rfind("mm/s") != std::string::npos && val > m_opt.max) || 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_opt.sidetext.rfind("mm ") != std::string::npos && val > 1)) &&
(m_value.empty() || std::string(str.ToUTF8().data()) != boost::any_cast<std::string>(m_value))) (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"; const std::string sidetext = m_opt.sidetext.rfind("mm/s") != std::string::npos ? "mm/s" : "mm";

View File

@ -60,10 +60,6 @@
#endif // ENABLE_RENDER_STATISTICS #endif // ENABLE_RENDER_STATISTICS
static const float TRACKBALLSIZE = 0.8f; 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_DARK_COLOR[3] = { 0.478f, 0.478f, 0.478f };
static const float DEFAULT_BG_LIGHT_COLOR[3] = { 0.753f, 0.753f, 0.753f }; static const float DEFAULT_BG_LIGHT_COLOR[3] = { 0.753f, 0.753f, 0.753f };
@ -1127,6 +1123,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, Bed3D& bed, Camera& camera, GLToolbar
, m_retina_helper(nullptr) , m_retina_helper(nullptr)
#endif #endif
, m_in_render(false) , m_in_render(false)
, m_render_enabled(true)
, m_bed(bed) , m_bed(bed)
, m_camera(camera) , m_camera(camera)
, m_view_toolbar(view_toolbar) , m_view_toolbar(view_toolbar)
@ -1513,7 +1510,7 @@ void GLCanvas3D::update_volumes_colors_by_extruder()
void GLCanvas3D::render() void GLCanvas3D::render()
{ {
if (m_in_render) if (!m_render_enabled || m_in_render)
{ {
// if called recursively, return // if called recursively, return
m_dirty = true; m_dirty = true;
@ -3909,7 +3906,7 @@ void GLCanvas3D::_picking_pass() const
m_gizmos.set_hover_id(-1); m_gizmos.set_hover_id(-1);
} }
else else
m_gizmos.set_hover_id(inside && volume_id <= (int)GLGizmoBase::BASE_ID ? ((int)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(); _update_volumes_hover_state();
} }

View File

@ -403,6 +403,7 @@ private:
std::unique_ptr<RetinaHelper> m_retina_helper; std::unique_ptr<RetinaHelper> m_retina_helper;
#endif #endif
bool m_in_render; bool m_in_render;
bool m_render_enabled;
LegendTexture m_legend_texture; LegendTexture m_legend_texture;
WarningTexture m_warning_texture; WarningTexture m_warning_texture;
wxTimer m_timer; wxTimer m_timer;
@ -433,7 +434,6 @@ private:
bool m_initialized; bool m_initialized;
bool m_apply_zoom_to_volumes_filter; bool m_apply_zoom_to_volumes_filter;
mutable std::vector<int> m_hover_volume_idxs; mutable std::vector<int> m_hover_volume_idxs;
bool m_warning_texture_enabled;
bool m_legend_texture_enabled; bool m_legend_texture_enabled;
bool m_picking_enabled; bool m_picking_enabled;
bool m_moving_enabled; bool m_moving_enabled;
@ -533,6 +533,9 @@ public:
void enable_dynamic_background(bool enable); void enable_dynamic_background(bool enable);
void allow_multisample(bool allow); 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_bed();
void zoom_to_volumes(); void zoom_to_volumes();
void zoom_to_selection(); void zoom_to_selection();

View File

@ -789,16 +789,11 @@ void ObjectList::OnContextMenu(wxDataViewEvent&)
void ObjectList::list_manipulation() void ObjectList::list_manipulation()
{ {
wxDataViewItem item; wxDataViewItem item;
wxDataViewColumn* col; wxDataViewColumn* col = nullptr;
const wxPoint pt = get_mouse_position_in_control(); const wxPoint pt = get_mouse_position_in_control();
HitTest(pt, item, col); HitTest(pt, item, col);
#ifdef __WXOSX__ // temporary workaround for OSX
// after Yosemite OS X version, HitTest return undefined item
if (!item) item = GetSelection();
#endif // __WXOSX__
if (!item) { if (!item || col == nullptr) {
printf("undefined item\n");
return; return;
} }
@ -1074,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) static bool improper_category(const std::string& category, const int extruders_cnt, const bool is_object_settings = true)
{ {
return category.empty() || return category.empty() ||
extruders_cnt == 1 && (category == "Extruders" || category == "Wipe options" ) || (extruders_cnt == 1 && (category == "Extruders" || category == "Wipe options" )) ||
!is_object_settings && category == "Support material"; (!is_object_settings && category == "Support material");
} }
void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part) void ObjectList::get_options_menu(settings_menu_hierarchy& settings_menu, const bool is_part)

View File

@ -668,7 +668,7 @@ void ObjectManipulation::update_mirror_buttons_visibility()
wxGetApp().CallAfter([this, new_states]{ wxGetApp().CallAfter([this, new_states]{
for (int i=0; i<3; ++i) { for (int i=0; i<3; ++i) {
if (new_states[i] != m_mirror_buttons[i].second) { if (new_states[i] != m_mirror_buttons[i].second) {
const ScalableBitmap* bmp; const ScalableBitmap* bmp = nullptr;
switch (new_states[i]) { switch (new_states[i]) {
case mbHidden : bmp = &m_mirror_bitmap_hidden; m_mirror_buttons[i].first->Enable(false); break; 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; case mbShown : bmp = &m_mirror_bitmap_off; m_mirror_buttons[i].first->Enable(true); break;

View File

@ -3080,18 +3080,28 @@ void Plater::priv::reload_from_disk()
{ {
Plater::TakeSnapshot snapshot(q, _(L("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(); const auto obj_orig_idx = selection.get_object_idx();
if (selection.is_wipe_tower() || obj_orig_idx == -1) { return; } 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]; auto *object_orig = model.objects[obj_orig_idx];
std::vector<fs::path> input_paths(1, object_orig->input_file); 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);
const auto new_idxs = load_files(input_paths, true, 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]; ModelObject *object = model.objects[idx];
object->config.apply(object_orig->config);
object->clear_instances(); object->clear_instances();
for (const ModelInstance *instance : object_orig->instances) { for (const ModelInstance *instance : object_orig->instances) {
object->add_instance(*instance); object->add_instance(*instance);
@ -3103,10 +3113,26 @@ void Plater::priv::reload_from_disk()
} }
} }
if (object_orig->instances.size() > 1)
sidebar->obj_list()->increase_object_instances(idx, object_orig->instances.size());
// XXX: Restore more: layer_height_ranges, layer_height_profile (?) // XXX: Restore more: layer_height_ranges, layer_height_profile (?)
} }
remove(obj_orig_idx); remove(obj_orig_idx);
// 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);
}
wxGetApp().obj_list()->update_and_show_object_settings_item();
} }
void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/) void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* = -1*/)

View File

@ -250,7 +250,7 @@ void PrintHostQueueDialog::on_list_select()
void PrintHostQueueDialog::on_progress(Event &evt) 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) { if (evt.progress < 100) {
set_state(evt.job_id, ST_PROGRESS); set_state(evt.job_id, ST_PROGRESS);
@ -265,7 +265,7 @@ void PrintHostQueueDialog::on_progress(Event &evt)
void PrintHostQueueDialog::on_error(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); set_state(evt.job_id, ST_ERROR);
@ -280,7 +280,7 @@ void PrintHostQueueDialog::on_error(Event &evt)
void PrintHostQueueDialog::on_cancel(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); set_state(evt.job_id, ST_CANCELLED);
job_list->SetValue(wxVariant(0), evt.job_id, COL_PROGRESS); job_list->SetValue(wxVariant(0), evt.job_id, COL_PROGRESS);

View File

@ -37,7 +37,6 @@ public:
private: private:
wxTextCtrl *txt_filename; wxTextCtrl *txt_filename;
wxCheckBox *box_print; wxCheckBox *box_print;
bool can_start_print;
}; };

View File

@ -34,10 +34,8 @@ static const std::string CONFIG_UPDATE_WIKI_URL("https://github.com/prusa3d/Prus
// MsgUpdateSlic3r // MsgUpdateSlic3r
MsgUpdateSlic3r::MsgUpdateSlic3r(const Semver &ver_current, const Semver &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)), : 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)
{ {
const bool dev_version = ver_online.prerelease() != nullptr; const bool dev_version = ver_online.prerelease() != nullptr;

View File

@ -31,8 +31,6 @@ public:
bool disable_version_check() const; bool disable_version_check() const;
private: private:
const Semver &ver_current;
const Semver &ver_online;
wxCheckBox *cbox; wxCheckBox *cbox;
}; };

View File

@ -363,12 +363,14 @@ private:
MutableHistoryInterval& operator=(const MutableHistoryInterval &rhs); MutableHistoryInterval& operator=(const MutableHistoryInterval &rhs);
}; };
#ifdef SLIC3R_UNDOREDO_DEBUG
static inline std::string ptr_to_string(const void* ptr) static inline std::string ptr_to_string(const void* ptr)
{ {
char buf[64]; char buf[64];
sprintf(buf, "%p", ptr); sprintf(buf, "%p", ptr);
return buf; return buf;
} }
#endif
// Smaller objects (Model, ModelObject, ModelInstance, ModelVolume, DynamicPrintConfig) // Smaller objects (Model, ModelObject, ModelInstance, ModelVolume, DynamicPrintConfig)
// are mutable and there is not tracking of the changes, therefore a snapshot needs to be // are mutable and there is not tracking of the changes, therefore a snapshot needs to be