mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-13 18:18:58 +08:00
Complete the C++ CLI; remove the #ifndef SLIC3RXS guards and fix CI by removing std::initializer_lists
This commit is contained in:
parent
11a6601c4a
commit
f0f36cb935
@ -147,6 +147,8 @@ src/libslic3r/PrintGCode.cpp
|
||||
src/libslic3r/PrintGCode.hpp
|
||||
src/libslic3r/PrintObject.cpp
|
||||
src/libslic3r/PrintRegion.cpp
|
||||
src/libslic3r/SimplePrint.cpp
|
||||
src/libslic3r/SimplePrint.hpp
|
||||
src/libslic3r/SLAPrint.cpp
|
||||
src/libslic3r/SLAPrint.hpp
|
||||
src/libslic3r/SlicingAdaptive.cpp
|
||||
|
@ -1,4 +1,3 @@
|
||||
#ifndef SLIC3RXS
|
||||
#include "Config.hpp"
|
||||
#include "Log.hpp"
|
||||
|
||||
@ -22,7 +21,7 @@ Config::new_from_defaults(std::initializer_list<std::string> init)
|
||||
std::shared_ptr<Config>
|
||||
Config::new_from_defaults(t_config_option_keys init)
|
||||
{
|
||||
auto my_config(std::make_shared<Config>());
|
||||
std::shared_ptr<Config> my_config(std::make_shared<Config>());
|
||||
for (auto& opt_key : init) {
|
||||
if (print_config_def.has(opt_key)) {
|
||||
const std::string value { print_config_def.get(opt_key).default_value->serialize() };
|
||||
@ -33,30 +32,25 @@ Config::new_from_defaults(t_config_option_keys init)
|
||||
return my_config;
|
||||
}
|
||||
|
||||
std::shared_ptr<Config>
|
||||
new_from_cli(const int& argc, const char* argv[])
|
||||
{
|
||||
return std::make_shared<Config>();
|
||||
}
|
||||
|
||||
std::shared_ptr<Config>
|
||||
Config::new_from_ini(const std::string& inifile)
|
||||
{
|
||||
|
||||
auto my_config(std::make_shared<Config>());
|
||||
std::shared_ptr<Config> my_config(std::make_shared<Config>());
|
||||
my_config->read_ini(inifile);
|
||||
return my_config;
|
||||
}
|
||||
|
||||
// TODO: this should be merged into ConfigBase::validate()
|
||||
bool
|
||||
Config::validate()
|
||||
{
|
||||
// general validation
|
||||
for (auto k : this->_config.keys()) {
|
||||
if (print_config_def.options.count(k) == 0) continue; // skip over keys that aren't in the master list
|
||||
const auto& opt {print_config_def.options.at(k)};
|
||||
const ConfigOptionDef& opt { print_config_def.options.at(k) };
|
||||
if (opt.cli == "" || std::regex_search(opt.cli, _match_info, _cli_pattern) == false) continue;
|
||||
auto type {_match_info.str(1)};
|
||||
std::string type { _match_info.str(1) };
|
||||
std::vector<std::string> values;
|
||||
if (std::regex_search(type, _match_info, std::regex("@$"))) {
|
||||
type = std::regex_replace(type, std::regex("@$"), std::string("")); // strip off the @ for later;
|
||||
@ -66,7 +60,7 @@ Config::validate()
|
||||
} catch (std::bad_cast& e) {
|
||||
throw InvalidOptionType((std::string("(cast failure) Invalid value for ") + std::string(k)).c_str());
|
||||
}
|
||||
auto tmp_str {tmp_opt->vserialize()};
|
||||
const std::vector<std::string> tmp_str { tmp_opt->vserialize() };
|
||||
values.insert(values.end(), tmp_str.begin(), tmp_str.end());
|
||||
} else {
|
||||
Slic3r::Log::debug("Config::validate", std::string("Not an array"));
|
||||
@ -91,28 +85,28 @@ void
|
||||
Config::set(const t_config_option_key& opt_key, const std::string& value)
|
||||
{
|
||||
try {
|
||||
const auto& def {print_config_def.options.at(opt_key)};
|
||||
const auto& def = print_config_def.options.at(opt_key);
|
||||
switch (def.type) {
|
||||
case coInt:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionInt* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->value = std::stoi(value);
|
||||
} break;
|
||||
case coInts:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionInts* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
|
||||
if (!ptr->deserialize(value, true) ) {
|
||||
throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value."));
|
||||
}
|
||||
} break;
|
||||
case coFloat:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloat* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->setFloat(std::stod(value));
|
||||
} break;
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloatOrPercent* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
|
||||
const size_t perc = value.find("%");
|
||||
ptr->percent = (perc != std::string::npos);
|
||||
if (ptr->percent) {
|
||||
@ -125,21 +119,21 @@ Config::set(const t_config_option_key& opt_key, const std::string& value)
|
||||
} break;
|
||||
case coFloats:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloats* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
|
||||
if (!ptr->deserialize(value, true) ) {
|
||||
throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value."));
|
||||
}
|
||||
} break;
|
||||
case coString:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionString* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
|
||||
if (!ptr->deserialize(value) ) {
|
||||
throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value."));
|
||||
}
|
||||
} break;
|
||||
case coBool:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionBool* ptr {dynamic_cast<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->deserialize(value);
|
||||
} break;
|
||||
default:
|
||||
@ -156,42 +150,42 @@ void
|
||||
Config::set(const t_config_option_key& opt_key, const bool value)
|
||||
{
|
||||
try {
|
||||
const auto& def {print_config_def.options.at(opt_key)};
|
||||
const auto& def = print_config_def.options.at(opt_key);
|
||||
switch (def.type) {
|
||||
case coBool:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionBool* ptr {dynamic_cast<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->value = value;
|
||||
} break;
|
||||
case coInt:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionInt* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->setInt(value);
|
||||
} break;
|
||||
case coInts:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionInts* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(value), true);
|
||||
} break;
|
||||
case coFloat:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloat* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
} break;
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloatOrPercent* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
ptr->percent = false;
|
||||
} break;
|
||||
case coFloats:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloats* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(value), true);
|
||||
} break;
|
||||
case coString:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionString* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
|
||||
if (!ptr->deserialize(std::to_string(value)) ) {
|
||||
throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value."));
|
||||
}
|
||||
@ -209,42 +203,42 @@ void
|
||||
Config::set(const t_config_option_key& opt_key, const int value)
|
||||
{
|
||||
try {
|
||||
const auto& def {print_config_def.options.at(opt_key)};
|
||||
const auto& def = print_config_def.options.at(opt_key);
|
||||
switch (def.type) {
|
||||
case coBool:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionBool* ptr {dynamic_cast<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->value = (value != 0);
|
||||
} break;
|
||||
case coInt:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionInt* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->setInt(value);
|
||||
} break;
|
||||
case coInts:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionInts* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(value), true);
|
||||
} break;
|
||||
case coFloat:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloat* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
} break;
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloatOrPercent* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
ptr->percent = false;
|
||||
} break;
|
||||
case coFloats:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloats* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(value), true);
|
||||
} break;
|
||||
case coString:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionString* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
|
||||
if (!ptr->deserialize(std::to_string(value)) ) {
|
||||
throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value."));
|
||||
}
|
||||
@ -262,37 +256,37 @@ void
|
||||
Config::set(const t_config_option_key& opt_key, const double value)
|
||||
{
|
||||
try {
|
||||
const auto& def {print_config_def.options.at(opt_key)};
|
||||
const auto& def = print_config_def.options.at(opt_key);
|
||||
switch (def.type) {
|
||||
case coInt:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionInt* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->setInt(std::round(value));
|
||||
} break;
|
||||
case coInts:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionInts* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(std::round(value)), true);
|
||||
} break;
|
||||
case coFloat:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloat* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
} break;
|
||||
case coFloatOrPercent:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloatOrPercent* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->setFloat(value);
|
||||
ptr->percent = false;
|
||||
} break;
|
||||
case coFloats:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionFloats* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
|
||||
ptr->deserialize(std::to_string(value), true);
|
||||
} break;
|
||||
case coString:
|
||||
{
|
||||
auto* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
|
||||
ConfigOptionString* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
|
||||
if (!ptr->deserialize(std::to_string(value)) ) {
|
||||
throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value."));
|
||||
}
|
||||
@ -355,7 +349,3 @@ is_valid_float(const std::string& type, const ConfigOptionDef& opt, const std::s
|
||||
Config::Config() : _config(DynamicPrintConfig()) {};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
|
||||
|
||||
#endif // SLIC3RXS
|
||||
|
@ -1,5 +1,3 @@
|
||||
#ifndef SLIC3RXS
|
||||
|
||||
#ifndef CONFIG_HPP
|
||||
#define CONFIG_HPP
|
||||
|
||||
@ -47,9 +45,6 @@ public:
|
||||
/// Factory method to construct a Config with specific default values loaded.
|
||||
static std::shared_ptr<Config> new_from_defaults(t_config_option_keys init);
|
||||
|
||||
/// Factory method to construct a Config from CLI options.
|
||||
static std::shared_ptr<Config> new_from_cli(const int& argc, const char* argv[]);
|
||||
|
||||
/// Factory method to construct a Config from an ini file.
|
||||
static std::shared_ptr<Config> new_from_ini(const std::string& inifile);
|
||||
|
||||
@ -156,5 +151,3 @@ bool is_valid_float(const std::string& type, const ConfigOptionDef& opt, const s
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // CONFIG_HPP
|
||||
|
||||
#endif // SLIC3RXS
|
||||
|
@ -378,7 +378,7 @@ ConfigBase::apply_only(const ConfigBase &other, const t_config_option_keys &opt_
|
||||
continue;
|
||||
}
|
||||
if (default_nonexistent && !other.has(opt_key)) {
|
||||
auto* def_opt = this->def->get(opt_key)->default_value->clone();
|
||||
auto* def_opt = this->def->get(opt_key).default_value->clone();
|
||||
// not the most efficient way, but easier than casting pointers to subclasses
|
||||
bool res = my_opt->deserialize( def_opt->serialize() );
|
||||
if (!res) {
|
||||
@ -434,11 +434,11 @@ ConfigBase::set_deserialize(t_config_option_key opt_key, std::string str, bool a
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this->def->has(opt_key)) {
|
||||
if (!this->def->has(opt_key))
|
||||
throw UnknownOptionException(opt_key);
|
||||
|
||||
const ConfigOptionDef& optdef = this->def->options.at(opt_key);
|
||||
if (!optdef.shortcut.empty())
|
||||
if (!optdef.shortcut.empty()) {
|
||||
for (const t_config_option_key& shortcut : optdef.shortcut)
|
||||
if (!this->set_deserialize(shortcut, str))
|
||||
return false;
|
||||
|
@ -103,8 +103,6 @@ Print::delete_object(size_t idx)
|
||||
// TODO: purge unused regions
|
||||
}
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
|
||||
void
|
||||
Print::process()
|
||||
{
|
||||
@ -176,11 +174,11 @@ Print::make_skirt()
|
||||
// $skirt_height_z in this case is the highest possible skirt height for safety.
|
||||
double skirt_height_z {-1.0};
|
||||
for (const auto& object : this->objects) {
|
||||
size_t skirt_height {
|
||||
const size_t skirt_height {
|
||||
this->has_infinite_skirt() ? object->layer_count() :
|
||||
std::min(size_t(this->config.skirt_height()), object->layer_count())
|
||||
};
|
||||
auto* highest_layer {object->get_layer(skirt_height - 1)};
|
||||
const Layer* highest_layer { object->get_layer(skirt_height - 1) };
|
||||
skirt_height_z = std::max(skirt_height_z, highest_layer->print_z);
|
||||
}
|
||||
|
||||
@ -303,8 +301,6 @@ Print::make_skirt()
|
||||
this->state.set_done(psSkirt);
|
||||
}
|
||||
|
||||
#endif // SLIC3RXS
|
||||
|
||||
void
|
||||
Print::reload_object(size_t idx)
|
||||
{
|
||||
@ -714,8 +710,6 @@ Print::add_model_object(ModelObject* model_object, int idx)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
|
||||
void
|
||||
Print::export_gcode(std::ostream& output, bool quiet)
|
||||
{
|
||||
@ -724,9 +718,8 @@ Print::export_gcode(std::ostream& output, bool quiet)
|
||||
|
||||
if (this->status_cb != nullptr)
|
||||
this->status_cb(90, "Exporting G-Code...");
|
||||
|
||||
auto export_handler {Slic3r::PrintGCode(*this, output)};
|
||||
export_handler.output();
|
||||
|
||||
Slic3r::PrintGCode(*this, output).output();
|
||||
}
|
||||
|
||||
void
|
||||
@ -777,13 +770,12 @@ Print::export_gcode(std::string outfile, bool quiet)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
bool
|
||||
Print::apply_config(config_ptr config) {
|
||||
// dereference the stored pointer and pass the resulting data to apply_config()
|
||||
return this->apply_config(config->config());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool
|
||||
@ -934,12 +926,19 @@ Print::validate() const
|
||||
object->model_object()->instances.front()->transform_polygon(&convex_hull);
|
||||
|
||||
// grow convex hull with the clearance margin
|
||||
convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, 1, jtRound, scale_(0.1)).front();
|
||||
convex_hull = offset(
|
||||
convex_hull,
|
||||
// safety_offset in intersection() is not enough for preventing false positives
|
||||
scale_(this->config.extruder_clearance_radius.value)/2 - scale_(0.01),
|
||||
CLIPPER_OFFSET_SCALE,
|
||||
jtRound, scale_(0.1)
|
||||
).front();
|
||||
|
||||
// now we check that no instance of convex_hull intersects any of the previously checked object instances
|
||||
for (Points::const_iterator copy = object->_shifted_copies.begin(); copy != object->_shifted_copies.end(); ++copy) {
|
||||
Polygon p = convex_hull;
|
||||
p.translate(*copy);
|
||||
|
||||
if (!intersection(a, p).empty())
|
||||
throw InvalidPrintException{"Some objects are too close; your extruder will collide with them."};
|
||||
|
||||
|
@ -113,7 +113,7 @@ class PrintObject
|
||||
// TODO: Fill* fill_maker => (is => 'lazy');
|
||||
PrintState<PrintObjectStep> state;
|
||||
|
||||
Print* print();
|
||||
Print* print() { return this->_print; };
|
||||
ModelObject* model_object() { return this->_model_object; };
|
||||
const ModelObject& model_object() const { return *(this->_model_object); };
|
||||
|
||||
@ -167,8 +167,6 @@ class PrintObject
|
||||
void _make_perimeters();
|
||||
void _infill();
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
|
||||
/// Initialize and generate support material.
|
||||
void generate_support_material();
|
||||
|
||||
@ -200,7 +198,7 @@ class PrintObject
|
||||
/// Idempotence of this method is guaranteed by the fact that we don't remove things from
|
||||
/// fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries.
|
||||
void clip_fill_surfaces();
|
||||
#endif // SLIC3RXS
|
||||
|
||||
private:
|
||||
Print* _print;
|
||||
ModelObject* _model_object;
|
||||
@ -211,12 +209,10 @@ class PrintObject
|
||||
PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox);
|
||||
~PrintObject();
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
/// Outer loop of logic for horizontal shell discovery
|
||||
void _discover_external_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id);
|
||||
/// Inner loop of logic for horizontal shell discovery
|
||||
void _discover_neighbor_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id, const SurfaceType& type, Polygons& solid, const size_t& solid_layers);
|
||||
#endif // SLIC3RXS
|
||||
void _discover_neighbor_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id, const SurfaceType& type, Polygons& solid, const size_t& solid_layers);
|
||||
|
||||
};
|
||||
|
||||
@ -233,13 +229,13 @@ class Print
|
||||
PrintObjectPtrs objects;
|
||||
PrintRegionPtrs regions;
|
||||
PlaceholderParser placeholder_parser;
|
||||
#ifndef SLIC3RXS
|
||||
|
||||
std::function<void(int, const std::string&)> status_cb {nullptr};
|
||||
|
||||
/// Function pointer for the UI side to call post-processing scripts.
|
||||
/// Vector is assumed to be the executable script and all arguments.
|
||||
std::function<void(std::vector<std::string>)> post_process_cb {nullptr};
|
||||
#endif
|
||||
|
||||
double total_used_filament, total_extruded_volume, total_cost, total_weight;
|
||||
std::map<size_t,float> filament_stats;
|
||||
PrintState<PrintStep> state;
|
||||
@ -263,7 +259,6 @@ class Print
|
||||
const PrintRegion* get_region(size_t idx) const { return this->regions.at(idx); };
|
||||
PrintRegion* add_region();
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
/// Triggers the rest of the print process
|
||||
void process();
|
||||
|
||||
@ -275,8 +270,6 @@ class Print
|
||||
|
||||
/// commands a gcode export to a temporary file and return its name
|
||||
std::string export_gcode(bool quiet = false);
|
||||
|
||||
#endif // SLIC3RXS
|
||||
|
||||
// methods for handling state
|
||||
bool invalidate_state_by_config(const PrintConfigBase &config);
|
||||
@ -301,14 +294,12 @@ class Print
|
||||
Flow skirt_flow() const;
|
||||
void _make_brim();
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
/// Generates a skirt around the union of all of
|
||||
/// the objects in the print.
|
||||
void make_skirt();
|
||||
|
||||
/// Generates a brim around all of the objects in the print.
|
||||
void make_brim();
|
||||
#endif // SLIC3RXS
|
||||
|
||||
|
||||
std::set<size_t> object_extruders() const;
|
||||
|
@ -2029,7 +2029,7 @@ CLITransformConfigDef::CLITransformConfigDef()
|
||||
|
||||
def = this->add("repair", coBool);
|
||||
def->label = __TRANS("Repair");
|
||||
def->tooltip = __TRANS("Try to repair any non-manifold meshes (this option is implicitly added whenever we need to slice the model to perform the requested action.");
|
||||
def->tooltip = __TRANS("Try to repair any non-manifold meshes (this option is implicitly added whenever we need to slice the model to perform the requested action).");
|
||||
def->cli = "repair";
|
||||
|
||||
def = this->add("rotate", coFloat);
|
||||
|
@ -1,4 +1,3 @@
|
||||
#ifndef SLIC3RXS
|
||||
#include "PrintGCode.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
|
||||
@ -9,12 +8,6 @@ namespace Slic3r {
|
||||
void
|
||||
PrintGCode::output()
|
||||
{
|
||||
auto& gcodegen {this->_gcodegen};
|
||||
auto& fh {this->fh};
|
||||
auto& print {this->_print};
|
||||
const auto& config {this->config};
|
||||
const auto extruders {print.extruders()};
|
||||
|
||||
// Write information about the generator.
|
||||
time_t rawtime; tm * timeinfo;
|
||||
time(&rawtime);
|
||||
@ -25,16 +18,16 @@ PrintGCode::output()
|
||||
fh << "; Git Commit: " << BUILD_COMMIT << "\n\n";
|
||||
|
||||
// Writes notes (content of all Settings tabs -> Notes)
|
||||
fh << gcodegen.notes();
|
||||
fh << _gcodegen.notes();
|
||||
|
||||
// Write some terse information on the slicing parameters.
|
||||
auto& first_object {*(this->objects.at(0))};
|
||||
auto layer_height {first_object.config.layer_height.getFloat()};
|
||||
PrintObject& first_object { *this->objects.at(0) };
|
||||
const auto layer_height = first_object.config.layer_height.getFloat();
|
||||
|
||||
for (auto* region : print.regions) {
|
||||
for (auto* region : _print.regions) {
|
||||
{
|
||||
auto flow {region->flow(frExternalPerimeter, layer_height, false, false, -1, first_object)};
|
||||
auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("external_perimeter_speed")};
|
||||
const Flow flow { region->flow(frExternalPerimeter, layer_height, false, false, -1, first_object) };
|
||||
auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("external_perimeter_speed");
|
||||
if (config.max_volumetric_speed.getInt() > 0)
|
||||
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
||||
fh << "; external perimeters extrusion width = ";
|
||||
@ -42,8 +35,8 @@ PrintGCode::output()
|
||||
fh << "(" << vol_speed << "mm^3/s)\n";
|
||||
}
|
||||
{
|
||||
auto flow {region->flow(frPerimeter, layer_height, false, false, -1, first_object)};
|
||||
auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("perimeter_speed")};
|
||||
const Flow flow { region->flow(frPerimeter, layer_height, false, false, -1, first_object) };
|
||||
auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("perimeter_speed");
|
||||
if (config.max_volumetric_speed.getInt() > 0)
|
||||
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
||||
fh << "; perimeters extrusion width = ";
|
||||
@ -51,8 +44,8 @@ PrintGCode::output()
|
||||
fh << "(" << vol_speed << "mm^3/s)\n";
|
||||
}
|
||||
{
|
||||
auto flow {region->flow(frInfill, layer_height, false, false, -1, first_object)};
|
||||
auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("infill_speed")};
|
||||
const Flow flow { region->flow(frInfill, layer_height, false, false, -1, first_object) };
|
||||
auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("infill_speed");
|
||||
if (config.max_volumetric_speed.getInt() > 0)
|
||||
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
||||
fh << "; infill extrusion width = ";
|
||||
@ -60,8 +53,8 @@ PrintGCode::output()
|
||||
fh << "(" << vol_speed << "mm^3/s)\n";
|
||||
}
|
||||
{
|
||||
auto flow {region->flow(frSolidInfill, layer_height, false, false, -1, first_object)};
|
||||
auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("solid_infill_speed")};
|
||||
const Flow flow { region->flow(frSolidInfill, layer_height, false, false, -1, first_object) };
|
||||
auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("solid_infill_speed");
|
||||
if (config.max_volumetric_speed.getInt() > 0)
|
||||
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
||||
fh << "; solid infill extrusion width = ";
|
||||
@ -69,26 +62,26 @@ PrintGCode::output()
|
||||
fh << "(" << vol_speed << "mm^3/s)\n";
|
||||
}
|
||||
{
|
||||
auto flow {region->flow(frTopSolidInfill, layer_height, false, false, -1, first_object)};
|
||||
auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("top_solid_infill_speed")};
|
||||
const Flow flow { region->flow(frTopSolidInfill, layer_height, false, false, -1, first_object) };
|
||||
auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("top_solid_infill_speed");
|
||||
if (config.max_volumetric_speed.getInt() > 0)
|
||||
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
||||
fh << "; top solid infill extrusion width = ";
|
||||
fh << std::fixed << std::setprecision(2) << flow.width << "mm ";
|
||||
fh << "(" << vol_speed << "mm^3/s)\n";
|
||||
}
|
||||
if (print.has_support_material()) {
|
||||
auto flow {first_object._support_material_flow()};
|
||||
auto vol_speed {flow.mm3_per_mm() * first_object.config.get_abs_value("support_material_speed")};
|
||||
if (_print.has_support_material()) {
|
||||
const Flow flow { first_object._support_material_flow() };
|
||||
auto vol_speed = flow.mm3_per_mm() * first_object.config.get_abs_value("support_material_speed");
|
||||
if (config.max_volumetric_speed.getInt() > 0)
|
||||
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
||||
fh << "; support material extrusion width = ";
|
||||
fh << std::fixed << std::setprecision(2) << flow.width << "mm ";
|
||||
fh << "(" << vol_speed << "mm^3/s)\n";
|
||||
}
|
||||
if (print.config.first_layer_extrusion_width.getFloat() > 0) {
|
||||
auto flow {region->flow(frPerimeter, layer_height, false, false, -1, first_object)};
|
||||
// auto vol_speed {flow.mm3_per_mm() * print.config.get_abs_value("first_layer_speed")};
|
||||
if (_print.config.first_layer_extrusion_width.getFloat() > 0) {
|
||||
const Flow flow { region->flow(frPerimeter, layer_height, false, false, -1, first_object) };
|
||||
// auto vol_speed = flow.mm3_per_mm() * _print.config.get_abs_value("first_layer_speed");
|
||||
// if (config.max_volumetric_speed.getInt() > 0)
|
||||
// vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
||||
fh << "; first layer extrusion width = ";
|
||||
@ -99,29 +92,29 @@ PrintGCode::output()
|
||||
fh << std::endl;
|
||||
}
|
||||
// Prepare the helper object for replacing placeholders in custom G-Code and output filename
|
||||
print.placeholder_parser.update_timestamp();
|
||||
_print.placeholder_parser.update_timestamp();
|
||||
|
||||
// GCode sets this automatically when change_layer() is called, but needed for skirt/brim as well
|
||||
gcodegen.first_layer = true;
|
||||
_gcodegen.first_layer = true;
|
||||
|
||||
// disable fan
|
||||
if (config.cooling.getBool() && config.disable_fan_first_layers.getInt() > 0) {
|
||||
fh << gcodegen.writer.set_fan(0,1) << "\n";
|
||||
fh << _gcodegen.writer.set_fan(0,1) << "\n";
|
||||
}
|
||||
|
||||
// set bed temperature
|
||||
auto temp{config.first_layer_bed_temperature.getFloat()};
|
||||
const auto temp = config.first_layer_bed_temperature.getFloat();
|
||||
if (config.has_heatbed && temp > 0 && std::regex_search(config.start_gcode.getString(), bed_temp_regex)) {
|
||||
fh << gcodegen.writer.set_bed_temperature(temp, 1);
|
||||
fh << _gcodegen.writer.set_bed_temperature(temp, 1);
|
||||
}
|
||||
|
||||
// Set extruder(s) temperature before and after start gcode.
|
||||
auto include_start_extruder_temp {!std::regex_search(config.start_gcode.getString(), ex_temp_regex)};
|
||||
auto include_start_extruder_temp = !std::regex_search(config.start_gcode.getString(), ex_temp_regex);
|
||||
for(const auto& start_gcode : config.start_filament_gcode.values) {
|
||||
include_start_extruder_temp = include_start_extruder_temp && !std::regex_search(start_gcode, ex_temp_regex);
|
||||
}
|
||||
|
||||
auto include_end_extruder_temp {!std::regex_search(config.end_gcode.getString(), ex_temp_regex)};
|
||||
auto include_end_extruder_temp = !std::regex_search(config.end_gcode.getString(), ex_temp_regex);
|
||||
for(const auto& end_gcode : config.end_filament_gcode.values) {
|
||||
include_end_extruder_temp = include_end_extruder_temp && !std::regex_search(end_gcode, ex_temp_regex);
|
||||
}
|
||||
@ -129,12 +122,12 @@ PrintGCode::output()
|
||||
if (include_start_extruder_temp) this->_print_first_layer_temperature(0);
|
||||
|
||||
// Apply gcode math to start gcode
|
||||
fh << apply_math(gcodegen.placeholder_parser->process(config.start_gcode.value));
|
||||
fh << apply_math(_gcodegen.placeholder_parser->process(config.start_gcode.value));
|
||||
{
|
||||
auto filament_extruder {0U};
|
||||
auto filament_extruder = 0U;
|
||||
for(const auto& start_gcode : config.start_filament_gcode.values) {
|
||||
gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++);
|
||||
fh << apply_math(gcodegen.placeholder_parser->process(start_gcode));
|
||||
_gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++);
|
||||
fh << apply_math(_gcodegen.placeholder_parser->process(start_gcode));
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,7 +135,7 @@ PrintGCode::output()
|
||||
|
||||
|
||||
// Set other general things (preamble)
|
||||
fh << gcodegen.preamble();
|
||||
fh << _gcodegen.preamble();
|
||||
|
||||
// initialize motion planner for object-to-object travel moves
|
||||
if (config.avoid_crossing_perimeters.getBool()) {
|
||||
@ -153,7 +146,7 @@ PrintGCode::output()
|
||||
Polygons polygons {};
|
||||
// Add polygons that aren't just thin walls.
|
||||
for (auto layer : object->layers) {
|
||||
const auto& slice {ExPolygons(layer->slices)};
|
||||
const ExPolygons& slice { layer->slices };
|
||||
std::for_each(slice.cbegin(), slice.cend(), [&polygons] (const ExPolygon& a) { polygons.emplace_back(a.contour); });
|
||||
}
|
||||
|
||||
@ -166,39 +159,70 @@ PrintGCode::output()
|
||||
}
|
||||
}
|
||||
|
||||
gcodegen.avoid_crossing_perimeters.init_external_mp(union_ex(islands_p));
|
||||
_gcodegen.avoid_crossing_perimeters.init_external_mp(union_ex(islands_p));
|
||||
}
|
||||
|
||||
const auto extruders = _print.extruders();
|
||||
|
||||
// Calculate wiping points if needed.
|
||||
if (config.ooze_prevention && extruders.size() > 1) {
|
||||
/*
|
||||
TODO: PORT THIS!
|
||||
my @skirt_points = map @$_, map @$_, @{$self->print->skirt};
|
||||
if (@skirt_points) {
|
||||
my $outer_skirt = convex_hull(\@skirt_points);
|
||||
my @skirts = ();
|
||||
foreach my $extruder_id (@extruders) {
|
||||
my $extruder_offset = $self->config->get_at('extruder_offset', $extruder_id);
|
||||
push @skirts, my $s = $outer_skirt->clone;
|
||||
$s->translate(-scale($extruder_offset->x), -scale($extruder_offset->y)); #)
|
||||
}
|
||||
my $convex_hull = convex_hull([ map @$_, @skirts ]);
|
||||
|
||||
$gcodegen->ooze_prevention->set_enable(1);
|
||||
$gcodegen->ooze_prevention->set_standby_points(
|
||||
[ map @{$_->equally_spaced_points(scale 10)}, @{offset([$convex_hull], scale 3)} ]
|
||||
);
|
||||
|
||||
if (0) {
|
||||
require "Slic3r/SVG.pm";
|
||||
Slic3r::SVG::output(
|
||||
"ooze_prevention.svg",
|
||||
red_polygons => \@skirts,
|
||||
polygons => [$outer_skirt],
|
||||
points => $gcodegen->ooze_prevention->standby_points,
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// Set initial extruder only after custom start gcode
|
||||
fh << gcodegen.set_extruder(*(extruders.begin()));
|
||||
fh << _gcodegen.set_extruder( *(extruders.begin()) );
|
||||
|
||||
// Do all objects for each layer.
|
||||
|
||||
if (config.complete_objects) {
|
||||
// print objects from the smallest to the tallest to avoid collisions
|
||||
// when moving onto next object starting point
|
||||
std::sort(print.objects.begin(), print.objects.end(), [] (const PrintObject* a, const PrintObject* b) {
|
||||
std::sort(_print.objects.begin(), _print.objects.end(), [] (const PrintObject* a, const PrintObject* b) {
|
||||
return (a->config.sequential_print_priority < a->config.sequential_print_priority) || (a->size.z < b->size.z);
|
||||
});
|
||||
size_t finished_objects {0};
|
||||
|
||||
for (size_t obj_idx {0}; obj_idx < print.objects.size(); ++obj_idx) {
|
||||
for (size_t obj_idx {0}; obj_idx < _print.objects.size(); ++obj_idx) {
|
||||
PrintObject& object {*(this->objects.at(obj_idx))};
|
||||
for (const Point& copy : object._shifted_copies) {
|
||||
if (finished_objects > 0) {
|
||||
gcodegen.set_origin(Pointf::new_unscale(copy));
|
||||
gcodegen.enable_cooling_markers = false;
|
||||
gcodegen.avoid_crossing_perimeters.use_external_mp_once = true;
|
||||
fh << gcodegen.retract();
|
||||
fh << gcodegen.travel_to(Point(0,0), erNone, "move to origin position for next object");
|
||||
_gcodegen.set_origin(Pointf::new_unscale(copy));
|
||||
_gcodegen.enable_cooling_markers = false;
|
||||
_gcodegen.avoid_crossing_perimeters.use_external_mp_once = true;
|
||||
fh << _gcodegen.retract();
|
||||
fh << _gcodegen.travel_to(Point(0,0), erNone, "move to origin position for next object");
|
||||
|
||||
gcodegen.enable_cooling_markers = true;
|
||||
_gcodegen.enable_cooling_markers = true;
|
||||
// disable motion planner when traveling to first object point
|
||||
gcodegen.avoid_crossing_perimeters.disable_once = true;
|
||||
_gcodegen.avoid_crossing_perimeters.disable_once = true;
|
||||
}
|
||||
std::vector<Layer*> layers;
|
||||
layers.reserve(object.layers.size() + object.support_layers.size());
|
||||
@ -218,7 +242,7 @@ PrintGCode::output()
|
||||
config.has_heatbed &&
|
||||
std::regex_search(config.between_objects_gcode.getString(), bed_temp_regex))
|
||||
{
|
||||
fh << gcodegen.writer.set_bed_temperature(config.first_layer_bed_temperature);
|
||||
fh << _gcodegen.writer.set_bed_temperature(config.first_layer_bed_temperature);
|
||||
}
|
||||
if (std::regex_search(config.between_objects_gcode.getString(), ex_temp_regex)) {
|
||||
_print_first_layer_temperature(false);
|
||||
@ -242,8 +266,8 @@ PrintGCode::output()
|
||||
std::vector<size_t> z;
|
||||
z.reserve(100); // preallocate with 100 layers
|
||||
std::map<coord_t, std::map<size_t, LayerPtrs > > layers {};
|
||||
for (size_t idx = 0U; idx < print.objects.size(); ++idx) {
|
||||
const auto& object {*(objects.at(idx))};
|
||||
for (size_t idx = 0U; idx < _print.objects.size(); ++idx) {
|
||||
const PrintObject& object { *objects.at(idx) };
|
||||
// sort layers by Z into buckets
|
||||
for (Layer* layer : object.layers) {
|
||||
if (layers.count(scale_(layer->print_z)) == 0) { // initialize bucket if empty
|
||||
@ -272,47 +296,47 @@ PrintGCode::output()
|
||||
this->process_layer(idx, layer, layer->object()->_shifted_copies);
|
||||
}
|
||||
}
|
||||
gcodegen.placeholder_parser->set("layer_z", unscale(print_z));
|
||||
gcodegen.placeholder_parser->set("layer_num", gcodegen.layer_index);
|
||||
_gcodegen.placeholder_parser->set("layer_z", unscale(print_z));
|
||||
_gcodegen.placeholder_parser->set("layer_num", _gcodegen.layer_index);
|
||||
}
|
||||
|
||||
this->flush_filters();
|
||||
}
|
||||
|
||||
// Write end commands to file.
|
||||
fh << gcodegen.retract(); // TODO: process this retract through PressureRegulator in order to discharge fully
|
||||
fh << _gcodegen.retract(); // TODO: process this retract through PressureRegulator in order to discharge fully
|
||||
|
||||
{
|
||||
auto filament_extruder {0U};
|
||||
auto filament_extruder = 0U;
|
||||
for(const auto& end_gcode : config.end_filament_gcode.values) {
|
||||
gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++);
|
||||
fh << apply_math(gcodegen.placeholder_parser->process(end_gcode));
|
||||
_gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++);
|
||||
fh << apply_math(_gcodegen.placeholder_parser->process(end_gcode));
|
||||
}
|
||||
}
|
||||
|
||||
fh << apply_math(gcodegen.placeholder_parser->process(config.end_gcode));
|
||||
fh << apply_math(_gcodegen.placeholder_parser->process(config.end_gcode));
|
||||
|
||||
// set bed temperature
|
||||
if (config.has_heatbed && temp > 0 && std::regex_search(config.end_gcode.getString(), bed_temp_regex)) {
|
||||
fh << gcodegen.writer.set_bed_temperature(0, 0);
|
||||
fh << _gcodegen.writer.set_bed_temperature(0, 0);
|
||||
}
|
||||
|
||||
// Get filament stats
|
||||
print.filament_stats.clear();
|
||||
print.total_used_filament = 0.0;
|
||||
print.total_extruded_volume = 0.0;
|
||||
print.total_weight = 0.0;
|
||||
print.total_cost = 0.0;
|
||||
_print.filament_stats.clear();
|
||||
_print.total_used_filament = 0.0;
|
||||
_print.total_extruded_volume = 0.0;
|
||||
_print.total_weight = 0.0;
|
||||
_print.total_cost = 0.0;
|
||||
|
||||
|
||||
for (auto extruder_pair : gcodegen.writer.extruders) {
|
||||
const auto& extruder {extruder_pair.second};
|
||||
auto used_material {extruder.used_filament()};
|
||||
auto extruded_volume {extruder.extruded_volume()};
|
||||
auto material_weight {extruded_volume * extruder.filament_density() / 1000.0};
|
||||
auto material_cost { material_weight * (extruder.filament_cost() / 1000.0)};
|
||||
for (auto extruder_pair : _gcodegen.writer.extruders) {
|
||||
const Extruder& extruder { extruder_pair.second };
|
||||
const auto used_material = extruder.used_filament();
|
||||
const auto extruded_volume = extruder.extruded_volume();
|
||||
const auto material_weight = extruded_volume * extruder.filament_density() / 1000.0;
|
||||
const auto material_cost = material_weight * (extruder.filament_cost() / 1000.0);
|
||||
|
||||
print.filament_stats[extruder.id] = used_material;
|
||||
_print.filament_stats[extruder.id] = used_material;
|
||||
|
||||
fh << "; material used = ";
|
||||
fh << std::fixed << std::setprecision(2) << used_material << "mm ";
|
||||
@ -321,28 +345,28 @@ PrintGCode::output()
|
||||
<< used_material << "cm3)\n";
|
||||
|
||||
if (material_weight > 0) {
|
||||
print.total_weight += material_weight;
|
||||
_print.total_weight += material_weight;
|
||||
fh << "; material used = "
|
||||
<< std::fixed << std::setprecision(2) << material_weight << "g\n";
|
||||
if (material_cost > 0) {
|
||||
print.total_cost += material_cost;
|
||||
_print.total_cost += material_cost;
|
||||
fh << "; material cost = "
|
||||
<< std::fixed << std::setprecision(2) << material_weight << "g\n";
|
||||
}
|
||||
}
|
||||
print.total_used_filament += used_material;
|
||||
print.total_extruded_volume += extruded_volume;
|
||||
_print.total_used_filament += used_material;
|
||||
_print.total_extruded_volume += extruded_volume;
|
||||
}
|
||||
fh << "; total filament cost = "
|
||||
<< std::fixed << std::setprecision(2) << print.total_cost << "\n";
|
||||
<< std::fixed << std::setprecision(2) << _print.total_cost << "\n";
|
||||
|
||||
// Append full config
|
||||
fh << std::endl;
|
||||
|
||||
// print config
|
||||
_print_config(print.config);
|
||||
_print_config(print.default_object_config);
|
||||
_print_config(print.default_region_config);
|
||||
_print_config(_print.config);
|
||||
_print_config(_print.default_object_config);
|
||||
_print_config(_print.default_region_config);
|
||||
}
|
||||
|
||||
std::string
|
||||
@ -355,17 +379,14 @@ void
|
||||
PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
||||
{
|
||||
std::string gcode {""};
|
||||
auto& gcodegen {this->_gcodegen};
|
||||
const auto& print {this->_print};
|
||||
const auto& config {this->config};
|
||||
|
||||
const auto& obj {*(layer->object())};
|
||||
gcodegen.config.apply(obj.config, true);
|
||||
const PrintObject& obj { *layer->object() };
|
||||
_gcodegen.config.apply(obj.config, true);
|
||||
|
||||
// check for usage of spiralvase logic.
|
||||
this->_spiral_vase.enable = (
|
||||
layer->id() > 0
|
||||
&& (print.config.skirts == 0 || (layer->id() >= print.config.skirt_height && !print.has_infinite_skirt()))
|
||||
&& (_print.config.skirts == 0 || (layer->id() >= _print.config.skirt_height && !_print.has_infinite_skirt()))
|
||||
&& std::find_if(layer->regions.cbegin(), layer->regions.cend(), [layer] (const LayerRegion* l)
|
||||
{ return l->region()->config.bottom_solid_layers > layer->id()
|
||||
|| l->perimeters.items_count() > 1
|
||||
@ -382,9 +403,9 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
||||
{
|
||||
// get the minimum cross-section used in the layer.
|
||||
std::vector<double> mm3_per_mm;
|
||||
for (auto region_id = 0U; region_id < print.regions.size(); ++region_id) {
|
||||
const auto& region {print.regions.at(region_id)};
|
||||
const auto& layerm {layer->get_region(region_id)};
|
||||
for (auto region_id = 0U; region_id < _print.regions.size(); ++region_id) {
|
||||
const PrintRegion* region = _print.get_region(region_id);
|
||||
const LayerRegion* layerm = layer->get_region(region_id);
|
||||
|
||||
if (!(region->config.get_abs_value("perimeter_speed") > 0 &&
|
||||
region->config.get_abs_value("small_perimeter_speed") > 0 &&
|
||||
@ -417,53 +438,53 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
||||
// TODO make the definition of "too thin" based on a config somewhere
|
||||
mm3_per_mm.erase(std::remove_if(mm3_per_mm.begin(), mm3_per_mm.end(), [] (const double& vol) { return vol <= 0.01;} ), mm3_per_mm.end());
|
||||
if (mm3_per_mm.size() > 0) {
|
||||
const auto min_mm3_per_mm {*(std::min_element(mm3_per_mm.begin(), mm3_per_mm.end()))};
|
||||
const double min_mm3_per_mm { *(std::min_element(mm3_per_mm.begin(), mm3_per_mm.end())) };
|
||||
// In order to honor max_print_speed we need to find a target volumetric
|
||||
// speed that we can use throughout the print. So we define this target
|
||||
// speed that we can use throughout the _print. So we define this target
|
||||
// volumetric speed as the volumetric speed produced by printing the
|
||||
// smallest cross-section at the maximum speed: any larger cross-section
|
||||
// will need slower feedrates.
|
||||
auto volumetric_speed {min_mm3_per_mm * config.max_print_speed};
|
||||
double volumetric_speed { min_mm3_per_mm * config.max_print_speed };
|
||||
if (config.max_volumetric_speed > 0) {
|
||||
volumetric_speed = std::min(volumetric_speed, config.max_volumetric_speed.getFloat());
|
||||
}
|
||||
gcodegen.volumetric_speed = volumetric_speed;
|
||||
_gcodegen.volumetric_speed = volumetric_speed;
|
||||
}
|
||||
}
|
||||
// set the second layer + temp
|
||||
if (!this->_second_layer_things_done && layer->id() == 1) {
|
||||
for (const auto& extruder_ref : gcodegen.writer.extruders) {
|
||||
const auto& extruder { extruder_ref.second };
|
||||
auto temp { config.temperature.get_at(extruder.id) };
|
||||
for (const auto& extruder_ref : _gcodegen.writer.extruders) {
|
||||
const Extruder& extruder { extruder_ref.second };
|
||||
auto temp = config.temperature.get_at(extruder.id);
|
||||
|
||||
if (temp > 0 && temp != config.first_layer_temperature.get_at(extruder.id) )
|
||||
gcode += gcodegen.writer.set_temperature(temp, 0, extruder.id);
|
||||
gcode += _gcodegen.writer.set_temperature(temp, 0, extruder.id);
|
||||
|
||||
}
|
||||
if (config.has_heatbed && print.config.first_layer_bed_temperature > 0 && print.config.bed_temperature != print.config.first_layer_bed_temperature) {
|
||||
gcode += gcodegen.writer.set_bed_temperature(print.config.bed_temperature);
|
||||
if (config.has_heatbed && _print.config.first_layer_bed_temperature > 0 && _print.config.bed_temperature != _print.config.first_layer_bed_temperature) {
|
||||
gcode += _gcodegen.writer.set_bed_temperature(_print.config.bed_temperature);
|
||||
}
|
||||
this->_second_layer_things_done = true;
|
||||
}
|
||||
|
||||
// set new layer - this will change Z and force a retraction if retract_layer_change is enabled
|
||||
if (print.config.before_layer_gcode.getString().size() > 0) {
|
||||
auto pp {*(gcodegen.placeholder_parser)};
|
||||
pp.set("layer_num", gcodegen.layer_index);
|
||||
if (_print.config.before_layer_gcode.getString().size() > 0) {
|
||||
PlaceholderParser pp { *_gcodegen.placeholder_parser };
|
||||
pp.set("layer_num", _gcodegen.layer_index);
|
||||
pp.set("layer_z", layer->print_z);
|
||||
pp.set("current_retraction", gcodegen.writer.extruder()->retracted);
|
||||
pp.set("current_retraction", _gcodegen.writer.extruder()->retracted);
|
||||
|
||||
gcode += apply_math(pp.process(print.config.before_layer_gcode.getString()));
|
||||
gcode += apply_math(pp.process(_print.config.before_layer_gcode.getString()));
|
||||
gcode += "\n";
|
||||
}
|
||||
gcode += gcodegen.change_layer(*layer);
|
||||
if (print.config.layer_gcode.getString().size() > 0) {
|
||||
auto pp {*(gcodegen.placeholder_parser)};
|
||||
pp.set("layer_num", gcodegen.layer_index);
|
||||
gcode += _gcodegen.change_layer(*layer);
|
||||
if (_print.config.layer_gcode.getString().size() > 0) {
|
||||
PlaceholderParser pp { *_gcodegen.placeholder_parser };
|
||||
pp.set("layer_num", _gcodegen.layer_index);
|
||||
pp.set("layer_z", layer->print_z);
|
||||
pp.set("current_retraction", gcodegen.writer.extruder()->retracted);
|
||||
pp.set("current_retraction", _gcodegen.writer.extruder()->retracted);
|
||||
|
||||
gcode += apply_math(pp.process(print.config.layer_gcode.getString()));
|
||||
gcode += apply_math(pp.process(_print.config.layer_gcode.getString()));
|
||||
gcode += "\n";
|
||||
}
|
||||
|
||||
@ -471,73 +492,73 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
||||
// extrude skirt along raft layers and normal obj layers
|
||||
// (not along interlaced support material layers)
|
||||
if (layer->id() < static_cast<size_t>(obj.config.raft_layers)
|
||||
|| ((print.has_infinite_skirt() || _skirt_done.size() == 0 || (_skirt_done.rbegin())->first < print.config.skirt_height)
|
||||
|| ((_print.has_infinite_skirt() || _skirt_done.size() == 0 || (_skirt_done.rbegin())->first < _print.config.skirt_height)
|
||||
&& _skirt_done.count(scale_(layer->print_z)) == 0
|
||||
&& typeid(layer) != typeid(SupportLayer*)) ) {
|
||||
|
||||
|
||||
gcodegen.set_origin(Pointf(0,0));
|
||||
gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
||||
_gcodegen.set_origin(Pointf(0,0));
|
||||
_gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
||||
|
||||
/// data load
|
||||
std::vector<size_t> extruder_ids;
|
||||
extruder_ids.reserve(gcodegen.writer.extruders.size());
|
||||
std::transform(gcodegen.writer.extruders.cbegin(), gcodegen.writer.extruders.cend(), std::back_inserter(extruder_ids),
|
||||
extruder_ids.reserve(_gcodegen.writer.extruders.size());
|
||||
std::transform(_gcodegen.writer.extruders.cbegin(), _gcodegen.writer.extruders.cend(), std::back_inserter(extruder_ids),
|
||||
[] (const std::pair<unsigned int, Extruder>& z) -> std::size_t { return z.second.id; } );
|
||||
gcode += gcodegen.set_extruder(extruder_ids.at(0));
|
||||
gcode += _gcodegen.set_extruder(extruder_ids.at(0));
|
||||
|
||||
// skip skirt if a large brim
|
||||
if (print.has_infinite_skirt() || layer->id() < static_cast<size_t>(print.config.skirt_height)) {
|
||||
const auto& skirt_flow {print.skirt_flow()};
|
||||
if (_print.has_infinite_skirt() || layer->id() < static_cast<size_t>(_print.config.skirt_height)) {
|
||||
const Flow skirt_flow { _print.skirt_flow() };
|
||||
|
||||
// distribute skirt loops across all extruders in layer 0
|
||||
auto skirt_loops {print.skirt.flatten().entities};
|
||||
const auto skirt_loops = _print.skirt.flatten().entities;
|
||||
for (size_t i = 0; i < skirt_loops.size(); ++i) {
|
||||
|
||||
// when printing layers > 0 ignore 'min_skirt_length' and
|
||||
// just use the 'skirts' setting; also just use the current extruder
|
||||
if (layer->id() > 0 && i >= static_cast<size_t>(print.config.skirts)) break;
|
||||
const auto extruder_id { extruder_ids.at((i / extruder_ids.size()) % extruder_ids.size()) };
|
||||
if (layer->id() > 0 && i >= static_cast<size_t>(_print.config.skirts)) break;
|
||||
const size_t extruder_id { extruder_ids.at((i / extruder_ids.size()) % extruder_ids.size()) };
|
||||
if (layer->id() == 0)
|
||||
gcode += gcodegen.set_extruder(extruder_id);
|
||||
gcode += _gcodegen.set_extruder(extruder_id);
|
||||
|
||||
// adjust flow according to layer height
|
||||
auto& loop {*(dynamic_cast<ExtrusionLoop*>(skirt_loops.at(i)))};
|
||||
auto& loop = *dynamic_cast<ExtrusionLoop*>(skirt_loops.at(i));
|
||||
{
|
||||
Flow layer_skirt_flow(skirt_flow);
|
||||
layer_skirt_flow.height = layer->height;
|
||||
|
||||
auto mm3_per_mm {layer_skirt_flow.mm3_per_mm()};
|
||||
const auto mm3_per_mm = layer_skirt_flow.mm3_per_mm();
|
||||
|
||||
for (auto& path : loop.paths) {
|
||||
path.height = layer->height;
|
||||
path.mm3_per_mm = mm3_per_mm;
|
||||
}
|
||||
}
|
||||
gcode += gcodegen.extrude(loop, "skirt", obj.config.support_material_speed);
|
||||
gcode += _gcodegen.extrude(loop, "skirt", obj.config.support_material_speed);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this->_skirt_done[scale_(layer->print_z)] = true;
|
||||
gcodegen.avoid_crossing_perimeters.use_external_mp = false;
|
||||
_gcodegen.avoid_crossing_perimeters.use_external_mp = false;
|
||||
|
||||
if (layer->id() == 0) gcodegen.avoid_crossing_perimeters.disable_once = true;
|
||||
if (layer->id() == 0) _gcodegen.avoid_crossing_perimeters.disable_once = true;
|
||||
}
|
||||
|
||||
// extrude brim
|
||||
if (this->_brim_done) {
|
||||
gcode += gcodegen.set_extruder(print.brim_extruder() - 1);
|
||||
gcodegen.set_origin(Pointf(0,0));
|
||||
gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
||||
for (const auto& b : print.brim.entities) {
|
||||
gcode += gcodegen.extrude(*b, "brim", obj.config.get_abs_value("support_material_speed"));
|
||||
gcode += _gcodegen.set_extruder(_print.brim_extruder() - 1);
|
||||
_gcodegen.set_origin(Pointf(0,0));
|
||||
_gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
||||
for (const auto& b : _print.brim.entities) {
|
||||
gcode += _gcodegen.extrude(*b, "brim", obj.config.get_abs_value("support_material_speed"));
|
||||
}
|
||||
this->_brim_done = true;
|
||||
gcodegen.avoid_crossing_perimeters.use_external_mp = false;
|
||||
_gcodegen.avoid_crossing_perimeters.use_external_mp = false;
|
||||
|
||||
// allow a straight travel move to the first object point
|
||||
gcodegen.avoid_crossing_perimeters.disable_once = true;
|
||||
_gcodegen.avoid_crossing_perimeters.disable_once = true;
|
||||
}
|
||||
|
||||
auto copy_idx = 0U;
|
||||
@ -548,10 +569,10 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
||||
|
||||
// when starting a new object, use the external motion planner for the first travel move
|
||||
if (this->_last_obj_copy.first != copy && this->_last_obj_copy.second )
|
||||
gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
||||
_gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
||||
this->_last_obj_copy.first = copy;
|
||||
this->_last_obj_copy.second = true;
|
||||
gcodegen.set_origin(Pointf::new_unscale(copy));
|
||||
_gcodegen.set_origin(Pointf::new_unscale(copy));
|
||||
|
||||
// extrude support material before other things because it might use a lower Z
|
||||
// and also because we avoid travelling on other things when printing it
|
||||
@ -559,17 +580,17 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
||||
const SupportLayer* slayer = dynamic_cast<const SupportLayer*>(layer);
|
||||
ExtrusionEntityCollection paths;
|
||||
if (slayer->support_interface_fills.size() > 0) {
|
||||
gcode += gcodegen.set_extruder(obj.config.support_material_interface_extruder - 1);
|
||||
slayer->support_interface_fills.chained_path_from(gcodegen.last_pos(), &paths, false);
|
||||
gcode += _gcodegen.set_extruder(obj.config.support_material_interface_extruder - 1);
|
||||
slayer->support_interface_fills.chained_path_from(_gcodegen.last_pos(), &paths, false);
|
||||
for (const auto& path : paths) {
|
||||
gcode += gcodegen.extrude(*path, "support material interface", obj.config.get_abs_value("support_material_interface_speed"));
|
||||
gcode += _gcodegen.extrude(*path, "support material interface", obj.config.get_abs_value("support_material_interface_speed"));
|
||||
}
|
||||
}
|
||||
if (slayer->support_fills.size() > 0) {
|
||||
gcode += gcodegen.set_extruder(obj.config.support_material_extruder - 1);
|
||||
slayer->support_fills.chained_path_from(gcodegen.last_pos(), &paths, false);
|
||||
gcode += _gcodegen.set_extruder(obj.config.support_material_extruder - 1);
|
||||
slayer->support_fills.chained_path_from(_gcodegen.last_pos(), &paths, false);
|
||||
for (const auto& path : paths) {
|
||||
gcode += gcodegen.extrude(*path, "support material", obj.config.get_abs_value("support_material_speed"));
|
||||
gcode += _gcodegen.extrude(*path, "support material", obj.config.get_abs_value("support_material_speed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -594,25 +615,25 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
||||
// cache bounding boxes of layer slices
|
||||
std::vector<BoundingBox> layer_slices_bb;
|
||||
std::transform(layer->slices.cbegin(), layer->slices.cend(), std::back_inserter(layer_slices_bb), [] (const ExPolygon& s)-> BoundingBox { return s.bounding_box(); });
|
||||
auto point_inside_surface { [&layer_slices_bb, &layer] (size_t i, Point point) -> bool {
|
||||
const auto& bbox {layer_slices_bb.at(i)};
|
||||
auto point_inside_surface = [&layer_slices_bb, &layer] (size_t i, Point point) -> bool {
|
||||
const BoundingBox& bbox { layer_slices_bb.at(i) };
|
||||
return bbox.contains(point) && layer->slices.at(i).contour.contains(point);
|
||||
}};
|
||||
const auto n_slices {layer->slices.size()};
|
||||
};
|
||||
const size_t n_slices { layer->slices.size() };
|
||||
|
||||
for (auto region_id = 0U; region_id < print.regions.size(); ++region_id) {
|
||||
for (auto region_id = 0U; region_id < _print.regions.size(); ++region_id) {
|
||||
const LayerRegion* layerm;
|
||||
try {
|
||||
layerm = layer->get_region(region_id); // we promise to be good and not give this to anyone who will modify it
|
||||
} catch (std::out_of_range &e) {
|
||||
continue; // if no regions, bail;
|
||||
}
|
||||
auto* region {print.get_region(region_id)};
|
||||
const PrintRegion* region { _print.get_region(region_id) };
|
||||
// process perimeters
|
||||
{
|
||||
auto extruder_id = region->config.perimeter_extruder-1;
|
||||
// Casting away const just to avoid double dereferences
|
||||
for(auto* perimeter_coll : layerm->perimeters.flatten().entities) {
|
||||
for(const auto* perimeter_coll : layerm->perimeters.flatten().entities) {
|
||||
|
||||
if(perimeter_coll->length() == 0) continue; // this shouldn't happen but first_point() would fail
|
||||
|
||||
@ -654,10 +675,10 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
||||
|
||||
// tweak extruder ordering to save toolchanges
|
||||
|
||||
auto last_extruder = gcodegen.writer.extruder()->id;
|
||||
auto last_extruder = _gcodegen.writer.extruder()->id;
|
||||
if (by_extruder.count(last_extruder)) {
|
||||
for(auto &island : by_extruder[last_extruder]) {
|
||||
if (print.config.infill_first()) {
|
||||
if (_print.config.infill_first()) {
|
||||
gcode += this->_extrude_infill(std::get<1>(island.second));
|
||||
gcode += this->_extrude_perimeters(std::get<0>(island.second));
|
||||
} else {
|
||||
@ -668,9 +689,9 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
||||
}
|
||||
for(auto &pair : by_extruder) {
|
||||
if(pair.first == last_extruder)continue;
|
||||
gcode += gcodegen.set_extruder(pair.first);
|
||||
gcode += _gcodegen.set_extruder(pair.first);
|
||||
for(auto &island : pair.second) {
|
||||
if (print.config.infill_first()) {
|
||||
if (_print.config.infill_first()) {
|
||||
gcode += this->_extrude_infill(std::get<1>(island.second));
|
||||
gcode += this->_extrude_perimeters(std::get<0>(island.second));
|
||||
} else {
|
||||
@ -733,16 +754,10 @@ PrintGCode::_extrude_infill(std::map<size_t,ExtrusionEntityCollection> &by_regio
|
||||
void
|
||||
PrintGCode::_print_first_layer_temperature(bool wait)
|
||||
{
|
||||
auto& gcodegen {this->_gcodegen};
|
||||
auto& fh {this->fh};
|
||||
const auto& print {this->_print};
|
||||
const auto& config {this->config};
|
||||
const auto extruders {print.extruders()};
|
||||
|
||||
for (auto& t : extruders) {
|
||||
auto temp { config.first_layer_temperature.get_at(t) };
|
||||
for (auto& t : _print.extruders()) {
|
||||
auto temp = config.first_layer_temperature.get_at(t);
|
||||
if (config.ooze_prevention.value) temp += config.standby_temperature_delta.value;
|
||||
if (temp > 0) fh << gcodegen.writer.set_temperature(temp, wait, t);
|
||||
if (temp > 0) fh << _gcodegen.writer.set_temperature(temp, wait, t);
|
||||
}
|
||||
}
|
||||
|
||||
@ -758,9 +773,9 @@ PrintGCode::_print_config(const ConfigBase& config)
|
||||
|
||||
PrintGCode::PrintGCode(Slic3r::Print& print, std::ostream& _fh) :
|
||||
_print(print),
|
||||
config(print.config),
|
||||
config(_print.config),
|
||||
_gcodegen(Slic3r::GCode()),
|
||||
objects(print.objects),
|
||||
objects(_print.objects),
|
||||
fh(_fh),
|
||||
_cooling_buffer(Slic3r::CoolingBuffer(this->_gcodegen)),
|
||||
_spiral_vase(Slic3r::SpiralVase(this->config))
|
||||
@ -771,16 +786,16 @@ PrintGCode::PrintGCode(Slic3r::Print& print, std::ostream& _fh) :
|
||||
} else {
|
||||
layer_count = std::accumulate(objects.cbegin(), objects.cend(), layer_count, [](const size_t& ret, const PrintObject* obj){ return ret + obj->total_layer_count(); });
|
||||
}
|
||||
_gcodegen.placeholder_parser = &(print.placeholder_parser); // initialize
|
||||
_gcodegen.placeholder_parser = &(_print.placeholder_parser); // initialize
|
||||
_gcodegen.layer_count = layer_count;
|
||||
_gcodegen.enable_cooling_markers = true;
|
||||
_gcodegen.apply_print_config(config);
|
||||
|
||||
if (config.spiral_vase) _spiral_vase.enable = true;
|
||||
|
||||
auto extruders {print.extruders()};
|
||||
const auto extruders = _print.extruders();
|
||||
_gcodegen.set_extruders(extruders.cbegin(), extruders.cend());
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
#endif //SLIC3RXS
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
#ifndef SLIC3RXS
|
||||
#ifndef slic3r_PrintGCode_hpp
|
||||
#define slic3r_PrintGCode_hpp
|
||||
|
||||
@ -77,4 +76,3 @@ private:
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_PrintGCode_hpp
|
||||
#endif // SLIC3RXS
|
||||
|
@ -38,12 +38,6 @@ PrintObject::~PrintObject()
|
||||
{
|
||||
}
|
||||
|
||||
Print*
|
||||
PrintObject::print()
|
||||
{
|
||||
return this->_print;
|
||||
}
|
||||
|
||||
Points
|
||||
PrintObject::copies() const
|
||||
{
|
||||
@ -952,7 +946,6 @@ PrintObject::_slice_region(size_t region_id, std::vector<float> z, bool modifier
|
||||
return layers;
|
||||
}
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
void
|
||||
PrintObject::make_perimeters()
|
||||
{
|
||||
@ -966,28 +959,22 @@ PrintObject::make_perimeters()
|
||||
void
|
||||
PrintObject::slice()
|
||||
{
|
||||
auto* print {this->print()};
|
||||
if (this->state.is_done(posSlice)) return;
|
||||
this->state.set_started(posSlice);
|
||||
if (print->status_cb != nullptr) {
|
||||
print->status_cb(10, "Processing triangulated mesh");
|
||||
if (_print->status_cb != nullptr) {
|
||||
_print->status_cb(10, "Processing triangulated mesh");
|
||||
}
|
||||
|
||||
|
||||
this->_slice();
|
||||
|
||||
// detect slicing errors
|
||||
bool warning_thrown = false;
|
||||
for (size_t i = 0U; i < this->layer_count(); ++i) {
|
||||
auto* layer {this->get_layer(i)};
|
||||
if (!layer->slicing_errors) continue;
|
||||
if (!warning_thrown) {
|
||||
Slic3r::Log::warn("PrintObject") << "The model has overlapping or self-intersecting facets. "
|
||||
<< "I tried to repair it, however you might want to check "
|
||||
<< "the results or repair the input file and retry.\n";
|
||||
warning_thrown = true;
|
||||
}
|
||||
}
|
||||
if (std::any_of(this->layers.cbegin(), this->layers.cend(),
|
||||
[](const Layer* l){ return l->slicing_errors; }))
|
||||
Slic3r::Log::warn("PrintObject") << "The model has overlapping or self-intersecting facets. "
|
||||
<< "I tried to repair it, however you might want to check "
|
||||
<< "the results or repair the input file and retry.\n";
|
||||
|
||||
if (this->layers.size() == 0) {
|
||||
Slic3r::Log::error("PrintObject") << "slice(): " << "No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n";
|
||||
return; // make this throw an exception instead?
|
||||
@ -998,7 +985,6 @@ PrintObject::slice()
|
||||
this->state.set_done(posSlice);
|
||||
}
|
||||
|
||||
#endif // SLIC3RXS
|
||||
void
|
||||
PrintObject::_make_perimeters()
|
||||
{
|
||||
@ -1142,7 +1128,6 @@ PrintObject::_infill()
|
||||
this->state.set_done(posInfill);
|
||||
}
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
void
|
||||
PrintObject::prepare_infill()
|
||||
{
|
||||
@ -1304,8 +1289,6 @@ PrintObject::infill()
|
||||
this->_infill();
|
||||
}
|
||||
|
||||
#endif //SLIC3RXS
|
||||
|
||||
SupportMaterial *
|
||||
PrintObject::_support_material()
|
||||
{
|
||||
@ -1357,12 +1340,10 @@ PrintObject::_support_material_flow(FlowRole role)
|
||||
|
||||
return support_flow;
|
||||
}
|
||||
#ifndef SLIC3RXS
|
||||
|
||||
void
|
||||
PrintObject::generate_support_material()
|
||||
{
|
||||
auto* print { this->_print };
|
||||
const auto& config { this->config };
|
||||
//prereqs
|
||||
this->slice();
|
||||
if (this->state.is_done(posSupportMaterial)) { return; }
|
||||
@ -1379,8 +1360,8 @@ PrintObject::generate_support_material()
|
||||
this->state.set_done(posSupportMaterial);
|
||||
return;
|
||||
}
|
||||
if (print->status_cb != nullptr)
|
||||
print->status_cb(85, "Generating support material");
|
||||
if (_print->status_cb != nullptr)
|
||||
_print->status_cb(85, "Generating support material");
|
||||
|
||||
this->_support_material()->generate(this);
|
||||
|
||||
@ -1388,8 +1369,8 @@ PrintObject::generate_support_material()
|
||||
|
||||
std::stringstream stats {""};
|
||||
|
||||
if (print->status_cb != nullptr)
|
||||
print->status_cb(85, stats.str().c_str());
|
||||
if (_print->status_cb != nullptr)
|
||||
_print->status_cb(85, stats.str().c_str());
|
||||
|
||||
}
|
||||
|
||||
@ -1397,15 +1378,14 @@ PrintObject::generate_support_material()
|
||||
void
|
||||
PrintObject::discover_horizontal_shells()
|
||||
{
|
||||
auto* print {this->print()};
|
||||
for (size_t region_id = 0U; region_id < print->regions.size(); ++region_id) {
|
||||
for (size_t region_id = 0U; region_id < _print->regions.size(); ++region_id) {
|
||||
for (size_t i = 0; i < this->layer_count(); ++i) {
|
||||
auto* layerm {this->get_layer(i)->regions.at(region_id)};
|
||||
const auto& region_config {layerm->region()->config};
|
||||
auto* layerm = this->get_layer(i)->get_region(region_id);
|
||||
const auto& region_config = layerm->region()->config;
|
||||
|
||||
if (region_config.solid_infill_every_layers() > 0 && region_config.fill_density() > 0
|
||||
&& (i % region_config.solid_infill_every_layers()) == 0) {
|
||||
const auto type {region_config.fill_density() == 100 ? stInternalSolid : stInternalBridge };
|
||||
const auto type = region_config.fill_density() == 100 ? stInternalSolid : stInternalBridge;
|
||||
// set the surface type to internal for the types
|
||||
std::for_each(layerm->fill_surfaces.begin(), layerm->fill_surfaces.end(), [type] (Surface& s) { s.surface_type = (s.surface_type == type ? stInternal : s.surface_type); });
|
||||
}
|
||||
@ -1417,7 +1397,7 @@ PrintObject::discover_horizontal_shells()
|
||||
void
|
||||
PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id)
|
||||
{
|
||||
const auto& region_config {layerm->region()->config};
|
||||
const auto& region_config = layerm->region()->config;
|
||||
for (auto& type : { stTop, stBottom, stBottomBridge }) {
|
||||
// find slices of current type for current layer
|
||||
// use slices instead of fill_surfaces because they also include the perimeter area
|
||||
@ -1430,7 +1410,7 @@ PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const siz
|
||||
// too much solid infill inside nearly-vertical slopes.
|
||||
|
||||
Polygons solid;
|
||||
auto tmp {layerm->slices.filter_by_type(type)};
|
||||
auto tmp = layerm->slices.filter_by_type(type);
|
||||
polygons_append(solid, tmp);
|
||||
tmp.clear();
|
||||
tmp = layerm->fill_surfaces.filter_by_type(type);
|
||||
@ -1438,11 +1418,11 @@ PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const siz
|
||||
|
||||
if (solid.size() == 0) continue;
|
||||
|
||||
auto solid_layers { type == stTop ? region_config.top_solid_layers() : region_config.bottom_solid_layers() };
|
||||
auto solid_layers = type == stTop ? region_config.top_solid_layers() : region_config.bottom_solid_layers();
|
||||
|
||||
if (region_config.min_top_bottom_shell_thickness() > 0) {
|
||||
auto current_shell_thick { static_cast<coordf_t>(solid_layers) * this->get_layer(i)->height };
|
||||
const auto& min_shell_thick { region_config.min_top_bottom_shell_thickness() };
|
||||
auto current_shell_thick = static_cast<coordf_t>(solid_layers) * this->get_layer(i)->height;
|
||||
const auto min_shell_thick = region_config.min_top_bottom_shell_thickness();
|
||||
while (std::abs(min_shell_thick - current_shell_thick) > Slic3r::Geometry::epsilon) {
|
||||
solid_layers++;
|
||||
current_shell_thick = static_cast<coordf_t>(solid_layers) * this->get_layer(i)->height;
|
||||
@ -1455,19 +1435,19 @@ PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const siz
|
||||
void
|
||||
PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id, const SurfaceType& type, Polygons& solid, const size_t& solid_layers)
|
||||
{
|
||||
const auto& region_config {layerm->region()->config};
|
||||
const auto& region_config = layerm->region()->config;
|
||||
|
||||
for (int n = (type == stTop ? i-1 : i+1); std::abs(n-int(i)) < solid_layers; (type == stTop ? n-- : n++)) {
|
||||
if (n < 0 || static_cast<size_t>(n) >= this->layer_count()) continue;
|
||||
|
||||
auto* neighbor_layerm { this->get_layer(n)->regions.at(region_id) };
|
||||
LayerRegion* neighbor_layerm { this->get_layer(n)->get_region(region_id) };
|
||||
// make a copy so we can use them even after clearing the original collection
|
||||
auto neighbor_fill_surfaces{ SurfaceCollection(neighbor_layerm->fill_surfaces) };
|
||||
SurfaceCollection neighbor_fill_surfaces{ neighbor_layerm->fill_surfaces };
|
||||
// find intersection between neighbor and current layer's surfaces
|
||||
// intersections have contours and holes
|
||||
Polygons filtered_poly;
|
||||
polygons_append(filtered_poly, neighbor_fill_surfaces.filter_by_type({stInternal, stInternalSolid}));
|
||||
auto new_internal_solid { intersection(solid, filtered_poly , 1 ) };
|
||||
auto new_internal_solid = intersection(solid, filtered_poly , 1 );
|
||||
if (new_internal_solid.size() == 0) {
|
||||
// No internal solid needed on this layer. In order to decide whether to continue
|
||||
// searching on the next neighbor (thus enforcing the configured number of solid
|
||||
@ -1490,8 +1470,8 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz
|
||||
// than a perimeter width, since it's probably just crossing a sloping wall
|
||||
// and it's not wanted in a hollow print even if it would make sense when
|
||||
// obeying the solid shell count option strictly (DWIM!)
|
||||
auto margin { neighbor_layerm->flow(frExternalPerimeter).scaled_width()};
|
||||
auto too_narrow { diff(new_internal_solid, offset2(new_internal_solid, -margin, +margin, CLIPPER_OFFSET_SCALE, ClipperLib::jtMiter, 5), 1)};
|
||||
const auto margin = neighbor_layerm->flow(frExternalPerimeter).scaled_width();
|
||||
const auto too_narrow = diff(new_internal_solid, offset2(new_internal_solid, -margin, +margin, CLIPPER_OFFSET_SCALE, ClipperLib::jtMiter, 5), 1);
|
||||
if (too_narrow.size() > 0)
|
||||
new_internal_solid = solid = diff(new_internal_solid, too_narrow);
|
||||
}
|
||||
@ -1499,16 +1479,16 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz
|
||||
// make sure the new internal solid is wide enough, as it might get collapsed
|
||||
// when spacing is added in Slic3r::Fill
|
||||
{
|
||||
auto margin {3 * layerm->flow(frSolidInfill).scaled_width()};
|
||||
const auto margin = 3 * layerm->flow(frSolidInfill).scaled_width();
|
||||
|
||||
// we use a higher miterLimit here to handle areas with acute angles
|
||||
// in those cases, the default miterLimit would cut the corner and we'd
|
||||
// get a triangle in $too_narrow; if we grow it below then the shell
|
||||
// would have a different shape from the external surface and we'd still
|
||||
// have the same angle, so the next shell would be grown even more and so on.
|
||||
auto too_narrow { diff(new_internal_solid, offset2(new_internal_solid, -margin, +margin, CLIPPER_OFFSET_SCALE, ClipperLib::jtMiter, 5), 1) };
|
||||
const auto too_narrow = diff(new_internal_solid, offset2(new_internal_solid, -margin, +margin, CLIPPER_OFFSET_SCALE, ClipperLib::jtMiter, 5), 1);
|
||||
|
||||
if (too_narrow.size() > 0) {
|
||||
if (!too_narrow.empty()) {
|
||||
// grow the collapsing parts and add the extra area to the neighbor layer
|
||||
// as well as to our original surfaces so that we support this
|
||||
// additional area in the next shell too
|
||||
@ -1518,16 +1498,16 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz
|
||||
for (auto& s : neighbor_fill_surfaces) {
|
||||
if (s.is_internal() && !s.is_bridge()) tmp_internal.emplace_back(Polygon(s.expolygon));
|
||||
}
|
||||
auto grown {intersection(
|
||||
offset(too_narrow, +margin),
|
||||
// Discard bridges as they are grown for anchoring and we cant
|
||||
// remove such anchors. (This may happen when a bridge is being
|
||||
// anchored onto a wall where little space remains after the bridge
|
||||
// is grown, and that little space is an internal solid shell so
|
||||
// it triggers this too_narrow logic.)
|
||||
tmp_internal)
|
||||
};
|
||||
new_internal_solid = solid = diff(new_internal_solid, too_narrow);
|
||||
const auto grown = intersection(
|
||||
offset(too_narrow, +margin),
|
||||
// Discard bridges as they are grown for anchoring and we cant
|
||||
// remove such anchors. (This may happen when a bridge is being
|
||||
// anchored onto a wall where little space remains after the bridge
|
||||
// is grown, and that little space is an internal solid shell so
|
||||
// it triggers this too_narrow logic.)
|
||||
tmp_internal
|
||||
);
|
||||
new_internal_solid = solid = diff(grown, new_internal_solid);
|
||||
}
|
||||
}
|
||||
// internal-solid are the union of the existing internal-solid surfaces
|
||||
@ -1535,11 +1515,11 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz
|
||||
|
||||
Polygons tmp_internal { to_polygons(neighbor_fill_surfaces.filter_by_type(stInternalSolid)) };
|
||||
polygons_append(tmp_internal, neighbor_fill_surfaces.surfaces);
|
||||
auto internal_solid {union_ex(tmp_internal)};
|
||||
const auto internal_solid = union_ex(tmp_internal);
|
||||
|
||||
// subtract intersections from layer surfaces to get resulting internal surfaces
|
||||
tmp_internal = to_polygons(neighbor_fill_surfaces.filter_by_type(stInternal));
|
||||
auto internal { diff_ex(tmp_internal, to_polygons(internal_solid), 1) };
|
||||
const auto internal = diff_ex(tmp_internal, to_polygons(internal_solid), 1);
|
||||
|
||||
// assign resulting internal surfaces to layer
|
||||
neighbor_fill_surfaces.clear();
|
||||
@ -1563,7 +1543,7 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz
|
||||
both_solids.insert(both_solids.end(), internal_solid.begin(), internal_solid.end());
|
||||
both_solids.insert(both_solids.end(), internal.begin(), internal.end());
|
||||
|
||||
auto solid_surfaces { diff_ex(pp, to_polygons(both_solids), 1) };
|
||||
const auto solid_surfaces = diff_ex(pp, to_polygons(both_solids), 1);
|
||||
for (auto exp : solid_surfaces)
|
||||
neighbor_fill_surfaces.surfaces.emplace_back(Surface(s.surface_type, exp));
|
||||
}
|
||||
@ -1645,5 +1625,4 @@ PrintObject::clip_fill_surfaces()
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SLIC3RXS
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ class SimplePrint {
|
||||
bool center{true};
|
||||
std::function<void(int, const std::string&)> status_cb {nullptr};
|
||||
|
||||
bool apply_config(config_ptr config) { return this->_print.apply_config(config); }
|
||||
bool apply_config(DynamicPrintConfig config) { return this->_print.apply_config(config); }
|
||||
double total_used_filament() const { return this->_print.total_used_filament; }
|
||||
double total_extruded_volume() const { return this->_print.total_extruded_volume; }
|
||||
|
@ -108,7 +108,6 @@ void TriangleMesh::clone(const TriangleMesh& other) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
TriangleMesh::TriangleMesh(TriangleMesh&& other) {
|
||||
this->repaired = std::move(other.repaired);
|
||||
this->stl = std::move(other.stl);
|
||||
@ -123,7 +122,6 @@ TriangleMesh& TriangleMesh::operator= (TriangleMesh&& other)
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
TriangleMesh::swap(TriangleMesh &other)
|
||||
@ -399,8 +397,6 @@ void TriangleMesh::rotate(double angle, const Point& center)
|
||||
this->translate(+center.x, +center.y, 0);
|
||||
}
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
|
||||
Pointf3s TriangleMesh::vertices()
|
||||
{
|
||||
Pointf3s tmp {};
|
||||
@ -408,7 +404,7 @@ Pointf3s TriangleMesh::vertices()
|
||||
if (this->stl.v_shared == nullptr)
|
||||
stl_generate_shared_vertices(&stl); // build the list of vertices
|
||||
for (auto i = 0; i < this->stl.stats.shared_vertices; i++) {
|
||||
const auto& v {this->stl.v_shared[i]};
|
||||
const stl_vertex& v { this->stl.v_shared[i] };
|
||||
tmp.emplace_back(Pointf3(v.x, v.y, v.z));
|
||||
}
|
||||
} else {
|
||||
@ -424,7 +420,7 @@ Point3s TriangleMesh::facets()
|
||||
if (this->stl.v_shared == nullptr)
|
||||
stl_generate_shared_vertices(&stl); // build the list of vertices
|
||||
for (auto i = 0; i < stl.stats.number_of_facets; i++) {
|
||||
const auto& v {stl.v_indices[i]};
|
||||
const v_indices_struct& v { stl.v_indices[i] };
|
||||
tmp.emplace_back(Point3(v.vertex[0], v.vertex[1], v.vertex[2]));
|
||||
}
|
||||
} else {
|
||||
@ -438,7 +434,7 @@ Pointf3s TriangleMesh::normals() const
|
||||
Pointf3s tmp {};
|
||||
if (this->repaired) {
|
||||
for (auto i = 0; i < stl.stats.number_of_facets; i++) {
|
||||
const auto& n {stl.facet_start[i].normal};
|
||||
const auto& n = stl.facet_start[i].normal;
|
||||
tmp.emplace_back(Pointf3(n.x, n.y, n.z));
|
||||
}
|
||||
} else {
|
||||
@ -449,7 +445,7 @@ Pointf3s TriangleMesh::normals() const
|
||||
|
||||
Pointf3 TriangleMesh::size() const
|
||||
{
|
||||
const auto& sz {stl.stats.size};
|
||||
const auto& sz = stl.stats.size;
|
||||
return Pointf3(sz.x, sz.y, sz.z);
|
||||
}
|
||||
|
||||
@ -513,10 +509,6 @@ void TriangleMesh::cut(Axis axis, double z, TriangleMesh* upper, TriangleMesh* l
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // SLIC3RXS
|
||||
|
||||
TriangleMeshPtrs
|
||||
TriangleMesh::split() const
|
||||
{
|
||||
|
@ -47,11 +47,10 @@ class TriangleMesh
|
||||
/// copy assignment
|
||||
TriangleMesh& operator= (const TriangleMesh& other);
|
||||
|
||||
#ifndef SLIC3RXS
|
||||
/// Move assignment
|
||||
TriangleMesh& operator= (TriangleMesh&& other);
|
||||
TriangleMesh(TriangleMesh&& other);
|
||||
#endif
|
||||
|
||||
void swap(TriangleMesh &other);
|
||||
~TriangleMesh();
|
||||
void ReadSTLFile(const std::string &input_file);
|
||||
@ -99,9 +98,7 @@ class TriangleMesh
|
||||
void extrude_tin(float offset);
|
||||
void require_shared_vertices();
|
||||
void reverse_normals();
|
||||
|
||||
#ifndef SLIC3RXS // Don't build these functions when also building the Perl interface.
|
||||
|
||||
|
||||
/// Return a copy of the vertex array defining this mesh.
|
||||
Pointf3s vertices();
|
||||
|
||||
@ -127,8 +124,6 @@ class TriangleMesh
|
||||
|
||||
/// Perform a cut of the mesh and put the output in upper and lower
|
||||
void cut(Axis axis, double z, TriangleMesh* upper, TriangleMesh* lower);
|
||||
|
||||
#endif // SLIC3RXS
|
||||
|
||||
/// Generate a mesh representing a cube with dimensions (x, y, z), with one corner at (0,0,0).
|
||||
static TriangleMesh make_cube(double x, double y, double z);
|
||||
|
@ -79,8 +79,8 @@ ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key) {
|
||||
ConfigOption* opt = THIS->option(opt_key);
|
||||
if (opt == NULL) return &PL_sv_undef;
|
||||
|
||||
const ConfigOptionDef* def = THIS->def->get(opt_key);
|
||||
return ConfigOption_to_SV(*opt, *def);
|
||||
const ConfigOptionDef& def = THIS->def->get(opt_key);
|
||||
return ConfigOption_to_SV(*opt, def);
|
||||
}
|
||||
|
||||
SV*
|
||||
@ -153,22 +153,22 @@ ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t
|
||||
ConfigOption* opt = THIS->option(opt_key);
|
||||
if (opt == NULL) return &PL_sv_undef;
|
||||
|
||||
const ConfigOptionDef* def = THIS->def->get(opt_key);
|
||||
if (def->type == coFloats) {
|
||||
const ConfigOptionDef& def = THIS->def->get(opt_key);
|
||||
if (def.type == coFloats) {
|
||||
ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt);
|
||||
return newSVnv(optv->get_at(i));
|
||||
} else if (def->type == coInts) {
|
||||
} else if (def.type == coInts) {
|
||||
ConfigOptionInts* optv = dynamic_cast<ConfigOptionInts*>(opt);
|
||||
return newSViv(optv->get_at(i));
|
||||
} else if (def->type == coStrings) {
|
||||
} else if (def.type == coStrings) {
|
||||
ConfigOptionStrings* optv = dynamic_cast<ConfigOptionStrings*>(opt);
|
||||
// we don't serialize() because that would escape newlines
|
||||
std::string val = optv->get_at(i);
|
||||
return newSVpvn_utf8(val.c_str(), val.length(), true);
|
||||
} else if (def->type == coPoints) {
|
||||
} else if (def.type == coPoints) {
|
||||
ConfigOptionPoints* optv = dynamic_cast<ConfigOptionPoints*>(opt);
|
||||
return perl_to_SV_clone_ref(optv->get_at(i));
|
||||
} else if (def->type == coBools) {
|
||||
} else if (def.type == coBools) {
|
||||
ConfigOptionBools* optv = dynamic_cast<ConfigOptionBools*>(opt);
|
||||
return newSViv(optv->get_at(i) ? 1 : 0);
|
||||
} else {
|
||||
@ -181,12 +181,12 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value)
|
||||
ConfigOption* opt = THIS->option(opt_key, true);
|
||||
if (opt == NULL) CONFESS("Trying to set non-existing option");
|
||||
|
||||
const ConfigOptionDef* def = THIS->def->get(opt_key);
|
||||
if (def->type == coFloat) {
|
||||
const ConfigOptionDef& def = THIS->def->get(opt_key);
|
||||
if (def.type == coFloat) {
|
||||
if (!looks_like_number(value)) return false;
|
||||
ConfigOptionFloat* optv = dynamic_cast<ConfigOptionFloat*>(opt);
|
||||
optv->value = SvNV(value);
|
||||
} else if (def->type == coFloats) {
|
||||
} else if (def.type == coFloats) {
|
||||
ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt);
|
||||
std::vector<double> values;
|
||||
AV* av = (AV*)SvRV(value);
|
||||
@ -197,11 +197,11 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value)
|
||||
values.push_back(SvNV(*elem));
|
||||
}
|
||||
optv->values = values;
|
||||
} else if (def->type == coInt) {
|
||||
} else if (def.type == coInt) {
|
||||
if (!looks_like_number(value)) return false;
|
||||
ConfigOptionInt* optv = dynamic_cast<ConfigOptionInt*>(opt);
|
||||
optv->value = SvIV(value);
|
||||
} else if (def->type == coInts) {
|
||||
} else if (def.type == coInts) {
|
||||
ConfigOptionInts* optv = dynamic_cast<ConfigOptionInts*>(opt);
|
||||
std::vector<int> values;
|
||||
AV* av = (AV*)SvRV(value);
|
||||
@ -212,10 +212,10 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value)
|
||||
values.push_back(SvIV(*elem));
|
||||
}
|
||||
optv->values = values;
|
||||
} else if (def->type == coString) {
|
||||
} else if (def.type == coString) {
|
||||
ConfigOptionString* optv = dynamic_cast<ConfigOptionString*>(opt);
|
||||
optv->value = std::string(SvPV_nolen(value), SvCUR(value));
|
||||
} else if (def->type == coStrings) {
|
||||
} else if (def.type == coStrings) {
|
||||
ConfigOptionStrings* optv = dynamic_cast<ConfigOptionStrings*>(opt);
|
||||
optv->values.clear();
|
||||
AV* av = (AV*)SvRV(value);
|
||||
@ -225,13 +225,13 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value)
|
||||
if (elem == NULL) return false;
|
||||
optv->values.push_back(std::string(SvPV_nolen(*elem), SvCUR(*elem)));
|
||||
}
|
||||
} else if (def->type == coPoint) {
|
||||
} else if (def.type == coPoint) {
|
||||
ConfigOptionPoint* optv = dynamic_cast<ConfigOptionPoint*>(opt);
|
||||
return from_SV_check(value, &optv->value);
|
||||
} else if(def->type == coPoint3){
|
||||
} else if(def.type == coPoint3){
|
||||
ConfigOptionPoint3* optv = dynamic_cast<ConfigOptionPoint3*>(opt);
|
||||
return from_SV_check(value, &optv->value);
|
||||
} else if (def->type == coPoints) {
|
||||
} else if (def.type == coPoints) {
|
||||
ConfigOptionPoints* optv = dynamic_cast<ConfigOptionPoints*>(opt);
|
||||
std::vector<Pointf> values;
|
||||
AV* av = (AV*)SvRV(value);
|
||||
@ -243,10 +243,10 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value)
|
||||
values.push_back(point);
|
||||
}
|
||||
optv->values = values;
|
||||
} else if (def->type == coBool) {
|
||||
} else if (def.type == coBool) {
|
||||
ConfigOptionBool* optv = dynamic_cast<ConfigOptionBool*>(opt);
|
||||
optv->value = SvTRUE(value);
|
||||
} else if (def->type == coBools) {
|
||||
} else if (def.type == coBools) {
|
||||
ConfigOptionBools* optv = dynamic_cast<ConfigOptionBools*>(opt);
|
||||
optv->values.clear();
|
||||
AV* av = (AV*)SvRV(value);
|
||||
@ -287,9 +287,9 @@ ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV*
|
||||
|
||||
bool
|
||||
StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value) {
|
||||
const ConfigOptionDef* optdef = THIS->def->get(opt_key);
|
||||
if (!optdef->shortcut.empty()) {
|
||||
for (std::vector<t_config_option_key>::const_iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it) {
|
||||
const ConfigOptionDef& optdef = THIS->def->get(opt_key);
|
||||
if (!optdef.shortcut.empty()) {
|
||||
for (std::vector<t_config_option_key>::const_iterator it = optdef.shortcut.begin(); it != optdef.shortcut.end(); ++it) {
|
||||
if (!StaticConfig__set(THIS, *it, value)) return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -269,7 +269,13 @@ _constant()
|
||||
bool has_infinite_skirt();
|
||||
bool has_skirt();
|
||||
std::string _validate()
|
||||
%code%{ RETVAL = THIS->validate(); %};
|
||||
%code%{
|
||||
try {
|
||||
THIS->validate();
|
||||
} catch (std::exception &e) {
|
||||
RETVAL = e.what();
|
||||
}
|
||||
%};
|
||||
Clone<BoundingBox> bounding_box();
|
||||
Clone<BoundingBox> total_bounding_box();
|
||||
double skirt_first_layer_height();
|
||||
|
Loading…
x
Reference in New Issue
Block a user