mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-12-04 16:21:17 -07:00
Merge branch 'merge-upstream'
Signed-off-by: SoftFever <softfeverever@gmail.com> # Conflicts: # src/libslic3r/Preset.cpp # src/libslic3r/PrintConfig.cpp # src/libslic3r/PrintConfig.hpp
This commit is contained in:
commit
59bab91da9
579 changed files with 23269 additions and 11097 deletions
|
|
@ -80,20 +80,196 @@ using ItemGroup = std::vector<std::reference_wrapper<Item>>;
|
|||
const double BIG_ITEM_TRESHOLD = 0.02;
|
||||
#define VITRIFY_TEMP_DIFF_THRSH 15 // bed temp can be higher than vitrify temp, but not higher than this thresh
|
||||
|
||||
void update_arrange_params(ArrangeParams& params, const DynamicPrintConfig& print_cfg, const ArrangePolygons& selected)
|
||||
{
|
||||
double skirt_distance = get_real_skirt_dist(print_cfg);
|
||||
// Note: skirt_distance is now defined between outermost brim and skirt, not the object and skirt.
|
||||
// So we can't do max but do adding instead.
|
||||
params.brim_skirt_distance = skirt_distance;
|
||||
params.bed_shrink_x = params.brim_skirt_distance;
|
||||
params.bed_shrink_y = params.brim_skirt_distance;
|
||||
// for sequential print, we need to inflate the bed because cleareance_radius is so large
|
||||
if (params.is_seq_print) {
|
||||
float shift_dist = params.cleareance_radius / 2 - 5;
|
||||
params.bed_shrink_x -= shift_dist;
|
||||
params.bed_shrink_y -= shift_dist;
|
||||
}
|
||||
}
|
||||
|
||||
void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, ArrangeParams& params) {
|
||||
// do not inflate brim_width. Objects are allowed to have overlapped brim.
|
||||
Points bedpts = get_shrink_bedpts(print_cfg, params);
|
||||
BoundingBox bedbb = Polygon(bedpts).bounding_box();
|
||||
// set obj distance for auto seq_print
|
||||
if (params.min_obj_distance == 0 && params.is_seq_print)
|
||||
params.min_obj_distance = scaled(params.cleareance_radius + 0.001);
|
||||
double brim_max = 0;
|
||||
bool plate_has_tree_support = false;
|
||||
std::for_each(selected.begin(), selected.end(), [&](ArrangePolygon& ap) {
|
||||
brim_max = std::max(brim_max, ap.brim_width);
|
||||
if (ap.has_tree_support) plate_has_tree_support = true; });
|
||||
std::for_each(selected.begin(), selected.end(), [&](ArrangePolygon& ap) {
|
||||
// 1. if user input a distance, use it
|
||||
// 2. if there is an object with tree support, all objects use the max tree branch radius (brim_max=branch diameter)
|
||||
// 3. otherwise, use each object's own brim width
|
||||
ap.inflation = params.min_obj_distance != 0 ? params.min_obj_distance / 2 :
|
||||
plate_has_tree_support ? scaled(brim_max / 2) : scaled(ap.brim_width);
|
||||
BoundingBox apbb = ap.poly.contour.bounding_box();
|
||||
auto diffx = bedbb.size().x() - apbb.size().x() - 5;
|
||||
auto diffy = bedbb.size().y() - apbb.size().y() - 5;
|
||||
if (diffx > 0 && diffy > 0) {
|
||||
auto min_diff = std::min(diffx, diffy);
|
||||
ap.inflation = std::min(min_diff / 2, ap.inflation);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void update_unselected_items_inflation(ArrangePolygons& unselected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params)
|
||||
{
|
||||
if (params.is_seq_print) {
|
||||
float shift_dist = params.cleareance_radius / 2 - 5;
|
||||
// dont forget to move the excluded region
|
||||
for (auto& region : unselected) {
|
||||
if (region.is_virt_object) region.poly.translate(-scaled(shift_dist), -scaled(shift_dist));
|
||||
}
|
||||
}
|
||||
// For occulusion regions, inflation should be larger to prevent genrating brim on them.
|
||||
// However, extrusion cali regions are exceptional, since we can allow brim overlaps them.
|
||||
// 屏蔽区域只需要膨胀brim宽度,防止brim长过去;挤出标定区域不需要膨胀,brim可以长过去。
|
||||
// 以前我们认为还需要膨胀clearance_radius/2,这其实是不需要的,因为这些区域并不会真的摆放物体,
|
||||
// 其他物体的膨胀轮廓是可以跟它们重叠的。
|
||||
double scaled_exclusion_gap = scale_(1);
|
||||
std::for_each(unselected.begin(), unselected.end(),
|
||||
[&](auto& ap) { ap.inflation = !ap.is_virt_object ? (params.min_obj_distance == 0 ? scaled(ap.brim_width) : params.min_obj_distance / 2)
|
||||
: (ap.is_extrusion_cali_object ? 0 : scaled_exclusion_gap); });
|
||||
}
|
||||
|
||||
void update_selected_items_axis_align(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params)
|
||||
{
|
||||
// now only need to consider "Align to x axis"
|
||||
if (!params.align_to_y_axis)
|
||||
return;
|
||||
|
||||
for (ArrangePolygon& ap : selected) {
|
||||
bool validResult = false;
|
||||
double angle = 0.0;
|
||||
{
|
||||
const auto& pts = ap.transformed_poly().contour;
|
||||
int lpt = pts.size();
|
||||
double a00 = 0, a10 = 0, a01 = 0, a20 = 0, a11 = 0, a02 = 0, a30 = 0, a21 = 0, a12 = 0, a03 = 0;
|
||||
double xi, yi, xi2, yi2, xi_1, yi_1, xi_12, yi_12, dxy, xii_1, yii_1;
|
||||
xi_1 = pts.back().x();
|
||||
yi_1 = pts.back().y();
|
||||
|
||||
xi_12 = xi_1 * xi_1;
|
||||
yi_12 = yi_1 * yi_1;
|
||||
|
||||
for (int i = 0; i < lpt; i++) {
|
||||
xi = pts[i].x();
|
||||
yi = pts[i].y();
|
||||
|
||||
xi2 = xi * xi;
|
||||
yi2 = yi * yi;
|
||||
dxy = xi_1 * yi - xi * yi_1;
|
||||
xii_1 = xi_1 + xi;
|
||||
yii_1 = yi_1 + yi;
|
||||
|
||||
a00 += dxy;
|
||||
a10 += dxy * xii_1;
|
||||
a01 += dxy * yii_1;
|
||||
a20 += dxy * (xi_1 * xii_1 + xi2);
|
||||
a11 += dxy * (xi_1 * (yii_1 + yi_1) + xi * (yii_1 + yi));
|
||||
a02 += dxy * (yi_1 * yii_1 + yi2);
|
||||
a30 += dxy * xii_1 * (xi_12 + xi2);
|
||||
a03 += dxy * yii_1 * (yi_12 + yi2);
|
||||
a21 += dxy * (xi_12 * (3 * yi_1 + yi) + 2 * xi * xi_1 * yii_1 + xi2 * (yi_1 + 3 * yi));
|
||||
a12 += dxy * (yi_12 * (3 * xi_1 + xi) + 2 * yi * yi_1 * xii_1 + yi2 * (xi_1 + 3 * xi));
|
||||
xi_1 = xi;
|
||||
yi_1 = yi;
|
||||
xi_12 = xi2;
|
||||
yi_12 = yi2;
|
||||
}
|
||||
|
||||
if (std::abs(a00) > EPSILON) {
|
||||
double db1_2, db1_6, db1_12, db1_24, db1_20, db1_60;
|
||||
double m00, m10, m01, m20, m11, m02, m30, m21, m12, m03;
|
||||
if (a00 > 0) {
|
||||
db1_2 = 0.5;
|
||||
db1_6 = 0.16666666666666666666666666666667;
|
||||
db1_12 = 0.083333333333333333333333333333333;
|
||||
db1_24 = 0.041666666666666666666666666666667;
|
||||
db1_20 = 0.05;
|
||||
db1_60 = 0.016666666666666666666666666666667;
|
||||
}
|
||||
else {
|
||||
db1_2 = -0.5;
|
||||
db1_6 = -0.16666666666666666666666666666667;
|
||||
db1_12 = -0.083333333333333333333333333333333;
|
||||
db1_24 = -0.041666666666666666666666666666667;
|
||||
db1_20 = -0.05;
|
||||
db1_60 = -0.016666666666666666666666666666667;
|
||||
}
|
||||
m00 = a00 * db1_2;
|
||||
m10 = a10 * db1_6;
|
||||
m01 = a01 * db1_6;
|
||||
m20 = a20 * db1_12;
|
||||
m11 = a11 * db1_24;
|
||||
m02 = a02 * db1_12;
|
||||
m30 = a30 * db1_20;
|
||||
m21 = a21 * db1_60;
|
||||
m12 = a12 * db1_60;
|
||||
m03 = a03 * db1_20;
|
||||
|
||||
double cx = m10 / m00;
|
||||
double cy = m01 / m00;
|
||||
|
||||
double a = m20 / m00 - cx * cx;
|
||||
double b = m11 / m00 - cx * cy;
|
||||
double c = m02 / m00 - cy * cy;
|
||||
|
||||
//if a and c are close, there is no dominant axis, then do not rotate
|
||||
if (std::abs(a) < 1.5*std::abs(c) && std::abs(c) < 1.5*std::abs(a)) {
|
||||
validResult = false;
|
||||
}
|
||||
else {
|
||||
angle = std::atan2(2 * b, (a - c)) / 2;
|
||||
validResult = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (validResult) { ap.rotation += (PI / 2 - angle); }
|
||||
}
|
||||
}
|
||||
|
||||
//it will bed accurate after call update_params
|
||||
Points get_shrink_bedpts(const DynamicPrintConfig* print_cfg, const ArrangeParams& params)
|
||||
{
|
||||
Points bedpts = get_bed_shape(*print_cfg);
|
||||
// shrink bed by moving to center by dist
|
||||
auto shrinkFun = [](Points& bedpts, double dist, int direction) {
|
||||
#define SGN(x) ((x) >= 0 ? 1 : -1)
|
||||
Point center = Polygon(bedpts).bounding_box().center();
|
||||
for (auto& pt : bedpts) pt[direction] += dist * SGN(center[direction] - pt[direction]);
|
||||
};
|
||||
shrinkFun(bedpts, scaled(params.bed_shrink_x), 0);
|
||||
shrinkFun(bedpts, scaled(params.bed_shrink_y), 1);
|
||||
return bedpts;
|
||||
}
|
||||
|
||||
// Fill in the placer algorithm configuration with values carefully chosen for
|
||||
// Slic3r.
|
||||
template<class PConf>
|
||||
void fill_config(PConf& pcfg, const ArrangeParams ¶ms) {
|
||||
|
||||
if (params.is_seq_print) {
|
||||
// Start placing the items from the center of the print bed
|
||||
pcfg.starting_point = PConf::Alignment::BOTTOM_LEFT;
|
||||
}
|
||||
else {
|
||||
// Start placing the items from the center of the print bed
|
||||
pcfg.starting_point = PConf::Alignment::TOP_RIGHT;
|
||||
}
|
||||
|
||||
|
||||
if (params.is_seq_print) {
|
||||
// Start placing the items from the center of the print bed
|
||||
pcfg.starting_point = PConf::Alignment::BOTTOM_LEFT;
|
||||
}
|
||||
else {
|
||||
// Start placing the items from the center of the print bed
|
||||
pcfg.starting_point = PConf::Alignment::TOP_RIGHT;
|
||||
}
|
||||
|
||||
if (params.do_final_align) {
|
||||
// Align the arranged pile into the center of the bin
|
||||
pcfg.alignment = PConf::Alignment::CENTER;
|
||||
|
|
@ -495,6 +671,14 @@ public:
|
|||
m_norm = std::sqrt(m_bin_area);
|
||||
fill_config(m_pconf, params);
|
||||
this->params = params;
|
||||
|
||||
// if best object center is not bed center, specify starting point here
|
||||
if (std::abs(this->params.align_center.x() - 0.5) > 0.001 || std::abs(this->params.align_center.y() - 0.5) > 0.001) {
|
||||
auto binbb = sl::boundingBox(m_bin);
|
||||
m_pconf.best_object_pos = binbb.minCorner() + Point{ binbb.width() * this->params.align_center.x(), binbb.height() * this->params.align_center.y() };
|
||||
m_pconf.alignment = PConfig::Alignment::USER_DEFINED;
|
||||
}
|
||||
|
||||
for (auto& region : m_pconf.m_excluded_regions) {
|
||||
Box bb = region.boundingBox();
|
||||
m_excluded_and_extruCali_regions.emplace_back(bb);
|
||||
|
|
@ -551,6 +735,7 @@ public:
|
|||
for (Item itm : items) {
|
||||
if (itm.is_wipe_tower) {
|
||||
starting_point = itm.boundingBox().center();
|
||||
BOOST_LOG_TRIVIAL(debug) << "arrange we have wipe tower, change starting point to: " << starting_point;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -575,15 +760,13 @@ public:
|
|||
if (on_packed)
|
||||
on_packed(ap);
|
||||
BOOST_LOG_TRIVIAL(debug) << "arrange " + last_packed.name + " succeed!"
|
||||
<< ", plate id=" << ap.bed_idx;
|
||||
<< ", plate id=" << ap.bed_idx << ", pos=" << last_packed.translation();
|
||||
}
|
||||
});
|
||||
|
||||
if (progressind) {
|
||||
m_pck.unfitIndicator([this, progressind](std::string name) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "arrange not fit: " + name;
|
||||
m_pck.unfitIndicator([this](std::string name) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "arrange progress: " + name;
|
||||
});
|
||||
}
|
||||
|
||||
if (stopcond) m_pck.stopCondition(stopcond);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define ARRANGE_HPP
|
||||
|
||||
#include "ExPolygon.hpp"
|
||||
|
||||
#include "PrintConfig.hpp"
|
||||
namespace Slic3r {
|
||||
|
||||
class BoundingBox;
|
||||
|
|
@ -53,7 +53,8 @@ struct ArrangePolygon {
|
|||
int locked_plate{ -1 };
|
||||
bool is_virt_object{ false };
|
||||
bool is_extrusion_cali_object{ false };
|
||||
bool is_wipe_tower{false};
|
||||
bool is_wipe_tower{ false };
|
||||
bool has_tree_support{false};
|
||||
//BBS: add row/col for sudoku-style layout
|
||||
int row{0};
|
||||
int col{0};
|
||||
|
|
@ -120,6 +121,7 @@ struct ArrangeParams {
|
|||
bool allow_multi_materials_on_same_plate = true;
|
||||
bool avoid_extrusion_cali_region = true;
|
||||
bool is_seq_print = false;
|
||||
bool align_to_y_axis = false;
|
||||
float bed_shrink_x = 0;
|
||||
float bed_shrink_y = 0;
|
||||
float brim_skirt_distance = 0;
|
||||
|
|
@ -127,6 +129,7 @@ struct ArrangeParams {
|
|||
float clearance_height_to_lid = 0;
|
||||
float cleareance_radius = 0;
|
||||
float printable_height = 256.0;
|
||||
Vec2d align_center{ 0.5,0.5 };
|
||||
|
||||
ArrangePolygons excluded_regions; // regions cant't be used
|
||||
ArrangePolygons nonprefered_regions; // regions can be used but not prefered
|
||||
|
|
@ -144,8 +147,39 @@ struct ArrangeParams {
|
|||
|
||||
ArrangeParams() = default;
|
||||
explicit ArrangeParams(coord_t md) : min_obj_distance(md) {}
|
||||
// to json format
|
||||
std::string to_json() const{
|
||||
std::string ret = "{";
|
||||
ret += "\"min_obj_distance\":" + std::to_string(min_obj_distance) + ",";
|
||||
ret += "\"accuracy\":" + std::to_string(accuracy) + ",";
|
||||
ret += "\"parallel\":" + std::to_string(parallel) + ",";
|
||||
ret += "\"allow_rotations\":" + std::to_string(allow_rotations) + ",";
|
||||
ret += "\"do_final_align\":" + std::to_string(do_final_align) + ",";
|
||||
ret += "\"allow_multi_materials_on_same_plate\":" + std::to_string(allow_multi_materials_on_same_plate) + ",";
|
||||
ret += "\"avoid_extrusion_cali_region\":" + std::to_string(avoid_extrusion_cali_region) + ",";
|
||||
ret += "\"is_seq_print\":" + std::to_string(is_seq_print) + ",";
|
||||
ret += "\"bed_shrink_x\":" + std::to_string(bed_shrink_x) + ",";
|
||||
ret += "\"bed_shrink_y\":" + std::to_string(bed_shrink_y) + ",";
|
||||
ret += "\"brim_skirt_distance\":" + std::to_string(brim_skirt_distance) + ",";
|
||||
ret += "\"clearance_height_to_rod\":" + std::to_string(clearance_height_to_rod) + ",";
|
||||
ret += "\"clearance_height_to_lid\":" + std::to_string(clearance_height_to_lid) + ",";
|
||||
ret += "\"cleareance_radius\":" + std::to_string(cleareance_radius) + ",";
|
||||
ret += "\"printable_height\":" + std::to_string(printable_height) + ",";
|
||||
return ret;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void update_arrange_params(ArrangeParams& params, const DynamicPrintConfig& print_cfg, const ArrangePolygons& selected);
|
||||
|
||||
void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, ArrangeParams& params);
|
||||
|
||||
void update_unselected_items_inflation(ArrangePolygons& unselected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params);
|
||||
|
||||
void update_selected_items_axis_align(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params);
|
||||
|
||||
Points get_shrink_bedpts(const DynamicPrintConfig* print_cfg, const ArrangeParams& params);
|
||||
|
||||
/**
|
||||
* \brief Arranges the input polygons.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -416,6 +416,8 @@ set(lisbslic3r_sources
|
|||
if (APPLE)
|
||||
list(APPEND lisbslic3r_sources
|
||||
MacUtils.mm
|
||||
Format/ModelIO.hpp
|
||||
Format/ModelIO.mm
|
||||
)
|
||||
endif ()
|
||||
|
||||
|
|
@ -532,6 +534,12 @@ if(NOT WIN32)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
find_library(FOUNDATION Foundation REQUIRED)
|
||||
find_library(MODELIO ModelIO REQUIRED)
|
||||
target_link_libraries(libslic3r ${FOUNDATION} ${MODELIO})
|
||||
endif ()
|
||||
|
||||
if (TARGET OpenVDB::openvdb)
|
||||
target_link_libraries(libslic3r OpenVDB::openvdb)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -786,6 +786,7 @@ int ConfigBase::load_from_json(const std::string &file, ConfigSubstitutionContex
|
|||
try {
|
||||
boost::nowide::ifstream ifs(file);
|
||||
ifs >> j;
|
||||
ifs.close();
|
||||
|
||||
const ConfigDef* config_def = this->def();
|
||||
if (config_def == nullptr) {
|
||||
|
|
|
|||
|
|
@ -534,23 +534,26 @@ public:
|
|||
}
|
||||
return false;
|
||||
}
|
||||
size_t i = 0;
|
||||
|
||||
size_t cnt = std::min(this->size(), rhs_vec->size());
|
||||
bool modified = false;
|
||||
for (; i < cnt; ++ i)
|
||||
if (! rhs_vec->is_nil(i) && this->values[i] != rhs_vec->values[i]) {
|
||||
this->values[i] = rhs_vec->values[i];
|
||||
modified = true;
|
||||
}
|
||||
for (; i < rhs_vec->size(); ++ i)
|
||||
if (! rhs_vec->is_nil(i)) {
|
||||
if (this->values.empty())
|
||||
this->values.resize(i + 1);
|
||||
else
|
||||
this->values.resize(i + 1, this->values.front());
|
||||
this->values[i] = rhs_vec->values[i];
|
||||
modified = true;
|
||||
}
|
||||
if (cnt < 1)
|
||||
return false;
|
||||
|
||||
if (this->values.empty())
|
||||
this->values.resize(rhs_vec->size());
|
||||
else
|
||||
this->values.resize(rhs_vec->size(), this->values.front());
|
||||
|
||||
bool modified = false;
|
||||
auto default_value = this->values[0];
|
||||
for (size_t i = 0; i < rhs_vec->size(); ++i) {
|
||||
if (!rhs_vec->is_nil(i)) {
|
||||
this->values[i] = rhs_vec->values[i];
|
||||
modified = true;
|
||||
} else {
|
||||
this->values[i] = default_value;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
|
@ -43,6 +44,24 @@ struct Item
|
|||
std::string extra; // this field is used for the extra data like :
|
||||
// - G-code text for the Type::Custom
|
||||
// - message text for the Type::PausePrint
|
||||
void from_json(const nlohmann::json& j) {
|
||||
std::string type_str;
|
||||
j.at("type").get_to(type_str);
|
||||
std::map<std::string,Type> str2type = { {"ColorChange", ColorChange },
|
||||
{"PausePrint",PausePrint},
|
||||
{"ToolChange",ToolChange},
|
||||
{"Template",Template},
|
||||
{"Custom",Custom},
|
||||
{"Unknown",Unknown} };
|
||||
type = Unknown;
|
||||
if (str2type.find(type_str) != str2type.end())
|
||||
type = str2type[type_str];
|
||||
j.at("print_z").get_to(print_z);
|
||||
j.at("color").get_to(color);
|
||||
j.at("extruder").get_to(extruder);
|
||||
if(j.contains("extra"))
|
||||
j.at("extra").get_to(extra);
|
||||
}
|
||||
};
|
||||
|
||||
enum Mode
|
||||
|
|
@ -71,6 +90,24 @@ struct Info
|
|||
(rhs.gcodes == this->gcodes );
|
||||
}
|
||||
bool operator!=(const Info& rhs) const { return !(*this == rhs); }
|
||||
|
||||
void from_json(const nlohmann::json& j) {
|
||||
std::string mode_str;
|
||||
if (j.contains("mode"))
|
||||
j.at("mode").get_to(mode_str);
|
||||
if (mode_str == "SingleExtruder") mode = SingleExtruder;
|
||||
else if (mode_str == "MultiAsSingle") mode = MultiAsSingle;
|
||||
else if (mode_str == "MultiExtruder") mode = MultiExtruder;
|
||||
else mode = Undef;
|
||||
|
||||
auto j_gcodes = j.at("gcodes");
|
||||
gcodes.reserve(j_gcodes.size());
|
||||
for (auto& jj : j_gcodes) {
|
||||
Item item;
|
||||
item.from_json(jj);
|
||||
gcodes.push_back(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// If loaded configuration has a "colorprint_heights" option (if it was imported from older Slicer),
|
||||
|
|
|
|||
|
|
@ -786,7 +786,7 @@ void Layer::make_ironing()
|
|||
// Check whether there is any non-solid hole in the regions.
|
||||
bool internal_infill_solid = region_config.sparse_infill_density.value > 95.;
|
||||
for (const Surface &surface : ironing_params.layerm->fill_surfaces.surfaces)
|
||||
if ((! internal_infill_solid && surface.surface_type == stInternal) || surface.surface_type == stInternalBridge || surface.surface_type == stInternalVoid) {
|
||||
if ((!internal_infill_solid && surface.surface_type == stInternal) || surface.surface_type == stInternalBridge || surface.surface_type == stInternalVoid || surface.surface_type==stInternalWithLoop) {
|
||||
// Some fill region is not quite solid. Don't iron over the whole surface.
|
||||
iron_completely = false;
|
||||
break;
|
||||
|
|
@ -798,7 +798,7 @@ void Layer::make_ironing()
|
|||
polygons_append(polys, surface.expolygon);
|
||||
} else {
|
||||
for (const Surface &surface : ironing_params.layerm->slices.surfaces)
|
||||
if (surface.surface_type == stTop || (iron_everything && surface.surface_type == stBottom))
|
||||
if ((surface.surface_type == stTop && region_config.top_shell_layers > 0) || (iron_everything && surface.surface_type == stBottom && region_config.bottom_shell_layers > 0))
|
||||
// stBottomBridge is not being ironed on purpose, as it would likely destroy the bridges.
|
||||
polygons_append(polys, surface.expolygon);
|
||||
}
|
||||
|
|
|
|||
19
src/libslic3r/Format/ModelIO.hpp
Normal file
19
src/libslic3r/Format/ModelIO.hpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include <string>
|
||||
|
||||
namespace Slic3r {
|
||||
/**
|
||||
* Uses ModelIO to convert supported model types to a temporary STL
|
||||
* that can then be consumed by the existing STL loader
|
||||
* @param input_file The File to load
|
||||
* @return Path to the temporary file, or an empty string if conversion failed
|
||||
*/
|
||||
std::string make_temp_stl_with_modelio(const std::string &input_file);
|
||||
|
||||
/**
|
||||
* Convenience function to delete the file.
|
||||
* No return value since success isn't required
|
||||
* @param temp_file File path to delete
|
||||
*/
|
||||
void delete_temp_file(const std::string &temp_file);
|
||||
}
|
||||
|
||||
27
src/libslic3r/Format/ModelIO.mm
Normal file
27
src/libslic3r/Format/ModelIO.mm
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#include "ModelIO.hpp"
|
||||
#import <ModelIO/ModelIO.h>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
std::string make_temp_stl_with_modelio(const std::string &input_file)
|
||||
{
|
||||
NSURL *input_url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:input_file.c_str()]];
|
||||
MDLAsset *asset = [[MDLAsset alloc] initWithURL:input_url];
|
||||
|
||||
NSString *tmp_file_name = [[[NSUUID UUID] UUIDString] stringByAppendingPathExtension:@"stl"];
|
||||
NSURL *tmp_file_url = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:tmp_file_name]];
|
||||
|
||||
if ([asset exportAssetToURL:tmp_file_url]) {
|
||||
std::string output_file = std::string([[tmp_file_url path] UTF8String]);
|
||||
return output_file;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
void delete_temp_file(const std::string &temp_file)
|
||||
{
|
||||
NSString *file_path = [NSString stringWithUTF8String:temp_file.c_str()];
|
||||
[[NSFileManager defaultManager] removeItemAtPath:file_path error:NULL];
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
@ -116,6 +116,7 @@ const std::string BBL_DESIGNER_USER_ID_TAG = "DesignerUserId";
|
|||
const std::string BBL_DESIGNER_COVER_FILE_TAG = "DesignerCover";
|
||||
const std::string BBL_DESCRIPTION_TAG = "Description";
|
||||
const std::string BBL_COPYRIGHT_TAG = "CopyRight";
|
||||
const std::string BBL_COPYRIGHT_NORMATIVE_TAG = "Copyright";
|
||||
const std::string BBL_LICENSE_TAG = "License";
|
||||
const std::string BBL_REGION_TAG = "Region";
|
||||
const std::string BBL_MODIFICATION_TAG = "ModificationDate";
|
||||
|
|
@ -226,11 +227,14 @@ static constexpr const char* HIT_NORMAL_ATTR = "hit_normal";
|
|||
// BBS: encrypt
|
||||
static constexpr const char* RELATIONSHIP_TAG = "Relationship";
|
||||
static constexpr const char* PID_ATTR = "pid";
|
||||
static constexpr const char* PUUID_ATTR = "p:uuid";
|
||||
static constexpr const char* PUUID_ATTR = "p:UUID";
|
||||
static constexpr const char* PUUID_LOWER_ATTR = "p:uuid";
|
||||
static constexpr const char* PPATH_ATTR = "p:path";
|
||||
static constexpr const char *OBJECT_UUID_SUFFIX = "-61cb-4c03-9d28-80fed5dfa1dc";
|
||||
static constexpr const char *OBJECT_UUID_SUFFIX2 = "-71cb-4c03-9d28-80fed5dfa1dc";
|
||||
static constexpr const char* BUILD_UUID = "d8eb061-b1ec-4553-aec9-835e5b724bb4";
|
||||
static constexpr const char *SUB_OBJECT_UUID_SUFFIX = "-81cb-4c03-9d28-80fed5dfa1dc";
|
||||
static constexpr const char *COMPONENT_UUID_SUFFIX = "-b206-40ff-9872-83e8017abed1";
|
||||
static constexpr const char* BUILD_UUID = "2c7c17d8-22b5-4d84-8835-1976022ea369";
|
||||
static constexpr const char* BUILD_UUID_SUFFIX = "-b1ec-4553-aec9-835e5b724bb4";
|
||||
static constexpr const char* TARGET_ATTR = "Target";
|
||||
static constexpr const char* RELS_TYPE_ATTR = "Type";
|
||||
|
|
@ -281,6 +285,8 @@ static constexpr const char* PLATER_NAME_ATTR = "plater_name";
|
|||
static constexpr const char* PLATE_IDX_ATTR = "index";
|
||||
static constexpr const char* SLICE_PREDICTION_ATTR = "prediction";
|
||||
static constexpr const char* SLICE_WEIGHT_ATTR = "weight";
|
||||
static constexpr const char* TIMELAPSE_TYPE_ATTR = "timelapse_type";
|
||||
static constexpr const char* TIMELAPSE_ERROR_CODE_ATTR = "timelapse_error_code";
|
||||
static constexpr const char* OUTSIDE_ATTR = "outside";
|
||||
static constexpr const char* SUPPORT_USED_ATTR = "support_used";
|
||||
static constexpr const char* LABEL_OBJECT_ENABLED_ATTR = "label_object_enabled";
|
||||
|
|
@ -1679,7 +1685,12 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
std::string name(stat.m_filename);
|
||||
std::replace(name.begin(), name.end(), '\\', '/');
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("extract %1%th file %2%, total=%3%\n")%(i+1)%name%num_entries;
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format("extract %1%th file %2%, total=%3%")%(i+1)%name%num_entries;
|
||||
|
||||
if (name.find("/../") != std::string::npos) {
|
||||
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", find file path including /../, not valid, skip it\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (boost::algorithm::iequals(name, BBS_LAYER_HEIGHTS_PROFILE_FILE)) {
|
||||
// extract slic3r layer heights profile file
|
||||
|
|
@ -1763,6 +1774,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
//BBS parsing pattern config files
|
||||
_extract_file_from_archive(archive, stat);
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", %1% skipped, already parsed or a directory or not supported\n")%name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2175,7 +2189,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
}
|
||||
}
|
||||
char error_buf[1024];
|
||||
::sprintf(error_buf, "File %s not found from archive", path.c_str());
|
||||
::snprintf(error_buf, 1024, "File %s not found from archive", path.c_str());
|
||||
add_error(error_buf);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2234,7 +2248,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
if (!XML_ParseBuffer(m_xml_parser, (int)stat.m_uncomp_size, 1)) {
|
||||
char error_buf[1024];
|
||||
::sprintf(error_buf, "Error (%s) while parsing xml file at line %d", XML_ErrorString(XML_GetErrorCode(m_xml_parser)), (int)XML_GetCurrentLineNumber(m_xml_parser));
|
||||
::snprintf(error_buf, 1024, "Error (%s) while parsing xml file at line %d", XML_ErrorString(XML_GetErrorCode(m_xml_parser)), (int)XML_GetCurrentLineNumber(m_xml_parser));
|
||||
add_error(error_buf);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2280,7 +2294,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
CallbackData* data = (CallbackData*)pOpaque;
|
||||
if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0) || data->importer.parse_error()) {
|
||||
char error_buf[1024];
|
||||
::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", data->importer.parse_error_message(), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
|
||||
::snprintf(error_buf, 1024, "Error (%s) while parsing '%s' at line %d", data->importer.parse_error_message(), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
|
||||
throw Slic3r::FileIOError(error_buf);
|
||||
}
|
||||
return n;
|
||||
|
|
@ -2501,6 +2515,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
void _BBS_3MF_Importer::_extract_auxiliary_file_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, Model& model)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", stat.m_uncomp_size is %1%")%stat.m_uncomp_size;
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
std::string dest_file;
|
||||
if (stat.m_is_utf8) {
|
||||
|
|
@ -2518,6 +2533,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
dest_file = dest_file.substr(found + AUXILIARY_STR_LEN);
|
||||
else
|
||||
return;
|
||||
|
||||
if (dest_file.find('/') != std::string::npos) {
|
||||
boost::filesystem::path src_path = boost::filesystem::path(dest_file);
|
||||
boost::filesystem::path parent_path = src_path.parent_path();
|
||||
|
|
@ -3175,6 +3191,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
m_curr_object->name = bbs_get_attribute_value_string(attributes, num_attributes, NAME_ATTR);
|
||||
|
||||
m_curr_object->uuid = bbs_get_attribute_value_string(attributes, num_attributes, PUUID_ATTR);
|
||||
if (m_curr_object->uuid.empty()) {
|
||||
m_curr_object->uuid = bbs_get_attribute_value_string(attributes, num_attributes, PUUID_LOWER_ATTR);
|
||||
}
|
||||
m_curr_object->pid = bbs_get_attribute_value_int(attributes, num_attributes, PID_ATTR);
|
||||
}
|
||||
|
||||
|
|
@ -3563,7 +3582,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found license = " << m_curr_characters;
|
||||
model_info.license = xml_unescape(m_curr_characters);
|
||||
} else if (m_curr_metadata_name == BBL_COPYRIGHT_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found copyright = " << m_curr_characters;
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found CopyRight = " << m_curr_characters;
|
||||
model_info.copyright = xml_unescape(m_curr_characters);
|
||||
} else if (m_curr_metadata_name == BBL_COPYRIGHT_NORMATIVE_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found Copyright = " << m_curr_characters;
|
||||
model_info.copyright = xml_unescape(m_curr_characters);
|
||||
} else if (m_curr_metadata_name == BBL_REGION_TAG) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "design_info, load_3mf found region = " << m_curr_characters;
|
||||
|
|
@ -4027,7 +4049,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
if (!m_curr_plater)
|
||||
{
|
||||
add_error("don't find plater created before");
|
||||
add_error("_handle_end_config_plater: don't find plate created before");
|
||||
return false;
|
||||
}
|
||||
m_plater_data.emplace(m_curr_plater->plate_index, m_curr_plater);
|
||||
|
|
@ -4039,7 +4061,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
if (!m_curr_plater)
|
||||
{
|
||||
add_error("don't find plater created before");
|
||||
add_error("_handle_start_config_plater_instance: don't find plate created before");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -4051,7 +4073,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
if (!m_curr_plater)
|
||||
{
|
||||
add_error("don't find plater created before");
|
||||
add_error("_handle_end_config_plater_instance: don't find plate created before");
|
||||
return false;
|
||||
}
|
||||
if ((m_curr_instance.object_id == -1) || (m_curr_instance.instance_id == -1))
|
||||
|
|
@ -4430,6 +4452,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
volume->supported_facets.shrink_to_fit();
|
||||
volume->seam_facets.shrink_to_fit();
|
||||
volume->mmu_segmentation_facets.shrink_to_fit();
|
||||
volume->mmu_segmentation_facets.touch();
|
||||
}
|
||||
|
||||
volume->set_type(volume_data->part_type);
|
||||
|
|
@ -4709,6 +4732,9 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
current_object->name = bbs_get_attribute_value_string(attributes, num_attributes, NAME_ATTR);
|
||||
|
||||
current_object->uuid = bbs_get_attribute_value_string(attributes, num_attributes, PUUID_ATTR);
|
||||
if (current_object->uuid.empty()) {
|
||||
current_object->uuid = bbs_get_attribute_value_string(attributes, num_attributes, PUUID_LOWER_ATTR);
|
||||
}
|
||||
current_object->pid = bbs_get_attribute_value_int(attributes, num_attributes, PID_ATTR);
|
||||
}
|
||||
|
||||
|
|
@ -5096,7 +5122,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
CallbackData* data = (CallbackData*)pOpaque;
|
||||
if (!XML_Parse(data->parser, (const char*)pBuf, (int)n, (file_ofs + n == data->stat.m_uncomp_size) ? 1 : 0) || data->importer.object_parse_error()) {
|
||||
char error_buf[1024];
|
||||
::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", data->importer.object_parse_error_message(), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
|
||||
::snprintf(error_buf, 1024, "Error (%s) while parsing '%s' at line %d", data->importer.object_parse_error_message(), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
|
||||
throw Slic3r::FileIOError(error_buf);
|
||||
}
|
||||
return n;
|
||||
|
|
@ -5219,7 +5245,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
bool _add_content_types_file_to_archive(mz_zip_archive& archive);
|
||||
|
||||
bool _add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, const char* local_path, int index);
|
||||
bool _add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, const char* local_path, int index, bool generate_small_thumbnail = false);
|
||||
bool _add_calibration_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, int index);
|
||||
bool _add_bbox_file_to_archive(mz_zip_archive& archive, const PlateBBoxData& id_bboxes, int index);
|
||||
bool _add_relationships_file_to_archive(mz_zip_archive & archive,
|
||||
|
|
@ -5245,7 +5271,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
bool _add_project_embedded_presets_to_archive(mz_zip_archive& archive, Model& model, std::vector<Preset*> project_presets);
|
||||
bool _add_model_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const ObjectToObjectDataMap &objects_data, int export_plate_idx = -1, bool save_gcode = true, bool use_loaded_id = false);
|
||||
bool _add_cut_information_file_to_archive(mz_zip_archive &archive, Model &model);
|
||||
bool _add_slice_info_config_file_to_archive(mz_zip_archive &archive, const Model &model, PlateDataPtrs &plate_data_list, const ObjectToObjectDataMap &objects_data);
|
||||
bool _add_slice_info_config_file_to_archive(mz_zip_archive &archive, const Model &model, PlateDataPtrs &plate_data_list, const ObjectToObjectDataMap &objects_data, const DynamicPrintConfig& config);
|
||||
bool _add_gcode_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, Export3mfProgressFn proFn = nullptr);
|
||||
bool _add_custom_gcode_per_print_z_file_to_archive(mz_zip_archive& archive, Model& model, const DynamicPrintConfig* config);
|
||||
bool _add_auxiliary_dir_to_archive(mz_zip_archive &archive, const std::string &aux_dir, PackingTemporaryData &data);
|
||||
|
|
@ -5464,9 +5490,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
if (thumbnail_data[index]->is_valid())
|
||||
{
|
||||
if (!_add_thumbnail_file_to_archive(archive, *thumbnail_data[index], "Metadata/plate", index)) {
|
||||
if (!_add_thumbnail_file_to_archive(archive, *thumbnail_data[index], "Metadata/plate", index, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format(",add thumbnail %1%'s data into 3mf")%(index+1);
|
||||
thumbnail_status[index] = true;
|
||||
}
|
||||
|
|
@ -5746,7 +5773,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
|
||||
// Adds sliced info of plate file ("Metadata/slice_info.config")
|
||||
// This file contains all sliced info of all plates
|
||||
if (!_add_slice_info_config_file_to_archive(archive, model, plate_data_list, objects_data)) {
|
||||
if (!_add_slice_info_config_file_to_archive(archive, model, plate_data_list, objects_data, *config)) {
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", _add_slice_info_config_file_to_archive failed\n");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -5843,7 +5870,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Exporter::_add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, const char* local_path, int index)
|
||||
bool _BBS_3MF_Exporter::_add_thumbnail_file_to_archive(mz_zip_archive& archive, const ThumbnailData& thumbnail_data, const char* local_path, int index, bool generate_small_thumbnail)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
|
|
@ -5860,6 +5887,49 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", Unable to add thumbnail file to archive\n");
|
||||
}
|
||||
|
||||
if (generate_small_thumbnail && thumbnail_data.is_valid()) {
|
||||
//generate small size of thumbnail
|
||||
std::vector<unsigned char> small_pixels;
|
||||
small_pixels.resize(PLATE_THUMBNAIL_SMALL_WIDTH * PLATE_THUMBNAIL_SMALL_HEIGHT * 4);
|
||||
/* step width and step height */
|
||||
int sw = thumbnail_data.width / PLATE_THUMBNAIL_SMALL_WIDTH;
|
||||
int sh = thumbnail_data.height / PLATE_THUMBNAIL_SMALL_HEIGHT;
|
||||
for (int i = 0; i < thumbnail_data.height; i += sh) {
|
||||
for (int j = 0; j < thumbnail_data.width; j += sw) {
|
||||
int r = 0, g = 0, b = 0, a = 0;
|
||||
for (int m = 0; m < sh; m++) {
|
||||
for (int n = 0; n < sw; n++) {
|
||||
r += (int)thumbnail_data.pixels[4 * ((i + m) * thumbnail_data.width + j + n) + 0];
|
||||
g += (int)thumbnail_data.pixels[4 * ((i + m) * thumbnail_data.width + j + n) + 1];
|
||||
b += (int)thumbnail_data.pixels[4 * ((i + m) * thumbnail_data.width + j + n) + 2];
|
||||
a += (int)thumbnail_data.pixels[4 * ((i + m) * thumbnail_data.width + j + n) + 3];
|
||||
}
|
||||
}
|
||||
r = std::clamp(0, r / sw / sh, 255);
|
||||
g = std::clamp(0, g / sw / sh, 255);
|
||||
b = std::clamp(0, b / sw / sh, 255);
|
||||
a = std::clamp(0, a / sw / sh, 255);
|
||||
small_pixels[4 * (i / sw * PLATE_THUMBNAIL_SMALL_WIDTH + j / sh) + 0] = (unsigned char)r;
|
||||
small_pixels[4 * (i / sw * PLATE_THUMBNAIL_SMALL_WIDTH + j / sh) + 1] = (unsigned char)g;
|
||||
small_pixels[4 * (i / sw * PLATE_THUMBNAIL_SMALL_WIDTH + j / sh) + 2] = (unsigned char)b;
|
||||
small_pixels[4 * (i / sw * PLATE_THUMBNAIL_SMALL_WIDTH + j / sh) + 3] = (unsigned char)a;
|
||||
//memcpy((void*)&small_pixels[4*(i / sw * PLATE_THUMBNAIL_SMALL_WIDTH + j / sh)], thumbnail_data.pixels.data() + 4*(i * thumbnail_data.width + j), 4);
|
||||
}
|
||||
}
|
||||
size_t small_png_size = 0;
|
||||
void* small_png_data = tdefl_write_image_to_png_file_in_memory_ex((const void*)small_pixels.data(), PLATE_THUMBNAIL_SMALL_WIDTH, PLATE_THUMBNAIL_SMALL_HEIGHT, 4, &small_png_size, MZ_DEFAULT_COMPRESSION, 1);
|
||||
if (png_data != nullptr) {
|
||||
std::string thumbnail_name = (boost::format("%1%_%2%_small.png") % local_path % (index + 1)).str();
|
||||
res = mz_zip_writer_add_mem(&archive, thumbnail_name.c_str(), (const void*)small_png_data, small_png_size, MZ_NO_COMPRESSION);
|
||||
mz_free(small_png_data);
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
add_error("Unable to add small thumbnail file to archive");
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ":" << __LINE__ << boost::format(", Unable to add small thumbnail file to archive\n");
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -5909,27 +5979,46 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
if (from.empty()) {
|
||||
stream << " <Relationship Target=\"/" << MODEL_FILE << "\" Id=\"rel-1\" Type=\"http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel\"/>\n";
|
||||
|
||||
if (data._3mf_thumbnail.empty()) {
|
||||
if (export_plate_idx < 0) {
|
||||
stream << " <Relationship Target=\"/" << THUMBNAIL_FILE
|
||||
<< "\" Id=\"rel-2\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail\"/>\n";
|
||||
if (export_plate_idx < 0) {
|
||||
//use cover image if have
|
||||
if (data._3mf_thumbnail.empty()) {
|
||||
stream << " <Relationship Target=\"/Metadata/plate_1.png"
|
||||
<< "\" Id=\"rel-2\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail\"/>\n";
|
||||
} else {
|
||||
std::string thumbnail_file_str = (boost::format("Metadata/plate_%1%.png") % (export_plate_idx + 1)).str();
|
||||
stream << " <Relationship Target=\"/" << xml_escape(thumbnail_file_str)
|
||||
<< "\" Id=\"rel-2\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail\"/>\n";
|
||||
stream << " <Relationship Target=\"/" << xml_escape(data._3mf_thumbnail)
|
||||
<< "\" Id=\"rel-2\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail\"/>\n";
|
||||
}
|
||||
} else {
|
||||
stream << " <Relationship Target=\"/" << xml_escape(data._3mf_thumbnail)
|
||||
<< "\" Id=\"rel-2\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail\"/>\n";
|
||||
}
|
||||
|
||||
if (!data._3mf_printer_thumbnail_middle.empty()) {
|
||||
stream << " <Relationship Target=\"/" << xml_escape(data._3mf_printer_thumbnail_middle)
|
||||
<< "\" Id=\"rel-4\" Type=\"http://schemas.bambulab.com/package/2021/cover-thumbnail-middle\"/>\n";
|
||||
if (data._3mf_printer_thumbnail_middle.empty()) {
|
||||
stream << " <Relationship Target=\"/Metadata/plate_1.png"
|
||||
<< "\" Id=\"rel-4\" Type=\"http://schemas.bambulab.com/package/2021/cover-thumbnail-middle\"/>\n";
|
||||
} else {
|
||||
stream << " <Relationship Target=\"/" << xml_escape(data._3mf_printer_thumbnail_middle)
|
||||
<< "\" Id=\"rel-4\" Type=\"http://schemas.bambulab.com/package/2021/cover-thumbnail-middle\"/>\n";
|
||||
}
|
||||
|
||||
if (data._3mf_printer_thumbnail_small.empty()) {
|
||||
stream << "<Relationship Target=\"/Metadata/plate_1_small.png"
|
||||
<< "\" Id=\"rel-5\" Type=\"http://schemas.bambulab.com/package/2021/cover-thumbnail-small\"/>\n";
|
||||
} else {
|
||||
stream << " <Relationship Target=\"/" << xml_escape(data._3mf_printer_thumbnail_small)
|
||||
<< "\" Id=\"rel-5\" Type=\"http://schemas.bambulab.com/package/2021/cover-thumbnail-small\"/>\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
//always use plate thumbnails
|
||||
std::string thumbnail_file_str = (boost::format("Metadata/plate_%1%.png") % (export_plate_idx + 1)).str();
|
||||
stream << " <Relationship Target=\"/" << xml_escape(thumbnail_file_str)
|
||||
<< "\" Id=\"rel-2\" Type=\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail\"/>\n";
|
||||
|
||||
thumbnail_file_str = (boost::format("Metadata/plate_%1%.png") % (export_plate_idx + 1)).str();
|
||||
stream << " <Relationship Target=\"/" << xml_escape(thumbnail_file_str)
|
||||
<< "\" Id=\"rel-4\" Type=\"http://schemas.bambulab.com/package/2021/cover-thumbnail-middle\"/>\n";
|
||||
|
||||
thumbnail_file_str = (boost::format("Metadata/plate_%1%_small.png") % (export_plate_idx + 1)).str();
|
||||
stream << " <Relationship Target=\"/" << xml_escape(thumbnail_file_str)
|
||||
<< "\" Id=\"rel-5\" Type=\"http://schemas.bambulab.com/package/2021/cover-thumbnail-small\"/>\n";
|
||||
}
|
||||
if (!data._3mf_printer_thumbnail_small.empty())
|
||||
stream << " <Relationship Target=\"/" << xml_escape(data._3mf_printer_thumbnail_small)
|
||||
<< "\" Id=\"rel-5\" Type=\"http://schemas.bambulab.com/package/2021/cover-thumbnail-small\"/>\n";
|
||||
}
|
||||
else if (targets.empty()) {
|
||||
return false;
|
||||
|
|
@ -6059,7 +6148,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
metadata_item_map[BBL_DESIGNER_USER_ID_TAG] = user_id;
|
||||
metadata_item_map[BBL_DESIGNER_COVER_FILE_TAG] = xml_escape(design_cover);
|
||||
metadata_item_map[BBL_DESCRIPTION_TAG] = xml_escape(description);
|
||||
metadata_item_map[BBL_COPYRIGHT_TAG] = xml_escape(copyright);
|
||||
metadata_item_map[BBL_COPYRIGHT_NORMATIVE_TAG] = xml_escape(copyright);
|
||||
metadata_item_map[BBL_LICENSE_TAG] = xml_escape(license);
|
||||
|
||||
/* save model info */
|
||||
|
|
@ -6313,9 +6402,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
}
|
||||
//add the transform of the volume
|
||||
if (ppath->empty())
|
||||
stream << " <" << COMPONENT_TAG << " objectid=\"" << volume_id; // << "\"/>\n";
|
||||
stream << " <" << COMPONENT_TAG << " objectid=\"" << volume_id;
|
||||
else
|
||||
stream << " <" << COMPONENT_TAG << " p:path=\"" << xml_escape(*ppath) << "\" objectid=\"" << volume_id; // << "\"/>\n";
|
||||
stream << "\" " << PUUID_ATTR << "=\"" << hex_wrap<boost::uint32_t>{(boost::uint32_t) object_data.backup_id} << COMPONENT_UUID_SUFFIX;
|
||||
const Transform3d &transf = volume->get_matrix();
|
||||
stream << "\" " << TRANSFORM_ATTR << "=\"";
|
||||
for (unsigned c = 0; c < 4; ++c) {
|
||||
|
|
@ -6437,17 +6527,17 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
output_buffer += OBJECT_TAG;
|
||||
output_buffer += " id=\"";
|
||||
output_buffer += std::to_string(volume_id);
|
||||
/*if (m_production_ext) {
|
||||
if (m_production_ext) {
|
||||
std::stringstream stream;
|
||||
reset_stream(stream);
|
||||
stream << "\" " << PUUID_ATTR << "=\"" << hex_wrap<boost::uint32_t>{(boost::uint32_t)backup_id} << OBJECT_UUID_SUFFIX;
|
||||
stream << "\" " << PUUID_ATTR << "=\"" << hex_wrap<boost::uint32_t>{(boost::uint32_t) object_data.backup_id} << SUB_OBJECT_UUID_SUFFIX;
|
||||
//output_buffer += "\" ";
|
||||
//output_buffer += PUUID_ATTR;
|
||||
//output_buffer += "=\"";
|
||||
//output_buffer += std::to_string(hex_wrap<boost::uint32_t>{(boost::uint32_t)backup_id});
|
||||
//output_buffer += OBJECT_UUID_SUFFIX;
|
||||
output_buffer += stream.str();
|
||||
}*/
|
||||
}
|
||||
output_buffer += "\" type=\"";
|
||||
output_buffer += type;
|
||||
output_buffer += "\">\n";
|
||||
|
|
@ -6580,6 +6670,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
// This happens for empty projects
|
||||
if (build_items.size() == 0) {
|
||||
stream << " <" << BUILD_TAG << "/>\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -6621,12 +6712,12 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
++count;
|
||||
const std::vector<double>& layer_height_profile = object->layer_height_profile.get();
|
||||
if (layer_height_profile.size() >= 4 && layer_height_profile.size() % 2 == 0) {
|
||||
sprintf(buffer, "object_id=%d|", count);
|
||||
snprintf(buffer, 1024, "object_id=%d|", count);
|
||||
out += buffer;
|
||||
|
||||
// Store the layer height profile as a single semicolon separated list.
|
||||
for (size_t i = 0; i < layer_height_profile.size(); ++i) {
|
||||
sprintf(buffer, (i == 0) ? "%f" : ";%f", layer_height_profile[i]);
|
||||
snprintf(buffer, 1024, (i == 0) ? "%f" : ";%f", layer_height_profile[i]);
|
||||
out += buffer;
|
||||
}
|
||||
|
||||
|
|
@ -6797,7 +6888,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
{
|
||||
assert(is_decimal_separator_point());
|
||||
char buffer[1024];
|
||||
sprintf(buffer, "; %s\n\n", header_slic3r_generated().c_str());
|
||||
snprintf(buffer, 1024, "; %s\n\n", header_slic3r_generated().c_str());
|
||||
std::string out = buffer;
|
||||
|
||||
for (const std::string &key : config.keys())
|
||||
|
|
@ -6828,7 +6919,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
bool _BBS_3MF_Exporter::_add_project_embedded_presets_to_archive(mz_zip_archive& archive, Model& model, std::vector<Preset*> project_presets)
|
||||
{
|
||||
char buffer[1024];
|
||||
sprintf(buffer, "; %s\n\n", header_slic3r_generated().c_str());
|
||||
snprintf(buffer, 1024, "; %s\n\n", header_slic3r_generated().c_str());
|
||||
std::string out = buffer;
|
||||
int print_count = 0, filament_count = 0, printer_count = 0;
|
||||
const std::string& temp_path = model.get_backup_path();
|
||||
|
|
@ -7235,7 +7326,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool _BBS_3MF_Exporter::_add_slice_info_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const ObjectToObjectDataMap &objects_data)
|
||||
bool _BBS_3MF_Exporter::_add_slice_info_config_file_to_archive(mz_zip_archive& archive, const Model& model, PlateDataPtrs& plate_data_list, const ObjectToObjectDataMap &objects_data, const DynamicPrintConfig& config)
|
||||
{
|
||||
std::stringstream stream;
|
||||
// Store mesh transformation in full precision, as the volumes are stored transformed and they need to be transformed back
|
||||
|
|
@ -7260,6 +7351,16 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
|||
stream << " <" << PLATE_TAG << ">\n";
|
||||
//plate index
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PLATE_IDX_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->plate_index + 1 << "\"/>\n";
|
||||
|
||||
int timelapse_type = int(config.opt_enum<TimelapseType>("timelapse_type"));
|
||||
for (auto it = plate_data->warnings.begin(); it != plate_data->warnings.end(); it++) {
|
||||
if (it->msg == NOT_GENERATE_TIMELAPSE) {
|
||||
timelapse_type = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << TIMELAPSE_TYPE_ATTR << "\" " << VALUE_ATTR << "=\"" << timelapse_type << "\"/>\n";
|
||||
//stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << TIMELAPSE_ERROR_CODE_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->timelapse_warning_code << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SLICE_PREDICTION_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->get_gcode_prediction_str() << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << SLICE_WEIGHT_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->get_gcode_weight_str() << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << OUTSIDE_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha<< plate_data->toolpath_outside << "\"/>\n";
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ class Preset;
|
|||
struct FilamentInfo;
|
||||
struct ThumbnailData;
|
||||
|
||||
|
||||
#define PLATE_THUMBNAIL_SMALL_WIDTH 128
|
||||
#define PLATE_THUMBNAIL_SMALL_HEIGHT 128
|
||||
|
||||
#define GCODE_FILE_FORMAT "Metadata/plate_%1%.gcode"
|
||||
#define THUMBNAIL_FILE_FORMAT "Metadata/plate_%1%.png"
|
||||
#define TOP_FILE_FORMAT "Metadata/top_%1%.png"
|
||||
|
|
@ -84,6 +88,7 @@ struct PlateData
|
|||
bool is_sliced_valid = false;
|
||||
bool toolpath_outside {false};
|
||||
bool is_label_object_enabled {false};
|
||||
int timelapse_warning_code = 0; // 1<<0 sprial vase, 1<<1 by object
|
||||
|
||||
std::vector<GCodeProcessorResult::SliceWarning> warnings;
|
||||
|
||||
|
|
|
|||
|
|
@ -190,6 +190,10 @@ bool get_svg_profile(const char *path, std::vector<Element_Info> &element_infos,
|
|||
profile_line_points.push_back({pt1, pt2});
|
||||
}
|
||||
}
|
||||
|
||||
if (profile_line_points.empty())
|
||||
continue;
|
||||
|
||||
// keep the start and end points of profile connected
|
||||
if (shape->fill.gradient != nullptr)
|
||||
profile_line_points.back().second = profile_line_points[0].first;
|
||||
|
|
@ -269,6 +273,9 @@ bool get_svg_profile(const char *path, std::vector<Element_Info> &element_infos,
|
|||
wires.emplace_back(wire);
|
||||
}
|
||||
|
||||
if (wires.empty())
|
||||
continue;
|
||||
|
||||
gp_Vec dir(0, 0, 10);
|
||||
BRepBuilderAPI_MakeFace face_make(wires[index]);
|
||||
for (int i = 0; i < wires.size(); ++i) {
|
||||
|
|
|
|||
|
|
@ -980,6 +980,33 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
return gcode;
|
||||
}
|
||||
|
||||
bool WipeTowerIntegration::is_empty_wipe_tower_gcode(GCode &gcodegen, int extruder_id, bool finish_layer)
|
||||
{
|
||||
assert(m_layer_idx >= 0);
|
||||
if (m_layer_idx >= (int) m_tool_changes.size())
|
||||
return true;
|
||||
|
||||
bool ignore_sparse = false;
|
||||
if (gcodegen.config().wipe_tower_no_sparse_layers.value) {
|
||||
ignore_sparse = (m_tool_changes[m_layer_idx].size() == 1 && m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool);
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print && m_is_first_print) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
|
||||
if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
|
||||
throw Slic3r::RuntimeError("Wipe tower generation failed, possibly due to empty first layer.");
|
||||
|
||||
if (!ignore_sparse) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Print is finished. Now it remains to unload the filament safely with ramming over the wipe tower.
|
||||
std::string WipeTowerIntegration::finalize(GCode &gcodegen)
|
||||
{
|
||||
|
|
@ -1367,6 +1394,7 @@ namespace DoExport {
|
|||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Machine end G-code")), config.machine_end_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Before layer change G-code")), config.before_layer_change_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Layer change G-code")), config.layer_change_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Time lapse G-code")), config.time_lapse_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Change filament G-code")), config.change_filament_gcode.value);
|
||||
//BBS
|
||||
//if (ret.size() < MAX_TAGS_COUNT) check(_(L("Printing by object G-code")), config.printing_by_object_gcode.value);
|
||||
|
|
@ -1489,6 +1517,16 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu
|
|||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info();
|
||||
// Post-process the G-code to update time stamps.
|
||||
|
||||
m_timelapse_warning_code = 0;
|
||||
if (m_config.printer_structure.value == PrinterStructure::psI3 && m_spiral_vase) {
|
||||
m_timelapse_warning_code += 1;
|
||||
}
|
||||
if (m_config.printer_structure.value == PrinterStructure::psI3 && print->config().print_sequence == PrintSequence::ByObject) {
|
||||
m_timelapse_warning_code += (1 << 1);
|
||||
}
|
||||
m_processor.result().timelapse_warning_code = m_timelapse_warning_code;
|
||||
m_processor.result().support_traditional_timelapse = m_support_traditional_timelapse;
|
||||
m_processor.finalize(true);
|
||||
// DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics);
|
||||
DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->m_print_statistics, print->config());
|
||||
|
|
@ -1651,16 +1689,13 @@ namespace DoExport {
|
|||
output((boost::format("; thumbnail begin %dx%d %d\n") % data.width % data.height % encoded.size()).str().c_str());
|
||||
|
||||
unsigned int row_count = 0;
|
||||
while (encoded.size() > max_row_length)
|
||||
{
|
||||
output((boost::format("; %s\n") % encoded.substr(0, max_row_length)).str().c_str());
|
||||
encoded = encoded.substr(max_row_length);
|
||||
//BBS: optimize performance ,reduce too much memeory operation
|
||||
size_t current_index = 0;
|
||||
while(current_index<encoded.size()){
|
||||
output((boost::format("; %s\n") % encoded.substr(current_index, max_row_length)).str().c_str());
|
||||
current_index+=std::min(max_row_length,encoded.size()-current_index);
|
||||
++row_count;
|
||||
}
|
||||
|
||||
if (encoded.size() > 0)
|
||||
output((boost::format("; %s\n") % encoded).str().c_str());
|
||||
|
||||
output("; thumbnail end\n");
|
||||
output("; THUMBNAIL_BLOCK_END\n\n");
|
||||
|
||||
|
|
@ -1948,7 +1983,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
[&print]() { print.throw_if_canceled(); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Write some terse information on the slicing parameters.
|
||||
const PrintObject *first_object = print.objects().front();
|
||||
|
|
@ -2248,8 +2283,12 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
file.writeln(this->placeholder_parser_process("filament_start_gcode", print.config().filament_start_gcode.values[initial_extruder_id], initial_extruder_id, &config));
|
||||
}
|
||||
*/
|
||||
if (is_bbl_printers)
|
||||
if (is_bbl_printers) {
|
||||
this->_print_first_layer_extruder_temperatures(file, print, machine_start_gcode, initial_extruder_id, true);
|
||||
if (m_config.support_air_filtration.getBool() && m_config.activate_air_filtration.get_at(initial_extruder_id)) {
|
||||
file.write(m_writer.set_exhaust_fan(m_config.during_print_exhaust_fan_speed.get_at(initial_extruder_id), true));
|
||||
}
|
||||
}
|
||||
print.throw_if_canceled();
|
||||
|
||||
// Set other general things.
|
||||
|
|
@ -2512,6 +2551,9 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
file.write(m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
|
||||
file.write(m_writer.postamble());
|
||||
|
||||
file.write(m_writer.set_chamber_temperature(0, false)); //close chamber_temperature
|
||||
|
||||
|
||||
// adds tags for time estimators
|
||||
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Last_Line_M73_Placeholder).c_str());
|
||||
file.write_format("; EXECUTABLE_BLOCK_END\n\n");
|
||||
|
|
@ -2561,6 +2603,19 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
}
|
||||
file.write("\n");
|
||||
|
||||
bool activate_air_filtration = false;
|
||||
for (const auto& extruder : m_writer.extruders())
|
||||
activate_air_filtration |= m_config.activate_air_filtration.get_at(extruder.id());
|
||||
activate_air_filtration &= m_config.support_air_filtration.getBool();
|
||||
|
||||
if (activate_air_filtration) {
|
||||
int complete_print_exhaust_fan_speed = 0;
|
||||
for (const auto& extruder : m_writer.extruders())
|
||||
if (m_config.activate_air_filtration.get_at(extruder.id()))
|
||||
complete_print_exhaust_fan_speed = std::max(complete_print_exhaust_fan_speed, m_config.complete_print_exhaust_fan_speed.get_at(extruder.id()));
|
||||
file.write(m_writer.set_exhaust_fan(complete_print_exhaust_fan_speed, true));
|
||||
}
|
||||
|
||||
print.throw_if_canceled();
|
||||
}
|
||||
|
||||
|
|
@ -2901,6 +2956,7 @@ int GCode::get_bed_temperature(const int extruder_id, const bool is_first_layer,
|
|||
return bed_temp_opt->get_at(extruder_id);
|
||||
}
|
||||
|
||||
|
||||
// Write 1st layer bed temperatures into the G-code.
|
||||
// Only do that if the start G-code does not already contain any M-code controlling an extruder temperature.
|
||||
// M140 - Set Extruder Temperature
|
||||
|
|
@ -3336,10 +3392,45 @@ LayerResult GCode::process_layer(
|
|||
+ "\n";
|
||||
}
|
||||
|
||||
PrinterStructure printer_structure = m_config.printer_structure.value;
|
||||
bool need_insert_timelapse_gcode_for_traditional = false;
|
||||
if (printer_structure == PrinterStructure::psI3 &&
|
||||
!m_spiral_vase &&
|
||||
(!m_wipe_tower || !m_wipe_tower->enable_timelapse_print()) &&
|
||||
print.config().print_sequence == PrintSequence::ByLayer) {
|
||||
need_insert_timelapse_gcode_for_traditional = true;
|
||||
}
|
||||
bool has_insert_timelapse_gcode = false;
|
||||
bool has_wipe_tower = (layer_tools.has_wipe_tower && m_wipe_tower);
|
||||
|
||||
auto insert_timelapse_gcode = [this, print_z, &print]() -> std::string {
|
||||
std::string gcode_res;
|
||||
if (!print.config().time_lapse_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
gcode_res = this->placeholder_parser_process("timelapse_gcode", print.config().time_lapse_gcode.value, m_writer.extruder()->id(), &config) + "\n";
|
||||
}
|
||||
return gcode_res;
|
||||
};
|
||||
|
||||
// BBS: don't use lazy_raise when enable spiral vase
|
||||
gcode += this->change_layer(print_z); // this will increase m_layer_index
|
||||
m_layer = &layer;
|
||||
m_object_layer_over_raft = false;
|
||||
if (printer_structure == PrinterStructure::psI3 && !need_insert_timelapse_gcode_for_traditional && !m_spiral_vase && print.config().print_sequence == PrintSequence::ByLayer) {
|
||||
std::string timepals_gcode = insert_timelapse_gcode();
|
||||
gcode += timepals_gcode;
|
||||
m_writer.set_current_position_clear(false);
|
||||
//BBS: check whether custom gcode changes the z position. Update if changed
|
||||
double temp_z_after_timepals_gcode;
|
||||
if (GCodeProcessor::get_last_z_from_gcode(timepals_gcode, temp_z_after_timepals_gcode)) {
|
||||
Vec3d pos = m_writer.get_position();
|
||||
pos(2) = temp_z_after_timepals_gcode;
|
||||
m_writer.set_position(pos);
|
||||
}
|
||||
}
|
||||
if (! print.config().layer_change_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
|
|
@ -3649,9 +3740,29 @@ LayerResult GCode::process_layer(
|
|||
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
|
||||
for (unsigned int extruder_id : layer_tools.extruders)
|
||||
{
|
||||
gcode += (layer_tools.has_wipe_tower && m_wipe_tower) ?
|
||||
m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back()) :
|
||||
this->set_extruder(extruder_id, print_z);
|
||||
if (has_wipe_tower) {
|
||||
if (!m_wipe_tower->is_empty_wipe_tower_gcode(*this, extruder_id, extruder_id == layer_tools.extruders.back())) {
|
||||
if (need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) {
|
||||
gcode += this->retract(false, false, LiftType::NormalLift);
|
||||
m_writer.add_object_change_labels(gcode);
|
||||
|
||||
std::string timepals_gcode = insert_timelapse_gcode();
|
||||
gcode += timepals_gcode;
|
||||
m_writer.set_current_position_clear(false);
|
||||
//BBS: check whether custom gcode changes the z position. Update if changed
|
||||
double temp_z_after_timepals_gcode;
|
||||
if (GCodeProcessor::get_last_z_from_gcode(timepals_gcode, temp_z_after_timepals_gcode)) {
|
||||
Vec3d pos = m_writer.get_position();
|
||||
pos(2) = temp_z_after_timepals_gcode;
|
||||
m_writer.set_position(pos);
|
||||
}
|
||||
has_insert_timelapse_gcode = true;
|
||||
}
|
||||
gcode += m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back());
|
||||
}
|
||||
} else {
|
||||
gcode += this->set_extruder(extruder_id, print_z);
|
||||
}
|
||||
|
||||
// let analyzer tag generator aware of a role type change
|
||||
if (layer_tools.has_wipe_tower && m_wipe_tower)
|
||||
|
|
@ -3845,11 +3956,11 @@ LayerResult GCode::process_layer(
|
|||
//BBS: for first layer, we always print wall firstly to get better bed adhesive force
|
||||
//This behaviour is same with cura
|
||||
if (is_infill_first && !first_layer) {
|
||||
gcode += this->extrude_infill(print, by_region_specific, false);
|
||||
gcode += this->extrude_infill(print, by_region_specific, false);
|
||||
gcode += this->extrude_perimeters(print, by_region_specific);
|
||||
} else {
|
||||
gcode += this->extrude_perimeters(print, by_region_specific);
|
||||
gcode += this->extrude_infill(print,by_region_specific, false);
|
||||
gcode += this->extrude_infill(print,by_region_specific, false);
|
||||
}
|
||||
// ironing
|
||||
gcode += this->extrude_infill(print,by_region_specific, true);
|
||||
|
|
@ -3900,6 +4011,25 @@ LayerResult GCode::process_layer(
|
|||
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
|
||||
log_memory_info();
|
||||
|
||||
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) {
|
||||
if (m_support_traditional_timelapse)
|
||||
m_support_traditional_timelapse = false;
|
||||
|
||||
gcode += this->retract(false, false, LiftType::NormalLift);
|
||||
m_writer.add_object_change_labels(gcode);
|
||||
|
||||
std::string timepals_gcode = insert_timelapse_gcode();
|
||||
gcode += timepals_gcode;
|
||||
m_writer.set_current_position_clear(false);
|
||||
//BBS: check whether custom gcode changes the z position. Update if changed
|
||||
double temp_z_after_timepals_gcode;
|
||||
if (GCodeProcessor::get_last_z_from_gcode(timepals_gcode, temp_z_after_timepals_gcode)) {
|
||||
Vec3d pos = m_writer.get_position();
|
||||
pos(2) = temp_z_after_timepals_gcode;
|
||||
m_writer.set_position(pos);
|
||||
}
|
||||
}
|
||||
|
||||
result.gcode = std::move(gcode);
|
||||
result.cooling_buffer_flush = object_layer || raft_layer || last_layer;
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -91,6 +91,7 @@ public:
|
|||
std::string prime(GCode &gcodegen);
|
||||
void next_layer() { ++ m_layer_idx; m_tool_change_idx = 0; }
|
||||
std::string tool_change(GCode &gcodegen, int extruder_id, bool finish_layer);
|
||||
bool is_empty_wipe_tower_gcode(GCode &gcodegen, int extruder_id, bool finish_layer);
|
||||
std::string finalize(GCode &gcodegen);
|
||||
std::vector<float> used_filament_length() const;
|
||||
|
||||
|
|
@ -529,6 +530,9 @@ private:
|
|||
// Index of a last object copy extruded.
|
||||
std::pair<const PrintObject*, Point> m_last_obj_copy;
|
||||
|
||||
int m_timelapse_warning_code = 0;
|
||||
bool m_support_traditional_timelapse = true;
|
||||
|
||||
bool m_silent_time_estimator_enabled;
|
||||
|
||||
// Processor
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ const std::vector<std::string> GCodeProcessor::Reserved_Tags = {
|
|||
"_GP_FIRST_LINE_M73_PLACEHOLDER",
|
||||
"_GP_LAST_LINE_M73_PLACEHOLDER",
|
||||
"_GP_ESTIMATED_PRINTING_TIME_PLACEHOLDER",
|
||||
"_GP_TOTAL_LAYER_NUMBER_PLACEHOLDER"
|
||||
"_GP_TOTAL_LAYER_NUMBER_PLACEHOLDER",
|
||||
"_DURING_PRINT_EXHAUST_FAN"
|
||||
};
|
||||
|
||||
const std::vector<std::string> GCodeProcessor::Reserved_Tags_compatible = {
|
||||
|
|
@ -383,6 +384,8 @@ void GCodeProcessor::TimeProcessor::reset()
|
|||
machine_limits = MachineEnvelopeConfig();
|
||||
filament_load_times = 0.0f;
|
||||
filament_unload_times = 0.0f;
|
||||
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
machines[i].reset();
|
||||
}
|
||||
|
|
@ -427,6 +430,14 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
|
|||
return std::string(line_M73);
|
||||
};
|
||||
|
||||
auto format_line_exhaust_fan_control = [](const std::string& mask,int fan_index,int percent) {
|
||||
char line_fan[64] = { 0 };
|
||||
sprintf(line_fan,mask.c_str(),
|
||||
std::to_string(fan_index).c_str(),
|
||||
std::to_string(int((percent/100.0)*255)).c_str());
|
||||
return std::string(line_fan);
|
||||
};
|
||||
|
||||
auto format_time_float = [](float time) {
|
||||
return Slic3r::float_to_string_decimal_point(time, 2);
|
||||
};
|
||||
|
|
@ -542,7 +553,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
|
|||
// add lines M73 to exported gcode
|
||||
auto process_line_move = [
|
||||
// Lambdas, mostly for string formatting, all with an empty capture block.
|
||||
time_in_minutes, format_time_float, format_line_M73_main, format_line_M73_stop_int, format_line_M73_stop_float, time_in_last_minute,
|
||||
time_in_minutes, format_time_float, format_line_M73_main, format_line_M73_stop_int, format_line_M73_stop_float, time_in_last_minute,format_line_exhaust_fan_control,
|
||||
&self = std::as_const(*this),
|
||||
// Caches, to be modified
|
||||
&g1_times_cache_it, &last_exported_main, &last_exported_stop,
|
||||
|
|
@ -561,6 +572,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
|
|||
if (it != machine.g1_times_cache.end() && it->id == g1_lines_counter) {
|
||||
std::pair<int, int> to_export_main = { int(100.0f * it->elapsed_time / machine.time),
|
||||
time_in_minutes(machine.time - it->elapsed_time) };
|
||||
|
||||
if (last_exported_main[i] != to_export_main) {
|
||||
export_line += format_line_M73_main(machine.line_m73_main_mask.c_str(),
|
||||
to_export_main.first, to_export_main.second);
|
||||
|
|
@ -802,6 +814,7 @@ void GCodeProcessorResult::reset() {
|
|||
toolpath_outside = false;
|
||||
//BBS: add label_object_enabled
|
||||
label_object_enabled = false;
|
||||
timelapse_warning_code = 0;
|
||||
printable_height = 0.0f;
|
||||
settings_ids.reset();
|
||||
extruders_count = 0;
|
||||
|
|
@ -829,6 +842,7 @@ void GCodeProcessorResult::reset() {
|
|||
toolpath_outside = false;
|
||||
//BBS: add label_object_enabled
|
||||
label_object_enabled = false;
|
||||
timelapse_warning_code = 0;
|
||||
printable_height = 0.0f;
|
||||
settings_ids.reset();
|
||||
extruders_count = 0;
|
||||
|
|
@ -998,6 +1012,8 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
const ConfigOptionBool* spiral_vase = config.option<ConfigOptionBool>("spiral_mode");
|
||||
if (spiral_vase != nullptr)
|
||||
m_spiral_vase_active = spiral_vase->value;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
||||
|
|
@ -1498,9 +1514,9 @@ void GCodeProcessor::finalize(bool post_process)
|
|||
m_height_compare.output();
|
||||
m_width_compare.output();
|
||||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
if (post_process)
|
||||
if (post_process){
|
||||
m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends, m_layer_id);
|
||||
}
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
m_result.time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - m_start_time).count();
|
||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
|
@ -1817,6 +1833,7 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
|
|||
case '9':
|
||||
switch (cmd[3]) {
|
||||
case '0': { process_M190(line); break; } // Wait bed temperature
|
||||
case '1': { process_M191(line); break; } // Wait chamber temperature
|
||||
default: break;
|
||||
}
|
||||
default:
|
||||
|
|
@ -1935,7 +1952,7 @@ template<typename T>
|
|||
// Legacy conversion, which is costly due to having to make a copy of the string before conversion.
|
||||
try {
|
||||
assert(sv.size() < 1024);
|
||||
assert(sv.data() != nullptr);
|
||||
assert(sv.data() != nullptr);
|
||||
std::string str { sv };
|
||||
size_t read = 0;
|
||||
if constexpr (std::is_same_v<T, int>)
|
||||
|
|
@ -3751,6 +3768,15 @@ void GCodeProcessor::process_M190(const GCodeReader::GCodeLine& line)
|
|||
m_highest_bed_temp = m_highest_bed_temp < (int)new_temp ? (int)new_temp : m_highest_bed_temp;
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_M191(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
float chamber_temp = 0;
|
||||
const float wait_chamber_temp_time = 720.0;
|
||||
// BBS: when chamber_temp>40,caculate time required for heating
|
||||
if (line.has_value('S', chamber_temp) && chamber_temp > 40)
|
||||
simulate_st_synchronize(wait_chamber_temp_time);
|
||||
}
|
||||
|
||||
|
||||
void GCodeProcessor::process_M201(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
|
|
@ -4355,6 +4381,29 @@ void GCodeProcessor::update_slice_warnings()
|
|||
m_result.warnings.push_back(warning);
|
||||
}
|
||||
|
||||
// bbs:HRC checker
|
||||
warning.params.clear();
|
||||
warning.level = 1;
|
||||
if (!m_result.support_traditional_timelapse) {
|
||||
warning.msg = NOT_SUPPORT_TRADITIONAL_TIMELAPSE;
|
||||
warning.error_code = "1000C003";
|
||||
m_result.warnings.push_back(warning);
|
||||
}
|
||||
|
||||
if (m_result.timelapse_warning_code != 0) {
|
||||
if (m_result.timelapse_warning_code & 1) {
|
||||
warning.msg = NOT_GENERATE_TIMELAPSE;
|
||||
warning.error_code = "1001C001";
|
||||
m_result.warnings.push_back(warning);
|
||||
}
|
||||
|
||||
if ((m_result.timelapse_warning_code >> 1) & 1) {
|
||||
warning.msg = NOT_GENERATE_TIMELAPSE;
|
||||
warning.error_code = "1001C002";
|
||||
m_result.warnings.push_back(warning);
|
||||
}
|
||||
}
|
||||
|
||||
m_result.warnings.shrink_to_fit();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ namespace Slic3r {
|
|||
// slice warnings enum strings
|
||||
#define NOZZLE_HRC_CHECKER "the_actual_nozzle_hrc_smaller_than_the_required_nozzle_hrc"
|
||||
#define BED_TEMP_TOO_HIGH_THAN_FILAMENT "bed_temperature_too_high_than_filament"
|
||||
#define NOT_SUPPORT_TRADITIONAL_TIMELAPSE "not_support_traditional_timelapse"
|
||||
#define NOT_GENERATE_TIMELAPSE "not_generate_timelapse"
|
||||
|
||||
enum class EMoveType : unsigned char
|
||||
{
|
||||
|
|
@ -179,6 +181,8 @@ namespace Slic3r {
|
|||
bool toolpath_outside;
|
||||
//BBS: add object_label_enabled
|
||||
bool label_object_enabled;
|
||||
int timelapse_warning_code {0};
|
||||
bool support_traditional_timelapse{true};
|
||||
float printable_height;
|
||||
SettingsIds settings_ids;
|
||||
size_t extruders_count;
|
||||
|
|
@ -212,6 +216,7 @@ namespace Slic3r {
|
|||
bed_exclude_area = other.bed_exclude_area;
|
||||
toolpath_outside = other.toolpath_outside;
|
||||
label_object_enabled = other.label_object_enabled;
|
||||
timelapse_warning_code = other.timelapse_warning_code;
|
||||
printable_height = other.printable_height;
|
||||
settings_ids = other.settings_ids;
|
||||
extruders_count = other.extruders_count;
|
||||
|
|
@ -255,7 +260,8 @@ namespace Slic3r {
|
|||
First_Line_M73_Placeholder,
|
||||
Last_Line_M73_Placeholder,
|
||||
Estimated_Printing_Time_Placeholder,
|
||||
Total_Layer_Number_Placeholder
|
||||
Total_Layer_Number_Placeholder,
|
||||
During_Print_Exhaust_Fan
|
||||
};
|
||||
|
||||
static const std::string& reserved_tag(ETags tag) { return s_IsBBLPrinter ? Reserved_Tags[static_cast<unsigned char>(tag)] : Reserved_Tags_compatible[static_cast<unsigned char>(tag)]; }
|
||||
|
|
@ -357,6 +363,7 @@ namespace Slic3r {
|
|||
float time() const;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
struct TimeMachine
|
||||
{
|
||||
|
|
@ -452,6 +459,7 @@ namespace Slic3r {
|
|||
// Additional load / unload times for a filament exchange sequence.
|
||||
float filament_load_times;
|
||||
float filament_unload_times;
|
||||
|
||||
std::array<TimeMachine, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> machines;
|
||||
|
||||
void reset();
|
||||
|
|
@ -617,7 +625,6 @@ namespace Slic3r {
|
|||
|
||||
private:
|
||||
GCodeReader m_parser;
|
||||
|
||||
EUnits m_units;
|
||||
EPositioningType m_global_positioning_type;
|
||||
EPositioningType m_e_local_positioning_type;
|
||||
|
|
@ -711,6 +718,7 @@ namespace Slic3r {
|
|||
void reset();
|
||||
|
||||
const GCodeProcessorResult& get_result() const { return m_result; }
|
||||
GCodeProcessorResult& result() { return m_result; }
|
||||
GCodeProcessorResult&& extract_result() { return std::move(m_result); }
|
||||
|
||||
// Load a G-code into a stand-alone G-code viewer.
|
||||
|
|
@ -829,6 +837,9 @@ namespace Slic3r {
|
|||
//BBS: wait bed temperature
|
||||
void process_M190(const GCodeReader::GCodeLine& line);
|
||||
|
||||
//BBS: wait chamber temperature
|
||||
void process_M191(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Set max printing acceleration
|
||||
void process_M201(const GCodeReader::GCodeLine& line);
|
||||
|
||||
|
|
|
|||
|
|
@ -157,6 +157,25 @@ std::string GCodeWriter::set_bed_temperature(int temperature, bool wait)
|
|||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string GCodeWriter::set_chamber_temperature(int temperature, bool wait)
|
||||
{
|
||||
std::string code, comment;
|
||||
std::ostringstream gcode;
|
||||
|
||||
if (wait)
|
||||
{
|
||||
gcode<<"M106 P2 S255 \n";
|
||||
gcode<<"M191 S"<<std::to_string(temperature)<<" ;"<<"set chamber_temperature and wait for it to be reached\n";
|
||||
gcode<<"M106 P2 S0 \n";
|
||||
}
|
||||
else {
|
||||
code = "M141";
|
||||
comment = "set chamber_temperature";
|
||||
gcode << code << " S" << temperature << ";" << comment << "\n";
|
||||
}
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
// copied from PrusaSlicer
|
||||
std::string GCodeWriter::set_acceleration_internal(Acceleration type, unsigned int acceleration)
|
||||
{
|
||||
|
|
@ -784,6 +803,16 @@ std::string GCodeWriter::set_additional_fan(unsigned int speed)
|
|||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string GCodeWriter::set_exhaust_fan( int speed,bool add_eol)
|
||||
{
|
||||
std::ostringstream gcode;
|
||||
gcode << "M106" << " P3" << " S" << (int)(speed / 100.0 * 255);
|
||||
|
||||
if(add_eol)
|
||||
gcode << "\n";
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
void GCodeWriter::add_object_start_labels(std::string& gcode)
|
||||
{
|
||||
if (!m_gcode_label_objects_start.empty()) {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public:
|
|||
std::string postamble() const;
|
||||
std::string set_temperature(unsigned int temperature, bool wait = false, int tool = -1) const;
|
||||
std::string set_bed_temperature(int temperature, bool wait = false);
|
||||
std::string set_chamber_temperature(int temperature, bool wait = false);
|
||||
std::string set_print_acceleration(unsigned int acceleration) { return set_acceleration_internal(Acceleration::Print, acceleration); }
|
||||
std::string set_travel_acceleration(unsigned int acceleration) { return set_acceleration_internal(Acceleration::Travel, acceleration); }
|
||||
std::string set_jerk_xy(double jerk);
|
||||
|
|
@ -90,6 +91,7 @@ public:
|
|||
std::string set_fan(unsigned int speed) const;
|
||||
//BBS: set additional fan speed for BBS machine only
|
||||
static std::string set_additional_fan(unsigned int speed);
|
||||
static std::string set_exhaust_fan(int speed,bool add_eol);
|
||||
//BBS
|
||||
void set_object_start_str(std::string start_string) { m_gcode_label_objects_start = start_string; }
|
||||
bool is_object_start_str_empty() { return m_gcode_label_objects_start.empty(); }
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@
|
|||
// Transtltion
|
||||
#include "I18N.hpp"
|
||||
|
||||
// ModelIO support
|
||||
#ifdef __APPLE__
|
||||
#include "Format/ModelIO.hpp"
|
||||
#endif
|
||||
|
||||
#define _L(s) Slic3r::I18N::translate(s)
|
||||
|
||||
namespace Slic3r {
|
||||
|
|
@ -204,6 +209,18 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
|
|||
//FIXME options & LoadStrategy::CheckVersion ?
|
||||
//BBS: is_xxx is used for is_bbs_3mf when load 3mf
|
||||
result = load_bbs_3mf(input_file.c_str(), config, config_substitutions, &model, plate_data, project_presets, is_xxx, file_version, proFn, options, project, plate_id);
|
||||
#ifdef __APPLE__
|
||||
else if (boost::algorithm::iends_with(input_file, ".usd") || boost::algorithm::iends_with(input_file, ".usda") ||
|
||||
boost::algorithm::iends_with(input_file, ".usdc") || boost::algorithm::iends_with(input_file, ".usdz") ||
|
||||
boost::algorithm::iends_with(input_file, ".abc") || boost::algorithm::iends_with(input_file, ".ply")) {
|
||||
std::string temp_stl = make_temp_stl_with_modelio(input_file);
|
||||
if (temp_stl.empty()) {
|
||||
throw Slic3r::RuntimeError("Failed to convert asset to STL via ModelIO.");
|
||||
}
|
||||
result = load_stl(temp_stl.c_str(), &model);
|
||||
delete_temp_file(temp_stl);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
throw Slic3r::RuntimeError(_L("Unknown file format. Input file must have .stl, .obj, .amf(.xml) extension."));
|
||||
|
||||
|
|
@ -2048,6 +2065,9 @@ static void reset_instance_transformation(ModelObject* object, size_t src_instan
|
|||
const Transform3d &assemble_matrix = obj_instance->get_assemble_transformation().get_matrix();
|
||||
const Transform3d &instance_inverse_matrix = instance_transformation_copy.get_matrix().inverse();
|
||||
Transform3d new_instance_inverse_matrix = instance_inverse_matrix * obj_instance->get_transformation().get_matrix(true).inverse();
|
||||
if (place_on_cut) { // reset the rotation of cut plane
|
||||
new_instance_inverse_matrix = new_instance_inverse_matrix * Transformation(cut_matrix).get_matrix(true, false, true, true).inverse();
|
||||
}
|
||||
Transform3d new_assemble_transform = assemble_matrix * new_instance_inverse_matrix;
|
||||
obj_instance->set_assemble_from_transform(new_assemble_transform);
|
||||
}
|
||||
|
|
@ -2097,7 +2117,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, std::array<Vec3d, 4> plane_poi
|
|||
// Displacement (in instance coordinates) to be applied to place the upper parts
|
||||
Vec3d local_displace = Vec3d::Zero();
|
||||
Vec3d local_dowels_displace = Vec3d::Zero();
|
||||
|
||||
|
||||
for (ModelVolume *volume : volumes) {
|
||||
const auto volume_matrix = volume->get_matrix();
|
||||
|
||||
|
|
@ -2122,7 +2142,7 @@ ModelObjectPtrs ModelObject::cut(size_t instance, std::array<Vec3d, 4> plane_poi
|
|||
}
|
||||
|
||||
ModelObjectPtrs res;
|
||||
|
||||
|
||||
if (attributes.has(ModelObjectCutAttribute::CutToParts) && !upper->volumes.empty()) {
|
||||
reset_instance_transformation(upper, instance, cut_matrix);
|
||||
res.push_back(upper);
|
||||
|
|
@ -2356,7 +2376,7 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
|
|||
{
|
||||
Vec3d shift = model_instance->get_transformation().get_matrix(true) * new_vol->get_offset();
|
||||
model_instance->set_offset(model_instance->get_offset() + shift);
|
||||
|
||||
|
||||
//BBS: add assemble_view related logic
|
||||
Geometry::Transformation instance_transformation_copy = model_instance->get_transformation();
|
||||
instance_transformation_copy.set_offset(-new_vol->get_offset());
|
||||
|
|
@ -2365,6 +2385,7 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
|
|||
Transform3d new_instance_inverse_matrix = instance_inverse_matrix * model_instance->get_transformation().get_matrix(true).inverse();
|
||||
Transform3d new_assemble_transform = assemble_matrix * new_instance_inverse_matrix;
|
||||
model_instance->set_assemble_from_transform(new_assemble_transform);
|
||||
model_instance->set_offset_to_assembly(new_vol->get_offset());
|
||||
}
|
||||
|
||||
new_vol->set_offset(Vec3d::Zero());
|
||||
|
|
@ -3234,6 +3255,91 @@ void ModelInstance::transform_polygon(Polygon* polygon) const
|
|||
}
|
||||
|
||||
//BBS
|
||||
// BBS set print speed table and find maximum speed
|
||||
void Model::setPrintSpeedTable(const DynamicPrintConfig& config, const PrintConfig& print_config) {
|
||||
//Slic3r::DynamicPrintConfig config = wxGetApp().preset_bundle->full_config();
|
||||
printSpeedMap.maxSpeed = 0;
|
||||
if (config.has("inner_wall_speed")) {
|
||||
printSpeedMap.perimeterSpeed = config.opt_float("inner_wall_speed");
|
||||
if (printSpeedMap.perimeterSpeed > printSpeedMap.maxSpeed)
|
||||
printSpeedMap.maxSpeed = printSpeedMap.perimeterSpeed;
|
||||
}
|
||||
if (config.has("outer_wall_speed")) {
|
||||
printSpeedMap.externalPerimeterSpeed = config.opt_float("outer_wall_speed");
|
||||
printSpeedMap.maxSpeed = std::max(printSpeedMap.maxSpeed, printSpeedMap.externalPerimeterSpeed);
|
||||
}
|
||||
if (config.has("sparse_infill_speed")) {
|
||||
printSpeedMap.infillSpeed = config.opt_float("sparse_infill_speed");
|
||||
if (printSpeedMap.infillSpeed > printSpeedMap.maxSpeed)
|
||||
printSpeedMap.maxSpeed = printSpeedMap.infillSpeed;
|
||||
}
|
||||
if (config.has("internal_solid_infill_speed")) {
|
||||
printSpeedMap.solidInfillSpeed = config.opt_float("internal_solid_infill_speed");
|
||||
if (printSpeedMap.solidInfillSpeed > printSpeedMap.maxSpeed)
|
||||
printSpeedMap.maxSpeed = printSpeedMap.solidInfillSpeed;
|
||||
}
|
||||
if (config.has("top_surface_speed")) {
|
||||
printSpeedMap.topSolidInfillSpeed = config.opt_float("top_surface_speed");
|
||||
if (printSpeedMap.topSolidInfillSpeed > printSpeedMap.maxSpeed)
|
||||
printSpeedMap.maxSpeed = printSpeedMap.topSolidInfillSpeed;
|
||||
}
|
||||
if (config.has("support_speed")) {
|
||||
printSpeedMap.supportSpeed = config.opt_float("support_speed");
|
||||
|
||||
if (printSpeedMap.supportSpeed > printSpeedMap.maxSpeed)
|
||||
printSpeedMap.maxSpeed = printSpeedMap.supportSpeed;
|
||||
}
|
||||
|
||||
|
||||
//auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
|
||||
//auto print_config = print.config();
|
||||
//printSpeedMap.bed_poly.points = get_bed_shape(*(wxGetApp().plater()->config()));
|
||||
printSpeedMap.bed_poly.points = get_bed_shape(config);
|
||||
Pointfs excluse_area_points = print_config.bed_exclude_area.values;
|
||||
Polygons exclude_polys;
|
||||
Polygon exclude_poly;
|
||||
for (int i = 0; i < excluse_area_points.size(); i++) {
|
||||
auto pt = excluse_area_points[i];
|
||||
exclude_poly.points.emplace_back(scale_(pt.x()), scale_(pt.y()));
|
||||
if (i % 4 == 3) { // exclude areas are always rectangle
|
||||
exclude_polys.push_back(exclude_poly);
|
||||
exclude_poly.points.clear();
|
||||
}
|
||||
}
|
||||
printSpeedMap.bed_poly = diff({ printSpeedMap.bed_poly }, exclude_polys)[0];
|
||||
}
|
||||
|
||||
// find temperature of heatend and bed and matierial of an given extruder
|
||||
void Model::setExtruderParams(const DynamicPrintConfig& config, int extruders_count) {
|
||||
extruderParamsMap.clear();
|
||||
//Slic3r::DynamicPrintConfig config = wxGetApp().preset_bundle->full_config();
|
||||
// BBS
|
||||
//int numExtruders = wxGetApp().preset_bundle->filament_presets.size();
|
||||
for (unsigned int i = 0; i != extruders_count; ++i) {
|
||||
std::string matName = "";
|
||||
// BBS
|
||||
int bedTemp = 35;
|
||||
double endTemp = 0.f;
|
||||
if (config.has("filament_type")) {
|
||||
matName = config.opt_string("filament_type", i);
|
||||
}
|
||||
if (config.has("nozzle_temperature")) {
|
||||
endTemp = config.opt_int("nozzle_temperature", i);
|
||||
}
|
||||
|
||||
// FIXME: curr_bed_type is now a plate config rather than a global config.
|
||||
// Currently bed temp is not used for brim generation, so just comment it for now.
|
||||
#if 0
|
||||
if (config.has("curr_bed_type")) {
|
||||
BedType curr_bed_type = config.opt_enum<BedType>("curr_bed_type");
|
||||
bedTemp = config.opt_int(get_bed_temp_key(curr_bed_type), i);
|
||||
}
|
||||
#endif
|
||||
if (i == 0) extruderParamsMap.insert({ i,{matName, bedTemp, endTemp} });
|
||||
extruderParamsMap.insert({ i + 1,{matName, bedTemp, endTemp} });
|
||||
}
|
||||
}
|
||||
|
||||
// update the maxSpeed of an object if it is different from the global configuration
|
||||
double Model::findMaxSpeed(const ModelObject* object) {
|
||||
auto objectKeys = object->config.keys();
|
||||
|
|
|
|||
|
|
@ -1561,6 +1561,9 @@ public:
|
|||
static double getThermalLength(const ModelVolume* modelVolumePtr);
|
||||
static double getThermalLength(const std::vector<ModelVolume*> modelVolumePtrs);
|
||||
static Polygon getBedPolygon() { return Model::printSpeedMap.bed_poly; }
|
||||
//BBS static functions that update extruder params and speed table
|
||||
static void setPrintSpeedTable(const DynamicPrintConfig& config, const PrintConfig& print_config);
|
||||
static void setExtruderParams(const DynamicPrintConfig& config, int extruders_count);
|
||||
|
||||
// BBS: backup
|
||||
static Model read_from_archive(
|
||||
|
|
|
|||
|
|
@ -145,24 +145,23 @@ ArrangePolygon get_instance_arrange_poly(ModelInstance* instance, const Slic3r::
|
|||
|
||||
// get brim width
|
||||
auto obj = instance->get_object();
|
||||
#if 0
|
||||
ap.brim_width = instance->get_auto_brim_width();
|
||||
auto brim_type_ptr = obj->get_config_value<ConfigOptionEnum<BrimType>>(config, "brim_type");
|
||||
if (brim_type_ptr) {
|
||||
auto brim_type = brim_type_ptr->getInt();
|
||||
if (brim_type == btOuterOnly)
|
||||
ap.brim_width = obj->get_config_value<ConfigOptionFloat>(config, "brim_width")->getFloat();
|
||||
else if (brim_type == btNoBrim)
|
||||
ap.brim_width = 0;
|
||||
}
|
||||
#else
|
||||
ap.brim_width = 0;
|
||||
|
||||
ap.brim_width = 1.0;
|
||||
// For by-layer printing, need to shrink bed a little, so the support won't go outside bed.
|
||||
// We set it to 5mm because that's how much a normal support will grow by default.
|
||||
// normal support 5mm, other support 22mm, no support 0mm
|
||||
auto supp_type_ptr = obj->get_config_value<ConfigOptionBool>(config, "enable_support");
|
||||
if (supp_type_ptr && supp_type_ptr->getBool())
|
||||
ap.brim_width = 5.0;
|
||||
#endif
|
||||
auto support_type_ptr = obj->get_config_value<ConfigOptionEnum<SupportType>>(config, "support_type");
|
||||
auto support_type = support_type_ptr->value;
|
||||
auto enable_support = supp_type_ptr->getBool();
|
||||
int support_int = support_type_ptr->getInt();
|
||||
|
||||
if (enable_support && (support_type == stNormalAuto || support_type == stNormal))
|
||||
ap.brim_width = 6.0;
|
||||
else if (enable_support) {
|
||||
ap.brim_width = 24.0; // 2*MAX_BRANCH_RADIUS_FIRST_LAYER
|
||||
ap.has_tree_support = true;
|
||||
}
|
||||
|
||||
ap.height = obj->bounding_box().size().z();
|
||||
ap.name = obj->name;
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ public:
|
|||
|
||||
area_cumulation_accurate(face_normals, normals_quantize, areas, 10);
|
||||
|
||||
area_cumulation_accurate(face_normals_hull, normals_hull_quantize, areas_hull, 10);
|
||||
area_cumulation_accurate(face_normals_hull, normals_hull_quantize, areas_hull, 14);
|
||||
|
||||
add_supplements();
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,87 @@ bool decode_png(IStream &in_buf, ImageGreyscale &out_img)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool decode_colored_png(IStream &in_buf, ImageColorscale &out_img)
|
||||
{
|
||||
static const constexpr int PNG_SIG_BYTES = 8;
|
||||
|
||||
std::vector<png_byte> sig(PNG_SIG_BYTES, 0);
|
||||
in_buf.read(sig.data(), PNG_SIG_BYTES);
|
||||
if (!png_check_sig(sig.data(), PNG_SIG_BYTES)) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("decode_colored_png: png_check_sig failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
PNGDescr dsc;
|
||||
dsc.png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr,
|
||||
nullptr);
|
||||
|
||||
if(!dsc.png) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("decode_colored_png: png_create_read_struct failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
dsc.info = png_create_info_struct(dsc.png);
|
||||
if(!dsc.info) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("decode_colored_png: png_create_info_struct failed");
|
||||
png_destroy_read_struct(&dsc.png, &dsc.info, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
png_set_read_fn(dsc.png, static_cast<void *>(&in_buf), png_read_callback);
|
||||
|
||||
// Tell that we have already read the first bytes to check the signature
|
||||
png_set_sig_bytes(dsc.png, PNG_SIG_BYTES);
|
||||
|
||||
png_read_info(dsc.png, dsc.info);
|
||||
|
||||
out_img.cols = png_get_image_width(dsc.png, dsc.info);
|
||||
out_img.rows = png_get_image_height(dsc.png, dsc.info);
|
||||
size_t color_type = png_get_color_type(dsc.png, dsc.info);
|
||||
size_t bit_depth = png_get_bit_depth(dsc.png, dsc.info);
|
||||
unsigned long rowbytes = png_get_rowbytes(dsc.png, dsc.info);
|
||||
|
||||
switch(color_type)
|
||||
{
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
out_img.bytes_per_pixel = 3;
|
||||
break;
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
out_img.bytes_per_pixel = 4;
|
||||
break;
|
||||
default: //not supported currently
|
||||
png_destroy_read_struct(&dsc.png, &dsc.info, NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("png's cols %1%, rows %2%, color_type %3%, bit_depth %4%, bytes_per_pixel %5%, rowbytes %6%")%out_img.cols %out_img.rows %color_type %bit_depth %out_img.bytes_per_pixel %rowbytes;
|
||||
out_img.buf.resize(out_img.rows * rowbytes);
|
||||
|
||||
int filter_type = png_get_filter_type(dsc.png, dsc.info);
|
||||
int compression_type = png_get_compression_type(dsc.png, dsc.info);
|
||||
int interlace_type = png_get_interlace_type(dsc.png, dsc.info);
|
||||
BOOST_LOG_TRIVIAL(info) << boost::format("filter_type %1%, compression_type %2%, interlace_type %3%, rowbytes %4%")%filter_type %compression_type %interlace_type %rowbytes;
|
||||
|
||||
auto readbuf = static_cast<png_bytep>(out_img.buf.data());
|
||||
for (size_t r = out_img.rows; r > 0; r--)
|
||||
{
|
||||
png_read_row(dsc.png, readbuf + (r - 1) * rowbytes, nullptr);
|
||||
}
|
||||
|
||||
png_read_end(dsc.png, dsc.info);
|
||||
png_destroy_read_struct(&dsc.png, &dsc.info, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool decode_colored_png(const ReadBuf &in_buf, ImageColorscale &out_img)
|
||||
{
|
||||
struct ReadBufStream stream{in_buf};
|
||||
|
||||
return decode_colored_png(stream, out_img);
|
||||
}
|
||||
|
||||
|
||||
// Down to earth function to store a packed RGB image to file. Mostly useful for debugging purposes.
|
||||
// Based on https://www.lemoda.net/c/write-png/
|
||||
// png_color_type is PNG_COLOR_TYPE_RGB or PNG_COLOR_TYPE_GRAY
|
||||
|
|
@ -112,7 +193,7 @@ static bool write_rgb_or_gray_to_file(const char *file_name_utf8, size_t width,
|
|||
png_structp png_ptr = nullptr;
|
||||
png_infop info_ptr = nullptr;
|
||||
png_byte **row_pointers = nullptr;
|
||||
|
||||
|
||||
FILE *fp = boost::nowide::fopen(file_name_utf8, "wb");
|
||||
if (! fp) {
|
||||
BOOST_LOG_TRIVIAL(error) << "write_png_file: File could not be opened for writing: " << file_name_utf8;
|
||||
|
|
|
|||
|
|
@ -23,11 +23,19 @@ template<class PxT> struct Image {
|
|||
};
|
||||
|
||||
using ImageGreyscale = Image<uint8_t>;
|
||||
struct ImageColorscale:Image<unsigned char>
|
||||
{
|
||||
int bytes_per_pixel;
|
||||
};
|
||||
|
||||
|
||||
// Only decodes true 8 bit grayscale png images. Returns false for other formats
|
||||
// TODO (if needed): implement transformation of rgb images into grayscale...
|
||||
bool decode_png(IStream &stream, ImageGreyscale &out_img);
|
||||
|
||||
//BBS: decode png for other format
|
||||
bool decode_colored_png(IStream &in_buf, ImageColorscale &out_img);
|
||||
|
||||
// TODO (if needed)
|
||||
// struct RGB { uint8_t r, g, b; };
|
||||
// using ImageRGB = Image<RGB>;
|
||||
|
|
@ -39,30 +47,36 @@ struct ReadBuf { const void *buf = nullptr; const size_t sz = 0; };
|
|||
|
||||
bool is_png(const ReadBuf &pngbuf);
|
||||
|
||||
struct ReadBufStream: public IStream {
|
||||
const ReadBuf &rbuf_ref;
|
||||
size_t pos = 0;
|
||||
|
||||
explicit ReadBufStream(const ReadBuf &buf): rbuf_ref{buf} {}
|
||||
|
||||
size_t read(std::uint8_t *outp, size_t amount) override
|
||||
{
|
||||
if (amount > rbuf_ref.sz - pos) return 0;
|
||||
|
||||
auto buf = static_cast<const std::uint8_t *>(rbuf_ref.buf);
|
||||
std::copy(buf + pos, buf + (pos + amount), outp);
|
||||
pos += amount;
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
bool is_ok() const override { return pos < rbuf_ref.sz; }
|
||||
};
|
||||
|
||||
template<class Img> bool decode_png(const ReadBuf &in_buf, Img &out_img)
|
||||
{
|
||||
struct ReadBufStream: public IStream {
|
||||
const ReadBuf &rbuf_ref; size_t pos = 0;
|
||||
|
||||
explicit ReadBufStream(const ReadBuf &buf): rbuf_ref{buf} {}
|
||||
|
||||
size_t read(std::uint8_t *outp, size_t amount) override
|
||||
{
|
||||
if (amount > rbuf_ref.sz - pos) return 0;
|
||||
|
||||
auto buf = static_cast<const std::uint8_t *>(rbuf_ref.buf);
|
||||
std::copy(buf + pos, buf + (pos + amount), outp);
|
||||
pos += amount;
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
bool is_ok() const override { return pos < rbuf_ref.sz; }
|
||||
} stream{in_buf};
|
||||
struct ReadBufStream stream{in_buf};
|
||||
|
||||
return decode_png(stream, out_img);
|
||||
}
|
||||
|
||||
bool decode_colored_png(const ReadBuf &in_buf, ImageColorscale &out_img);
|
||||
|
||||
|
||||
// TODO: std::istream of FILE* could be similarly adapted in case its needed...
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -781,6 +781,8 @@ static std::vector<std::string> s_Preset_filament_options {
|
|||
"temperature_vitrification", "reduce_fan_stop_start_freq", "slow_down_for_layer_cooling", "fan_min_speed",
|
||||
"fan_max_speed", "enable_overhang_bridge_fan", "overhang_fan_speed", "overhang_fan_threshold", "close_fan_the_first_x_layers", "full_fan_speed_layer", "fan_cooling_layer_time", "slow_down_layer_time", "slow_down_min_speed",
|
||||
"filament_start_gcode", "filament_end_gcode",
|
||||
//exhaust fan control
|
||||
"activate_air_filtration","during_print_exhaust_fan_speed","complete_print_exhaust_fan_speed",
|
||||
// Retract overrides
|
||||
"filament_retraction_length", "filament_z_hop", "filament_z_hop_types", "filament_retract_lift_above", "filament_retract_lift_below", "filament_retract_lift_enforce", "filament_retraction_speed", "filament_deretraction_speed", "filament_retract_restart_extra", "filament_retraction_minimum_travel",
|
||||
"filament_retract_when_changing_layer", "filament_wipe", "filament_retract_before_wipe",
|
||||
|
|
@ -788,7 +790,7 @@ static std::vector<std::string> s_Preset_filament_options {
|
|||
"filament_vendor", "compatible_prints", "compatible_prints_condition", "compatible_printers", "compatible_printers_condition", "inherits",
|
||||
//BBS
|
||||
"filament_wipe_distance", "additional_cooling_fan_speed",
|
||||
"bed_temperature_difference", "nozzle_temperature_range_low", "nozzle_temperature_range_high",
|
||||
"nozzle_temperature_range_low", "nozzle_temperature_range_high",
|
||||
//SoftFever
|
||||
"enable_pressure_advance", "pressure_advance","chamber_temperature", "filament_shrink", "support_material_interface_fan_speed", "filament_notes" /*,"filament_seam_gap"*/,
|
||||
"filament_loading_speed", "filament_loading_speed_start", "filament_load_time",
|
||||
|
|
@ -809,13 +811,13 @@ static std::vector<std::string> s_Preset_printer_options {
|
|||
"printer_technology",
|
||||
"printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
|
||||
"fan_kickstart", "fan_speedup_time", "fan_speedup_overhangs",
|
||||
"single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "change_filament_gcode",
|
||||
"single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "time_lapse_gcode", "change_filament_gcode",
|
||||
"printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
|
||||
"default_print_profile", "inherits",
|
||||
"silent_mode",
|
||||
// BBS
|
||||
"scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time","time_cost", "machine_pause_gcode", "template_custom_gcode",
|
||||
"nozzle_type", "nozzle_hrc","auxiliary_fan", "nozzle_volume","upward_compatible_machine", "z_hop_types", "retract_lift_enforce",
|
||||
"nozzle_type", "nozzle_hrc","auxiliary_fan", "nozzle_volume","upward_compatible_machine", "z_hop_types", "retract_lift_enforce","support_chamber_temp_control","support_air_filtration","printer_structure",
|
||||
//SoftFever
|
||||
"host_type", "print_host", "printhost_apikey",
|
||||
"print_host_webui",
|
||||
|
|
|
|||
|
|
@ -2828,6 +2828,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||
std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_vendor_configs_from_json(
|
||||
const std::string &path, const std::string &vendor_name, LoadConfigBundleAttributes flags, ForwardCompatibilitySubstitutionRule compatibility_rule)
|
||||
{
|
||||
CNumericLocalesSetter locales_setter;
|
||||
// Enable substitutions for user config bundle, throw an exception when loading a system profile.
|
||||
ConfigSubstitutionContext substitution_context { compatibility_rule };
|
||||
PresetsConfigSubstitutions substitutions;
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"printable_area",
|
||||
//BBS: add bed_exclude_area
|
||||
"bed_exclude_area",
|
||||
"thumbnail_size",
|
||||
"before_layer_change_gcode",
|
||||
"enable_pressure_advance",
|
||||
"pressure_advance",
|
||||
|
|
@ -146,6 +147,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"textured_plate_temp_initial_layer",
|
||||
"gcode_add_line_number",
|
||||
"layer_change_gcode",
|
||||
"time_lapse_gcode",
|
||||
"fan_min_speed",
|
||||
"fan_max_speed",
|
||||
"printable_height",
|
||||
|
|
@ -194,7 +196,10 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"gcode_label_objects",
|
||||
"exclude_object",
|
||||
"support_material_interface_fan_speed",
|
||||
"single_extruder_multi_material_priming"
|
||||
"single_extruder_multi_material_priming",
|
||||
"activate_air_filtration",
|
||||
"during_print_exhaust_fan_speed",
|
||||
"complete_print_exhaust_fan_speed"
|
||||
};
|
||||
|
||||
static std::unordered_set<std::string> steps_ignore;
|
||||
|
|
|
|||
|
|
@ -110,11 +110,11 @@ void PrintBase::set_status(int percent, const std::string &message, unsigned in
|
|||
BOOST_LOG_TRIVIAL(debug) <<boost::format("Percent %1%: %2%\n")%percent %message.c_str();
|
||||
}
|
||||
|
||||
void PrintBase::status_update_warnings(int step, PrintStateBase::WarningLevel /* warning_level */,
|
||||
void PrintBase::status_update_warnings(int step, PrintStateBase::WarningLevel warning_level,
|
||||
const std::string &message, const PrintObjectBase* print_object, PrintStateBase::SlicingNotificationType message_id)
|
||||
{
|
||||
if (this->m_status_callback) {
|
||||
auto status = print_object ? SlicingStatus(*print_object, step, message, message_id) : SlicingStatus(*this, step, message, message_id);
|
||||
auto status = print_object ? SlicingStatus(*print_object, step, message, message_id, warning_level) : SlicingStatus(*this, step, message, message_id, warning_level);
|
||||
m_status_callback(status);
|
||||
}
|
||||
else if (! message.empty())
|
||||
|
|
@ -122,12 +122,12 @@ void PrintBase::status_update_warnings(int step, PrintStateBase::WarningLevel /*
|
|||
}
|
||||
|
||||
//BBS: add PrintObject id into slicing status
|
||||
void PrintBase::status_update_warnings(int step, PrintStateBase::WarningLevel /* warning_level */,
|
||||
void PrintBase::status_update_warnings(int step, PrintStateBase::WarningLevel warning_level,
|
||||
const std::string& message, PrintObjectBase &object, PrintStateBase::SlicingNotificationType message_id)
|
||||
{
|
||||
//BBS: add object it into slicing status
|
||||
if (this->m_status_callback) {
|
||||
m_status_callback(SlicingStatus(object, step, message, message_id));
|
||||
m_status_callback(SlicingStatus(object, step, message, message_id, warning_level));
|
||||
}
|
||||
else if (!message.empty())
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", PrintObject warning: %1%\n")% message.c_str();
|
||||
|
|
|
|||
|
|
@ -431,18 +431,18 @@ public:
|
|||
|
||||
struct SlicingStatus {
|
||||
SlicingStatus(int percent, const std::string &text, unsigned int flags = 0, int warning_step = -1,
|
||||
PrintStateBase::SlicingNotificationType msg_type = PrintStateBase::SlicingDefaultNotification) :
|
||||
percent(percent), text(text), flags(flags), warning_step(warning_step), message_type(msg_type)
|
||||
PrintStateBase::SlicingNotificationType msg_type = PrintStateBase::SlicingDefaultNotification, PrintStateBase::WarningLevel warning_level = PrintStateBase::WarningLevel::NON_CRITICAL) :
|
||||
percent(percent), text(text), flags(flags), warning_step(warning_step), message_type(msg_type), warning_level(warning_level)
|
||||
{
|
||||
}
|
||||
SlicingStatus(const PrintBase &print, int warning_step, const std::string& text,
|
||||
PrintStateBase::SlicingNotificationType msg_type = PrintStateBase::SlicingDefaultNotification) :
|
||||
flags(UPDATE_PRINT_STEP_WARNINGS), warning_object_id(print.id()), text(text), warning_step(warning_step), message_type(msg_type)
|
||||
PrintStateBase::SlicingNotificationType msg_type = PrintStateBase::SlicingDefaultNotification, PrintStateBase::WarningLevel warning_level = PrintStateBase::WarningLevel::NON_CRITICAL) :
|
||||
flags(UPDATE_PRINT_STEP_WARNINGS), warning_object_id(print.id()), text(text), warning_step(warning_step), message_type(msg_type), warning_level(warning_level)
|
||||
{
|
||||
}
|
||||
SlicingStatus(const PrintObjectBase &print_object, int warning_step, const std::string& text,
|
||||
PrintStateBase::SlicingNotificationType msg_type = PrintStateBase::SlicingDefaultNotification) :
|
||||
flags(UPDATE_PRINT_OBJECT_STEP_WARNINGS), warning_object_id(print_object.id()), text(text), warning_step(warning_step), message_type(msg_type)
|
||||
PrintStateBase::SlicingNotificationType msg_type = PrintStateBase::SlicingDefaultNotification, PrintStateBase::WarningLevel warning_level = PrintStateBase::WarningLevel::NON_CRITICAL) :
|
||||
flags(UPDATE_PRINT_OBJECT_STEP_WARNINGS), warning_object_id(print_object.id()), text(text), warning_step(warning_step), message_type(msg_type), warning_level(warning_level)
|
||||
{
|
||||
}
|
||||
int percent { -1 };
|
||||
|
|
@ -466,6 +466,7 @@ public:
|
|||
int warning_step { -1 };
|
||||
|
||||
PrintStateBase::SlicingNotificationType message_type {PrintStateBase::SlicingDefaultNotification};
|
||||
PrintStateBase::WarningLevel warning_level {PrintStateBase::WarningLevel::NON_CRITICAL};
|
||||
};
|
||||
typedef std::function<void(const SlicingStatus&)> status_callback_type;
|
||||
// Default status console print out in the form of percent => message.
|
||||
|
|
@ -532,7 +533,7 @@ protected:
|
|||
void status_update_warnings(int step, PrintStateBase::WarningLevel warning_level,
|
||||
const std::string &message, const PrintObjectBase* print_object = nullptr, PrintStateBase::SlicingNotificationType message_id = PrintStateBase::SlicingDefaultNotification);
|
||||
//BBS: add api to update printobject's warnings
|
||||
void status_update_warnings(int step, PrintStateBase::WarningLevel /* warning_level */,
|
||||
void status_update_warnings(int step, PrintStateBase::WarningLevel warning_level,
|
||||
const std::string& message, PrintObjectBase &object, PrintStateBase::SlicingNotificationType message_id = PrintStateBase::SlicingDefaultNotification);
|
||||
|
||||
// If the background processing stop was requested, throw CanceledException.
|
||||
|
|
|
|||
|
|
@ -296,6 +296,15 @@ static t_config_enum_values s_keys_map_NozzleType {
|
|||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(NozzleType)
|
||||
|
||||
static t_config_enum_values s_keys_map_PrinterStructure {
|
||||
{"undefine", int(PrinterStructure::psUndefine)},
|
||||
{"corexy", int(PrinterStructure::psCoreXY)},
|
||||
{"i3", int(PrinterStructure::psI3)},
|
||||
{"hbot", int(PrinterStructure::psHbot)},
|
||||
{"delta", int(PrinterStructure::psDelta)}
|
||||
};
|
||||
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PrinterStructure)
|
||||
|
||||
static t_config_enum_values s_keys_map_PerimeterGeneratorType{
|
||||
{ "classic", int(PerimeterGeneratorType::Classic) },
|
||||
{ "arachne", int(PerimeterGeneratorType::Arachne) }
|
||||
|
|
@ -492,7 +501,7 @@ void PrintConfigDef::init_common_params()
|
|||
def->mode = comAdvanced;
|
||||
def->cli = ConfigOptionDef::nocli;
|
||||
def->set_default_value(new ConfigOptionEnum<AuthorizationType>(atKeyPassword));
|
||||
|
||||
|
||||
// temporary workaround for compatibility with older Slicer
|
||||
{
|
||||
def = this->add("preset_name", coString);
|
||||
|
|
@ -617,7 +626,7 @@ void PrintConfigDef::init_fff_params()
|
|||
def->enum_values.emplace_back("Textured PEI Plate");
|
||||
def->enum_labels.emplace_back(L("Cool Plate"));
|
||||
def->enum_labels.emplace_back(L("Engineering Plate"));
|
||||
def->enum_labels.emplace_back(L("High Temp Plate"));
|
||||
def->enum_labels.emplace_back(L("Smooth PEI Plate / High Temp Plate"));
|
||||
def->enum_labels.emplace_back(L("Textured PEI Plate"));
|
||||
def->set_default_value(new ConfigOptionEnum<BedType>(btPC));
|
||||
|
||||
|
|
@ -1036,6 +1045,30 @@ void PrintConfigDef::init_fff_params()
|
|||
def->set_default_value(new ConfigOptionString());
|
||||
def->cli = ConfigOptionDef::nocli;
|
||||
|
||||
def = this->add("activate_air_filtration",coBools);
|
||||
def->label = L("Activate air filtration");
|
||||
def->tooltip = L("Activate for better air filtration");
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionBools{false});
|
||||
|
||||
def = this->add("during_print_exhaust_fan_speed", coInts);
|
||||
def->label = L("Fan speed");
|
||||
def->tooltip=L("Speed of exhuast fan during printing.This speed will overwrite the speed in filament custom gcode");
|
||||
def->sidetext = L("%");
|
||||
def->min=0;
|
||||
def->max=100;
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionInts{60});
|
||||
|
||||
def = this->add("complete_print_exhaust_fan_speed", coInts);
|
||||
def->label = L("Fan speed");
|
||||
def->sidetext = L("%");
|
||||
def->tooltip=L("Speed of exhuast fan after printing completes");
|
||||
def->min=0;
|
||||
def->max=100;
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionInts{80});
|
||||
|
||||
def = this->add("close_fan_the_first_x_layers", coInts);
|
||||
def->label = L("No cooling for the first");
|
||||
def->tooltip = L("Close all cooling fan for the first certain layers. Cooling fan of the first layer used to be closed "
|
||||
|
|
@ -1546,12 +1579,17 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->enum_values.push_back("PC");
|
||||
def->enum_values.push_back("PA");
|
||||
def->enum_values.push_back("PA-CF");
|
||||
def->enum_values.push_back("PA6-CF");
|
||||
def->enum_values.push_back("PLA-CF");
|
||||
def->enum_values.push_back("PET-CF");
|
||||
def->enum_values.push_back("PETG-CF");
|
||||
def->enum_values.push_back("PVA");
|
||||
def->enum_values.push_back("HIPS");
|
||||
def->enum_values.push_back("PLA-AERO");
|
||||
def->enum_values.push_back("PPS");
|
||||
def->enum_values.push_back("PPS-CF");
|
||||
def->enum_values.push_back("PPA-CF");
|
||||
def->enum_values.push_back("PPA-GF");
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionStrings { "PLA" });
|
||||
|
||||
|
|
@ -1790,8 +1828,8 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
|
||||
def = this->add("accel_to_decel_factor", coPercent);
|
||||
def->label = L("accel_to_decel");
|
||||
def->tooltip = L("Klipper's max_accel_to_decel will be adjusted to this % of acceleration");
|
||||
def->sidetext = L("%");
|
||||
def->tooltip = L("Klipper's max_accel_to_decel will be adjusted to this %% of acceleration");
|
||||
def->sidetext = L("%%");
|
||||
def->min = 1;
|
||||
def->max = 100;
|
||||
def->mode = comAdvanced;
|
||||
|
|
@ -2022,6 +2060,15 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->tooltip = L("Enable this to enable the camera on printer to check the quality of first layer");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
// BBS
|
||||
def = this->add("thumbnail_size", coPoints);
|
||||
def->label = L("Thumbnail size");
|
||||
def->tooltip = L("Decides the size of thumbnail stored in gcode files");
|
||||
def->mode = comDevelop;
|
||||
def->gui_type = ConfigOptionDef::GUIType::one_string;
|
||||
def->set_default_value(new ConfigOptionPoints{ Vec2d(50,50) });
|
||||
|
||||
//BBS
|
||||
// def = this->add("spaghetti_detector", coBool);
|
||||
// def->label = L("Enable spaghetti detector");
|
||||
|
|
@ -2045,6 +2092,7 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<NozzleType>(ntUndefine));
|
||||
|
||||
|
||||
def = this->add("nozzle_hrc", coInt);
|
||||
def->label = L("Nozzle HRC");
|
||||
def->tooltip = L("The nozzle's hardness. Zero means no checking for nozzle's hardness during slicing.");
|
||||
|
|
@ -2054,12 +2102,36 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->mode = comDevelop;
|
||||
def->set_default_value(new ConfigOptionInt{0});
|
||||
|
||||
def = this->add("printer_structure", coEnum);
|
||||
def->label = L("Printer structure");
|
||||
def->tooltip = L("The physical arrangement and components of a printing device");
|
||||
def->enum_keys_map = &ConfigOptionEnum<PrinterStructure>::get_enum_values();
|
||||
def->enum_values.push_back("undefine");
|
||||
def->enum_values.push_back("corexy");
|
||||
def->enum_values.push_back("i3");
|
||||
def->enum_values.push_back("hbot");
|
||||
def->enum_values.push_back("delta");
|
||||
def->enum_labels.push_back(L("Undefine"));
|
||||
def->enum_labels.push_back(L("CoreXY"));
|
||||
def->enum_labels.push_back(L("I3"));
|
||||
def->enum_labels.push_back(L("Hbot"));
|
||||
def->enum_labels.push_back(L("Delta"));
|
||||
def->mode = comDevelop;
|
||||
def->set_default_value(new ConfigOptionEnum<PrinterStructure>(psUndefine));
|
||||
|
||||
def = this->add("best_object_pos", coPoint);
|
||||
def->label = L("Best object position");
|
||||
def->tooltip = L("Best auto arranging position in range [0,1] w.r.t. bed shape.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPoint(Vec2d(0.5, 0.5)));
|
||||
|
||||
def = this->add("auxiliary_fan", coBool);
|
||||
def->label = L("Auxiliary part cooling fan");
|
||||
def->tooltip = L("Enable this option if machine has auxiliary part cooling fan");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
|
||||
def = this->add("fan_speedup_time", coFloat);
|
||||
// Label is set in Tab.cpp in the Line object.
|
||||
//def->label = L("Fan speed-up time");
|
||||
|
|
@ -2090,6 +2162,7 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
|
||||
def = this->add("time_cost", coFloat);
|
||||
def->label = L("Time cost");
|
||||
def->tooltip = L("The printer cost per hour");
|
||||
|
|
@ -2098,6 +2171,19 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def =this->add("support_chamber_temp_control",coBool);
|
||||
def->label=L("Support control chamber temperature");
|
||||
def->tooltip=L("This option is enabled if machine support controlling chamber temperature");
|
||||
def->mode=comDevelop;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
def->readonly=false;
|
||||
|
||||
def =this->add("support_air_filtration",coBool);
|
||||
def->label=L("Support air filtration");
|
||||
def->tooltip=L("Enable this if printer support air filtration");
|
||||
def->mode=comDevelop;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("gcode_flavor", coEnum);
|
||||
def->label = L("G-code flavor");
|
||||
def->tooltip = L("What kind of gcode the printer is compatible with");
|
||||
|
|
@ -2294,6 +2380,14 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("time_lapse_gcode",coString);
|
||||
def->label = L("Time lapse G-code");
|
||||
def->multiline = true;
|
||||
def->full_width = true;
|
||||
def->height =5;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("silent_mode", coBool);
|
||||
def->label = L("Supports silent mode");
|
||||
def->tooltip = L("Whether the machine supports silent mode in which machine use lower acceleration to print");
|
||||
|
|
@ -2891,6 +2985,21 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionFloats { 0.4 });
|
||||
|
||||
def = this->add("retract_lift_above", coFloats);
|
||||
def->label = L("Z hop lower boundary");
|
||||
def->tooltip = L("Z hop will only come into effect when Z is above this value and is below the parameter: \"Z hop upper boundary\"");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats{0.});
|
||||
|
||||
def = this->add("retract_lift_below", coFloats);
|
||||
def->label = L("Z hop upper boundary");
|
||||
def->tooltip = L("If this value is positive, Z hop will only come into effect when Z is above the parameter: \"Z hop lower boundary\" and is below this value");
|
||||
def->sidetext = L("mm");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats{0.});
|
||||
|
||||
|
||||
def = this->add("z_hop_types", coEnums);
|
||||
def->label = L("Z hop type");
|
||||
def->tooltip = L("Z hop type");
|
||||
|
|
@ -3733,7 +3842,10 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
|
||||
def = this->add("chamber_temperature", coInts);
|
||||
def->label = L("Chamber temperature");
|
||||
def->tooltip = L("Target chamber temperature");
|
||||
def->tooltip = L("Higher chamber temperature can help suppress or reduce warping and potentially lead to higher interlayer bonding strength for high temperature materials like ABS, ASA, PC, PA and so on."
|
||||
"At the same time, the air filtration of ABS and ASA will get worse.While for PLA, PETG, TPU, PVA and other low temperature materials,"
|
||||
"the actual chamber temperature should not be high to avoid cloggings, so 0 which stands for turning off is highly recommended"
|
||||
);
|
||||
def->sidetext = L("°C");
|
||||
def->full_label = L("Chamber temperature");
|
||||
def->min = 0;
|
||||
|
|
@ -3765,15 +3877,6 @@ def = this->add("filament_loading_speed", coFloats);
|
|||
def->max = max_temp;
|
||||
def->set_default_value(new ConfigOptionInts { 240 });
|
||||
|
||||
def = this->add("bed_temperature_difference", coInts);
|
||||
def->label = L("Bed temperature difference");
|
||||
def->tooltip = L("Do not recommend bed temperature of other layer to be lower than initial layer for more than this threshold. "
|
||||
"Too low bed temperature of other layer may cause the model broken free from build plate");
|
||||
def->sidetext = L("°C");
|
||||
def->min = 0;
|
||||
def->max = 30;
|
||||
def->mode = comDevelop;
|
||||
def->set_default_value(new ConfigOptionInts { 10 });
|
||||
|
||||
def = this->add("detect_thin_wall", coBool);
|
||||
def->label = L("Detect thin wall");
|
||||
|
|
@ -4974,7 +5077,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
|
|||
"remove_freq_sweep", "remove_bed_leveling", "remove_extrusion_calibration",
|
||||
"support_transition_line_width", "support_transition_speed", "bed_temperature", "bed_temperature_initial_layer",
|
||||
"can_switch_nozzle_type", "can_add_auxiliary_fan", "extra_flush_volume", "spaghetti_detector", "adaptive_layer_height",
|
||||
"z_hop_type", "z_lift_type"
|
||||
"z_hop_type", "z_lift_type", "bed_temperature_difference"
|
||||
};
|
||||
|
||||
if (ignore.find(opt_key) != ignore.end()) {
|
||||
|
|
@ -5683,6 +5786,12 @@ CLIActionsConfigDef::CLIActionsConfigDef()
|
|||
def->cli_params = "option";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("min_save", coBool);
|
||||
def->label = L("Minimum save");
|
||||
def->tooltip = L("export 3mf with minimum size.");
|
||||
def->cli_params = "option";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("mtcpp", coInt);
|
||||
def->label = L("mtcpp");
|
||||
def->tooltip = L("max triangle count per plate for slicing.");
|
||||
|
|
@ -5789,12 +5898,12 @@ CLITransformConfigDef::CLITransformConfigDef()
|
|||
def->cli_params = "count";
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
|
||||
/*def = this->add("ensure_on_bed", coBool);
|
||||
def = this->add("ensure_on_bed", coBool);
|
||||
def->label = L("Ensure on bed");
|
||||
def->tooltip = L("Lift the object above the bed when it is partially below. Enabled by default, use --no-ensure-on-bed to disable.");
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
def->tooltip = L("Lift the object above the bed when it is partially below. Disabled by default");
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("copy", coInt);
|
||||
/*def = this->add("copy", coInt);
|
||||
def->label = L("Copy");
|
||||
def->tooltip =L("Duplicate copies of model");
|
||||
def->min = 1;
|
||||
|
|
@ -5814,18 +5923,18 @@ CLITransformConfigDef::CLITransformConfigDef()
|
|||
def->tooltip = L("Convert the units of model");
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("orient", coBool);
|
||||
def->label = L("Orient");
|
||||
def->tooltip = L("Orient the model");
|
||||
def = this->add("orient", coInt);
|
||||
def->label = L("Orient Options");
|
||||
def->tooltip = L("Orient options: 0-disable, 1-enable, others-auto");
|
||||
//def->cli = "orient|o";
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
/*def = this->add("repair", coBool);
|
||||
def->label = L("Repair");
|
||||
def->tooltip = L("Repair the model's meshes if it is non-manifold mesh");
|
||||
def->set_default_value(new ConfigOptionBool(false));*/
|
||||
|
||||
/*def = this->add("rotate", coFloat);
|
||||
def = this->add("rotate", coFloat);
|
||||
def->label = L("Rotate");
|
||||
def->tooltip = L("Rotation angle around the Z axis in degrees.");
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
|
@ -5838,7 +5947,7 @@ CLITransformConfigDef::CLITransformConfigDef()
|
|||
def = this->add("rotate_y", coFloat);
|
||||
def->label = L("Rotate around Y");
|
||||
def->tooltip = L("Rotation angle around the Y axis in degrees.");
|
||||
def->set_default_value(new ConfigOptionFloat(0));*/
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("scale", coFloat);
|
||||
def->label = L("Scale");
|
||||
|
|
@ -5947,6 +6056,12 @@ CLIMiscConfigDef::CLIMiscConfigDef()
|
|||
def->tooltip = L("Render with a software renderer. The bundled MESA software renderer is loaded instead of the default OpenGL driver.");
|
||||
def->min = 0;*/
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
def = this->add("load_custom_gcodes", coString);
|
||||
def->label = L("Load custom gcode");
|
||||
def->tooltip = L("Load custom gcode from json");
|
||||
def->cli_params = "custom_gcode_toolchange.json";
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
}
|
||||
|
||||
const CLIActionsConfigDef cli_actions_config_def;
|
||||
|
|
@ -6017,6 +6132,17 @@ Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg)
|
|||
if (!tmp.empty()) bed_poly = tmp[0];
|
||||
return bed_poly;
|
||||
}
|
||||
bool has_skirt(const DynamicPrintConfig& cfg)
|
||||
{
|
||||
auto opt_skirt_height = cfg.option("skirt_height");
|
||||
auto opt_skirt_loops = cfg.option("skirt_loops");
|
||||
auto opt_draft_shield = cfg.option("draft_shield");
|
||||
return (opt_skirt_height && opt_skirt_height->getInt() > 0 && opt_skirt_loops && opt_skirt_loops->getInt() > 0)
|
||||
|| (opt_draft_shield && opt_draft_shield->getInt() != dsDisabled);
|
||||
}
|
||||
float get_real_skirt_dist(const DynamicPrintConfig& cfg) {
|
||||
return has_skirt(cfg) ? cfg.opt_float("skirt_distance") : 0;
|
||||
}
|
||||
} // namespace Slic3r
|
||||
|
||||
#include <cereal/types/polymorphic.hpp>
|
||||
|
|
|
|||
|
|
@ -208,6 +208,15 @@ enum NozzleType {
|
|||
ntCount
|
||||
};
|
||||
|
||||
// BBS
|
||||
enum PrinterStructure {
|
||||
psUndefine=0,
|
||||
psCoreXY,
|
||||
psI3,
|
||||
psHbot,
|
||||
psDelta
|
||||
};
|
||||
|
||||
// BBS
|
||||
enum ZHopType {
|
||||
zhtAuto = 0,
|
||||
|
|
@ -878,8 +887,10 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionBool, gcode_add_line_number))
|
||||
((ConfigOptionBool, bbl_bed_temperature_gcode))
|
||||
((ConfigOptionEnum<GCodeFlavor>, gcode_flavor))
|
||||
|
||||
((ConfigOptionFloat, time_cost))
|
||||
((ConfigOptionString, layer_change_gcode))
|
||||
((ConfigOptionString, time_lapse_gcode))
|
||||
|
||||
((ConfigOptionFloat, max_volumetric_extrusion_rate_slope))
|
||||
((ConfigOptionInt, max_volumetric_extrusion_rate_slope_segment_length))
|
||||
|
|
@ -911,6 +922,11 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionEnum<NozzleType>, nozzle_type))
|
||||
((ConfigOptionInt, nozzle_hrc))
|
||||
((ConfigOptionBool, auxiliary_fan))
|
||||
((ConfigOptionBool, support_air_filtration))
|
||||
((ConfigOptionEnum<PrinterStructure>,printer_structure))
|
||||
((ConfigOptionBool, support_chamber_temp_control))
|
||||
|
||||
|
||||
// SoftFever
|
||||
((ConfigOptionBool, use_firmware_retraction))
|
||||
((ConfigOptionBool, use_relative_e_distances))
|
||||
|
|
@ -994,6 +1010,9 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
|||
((ConfigOptionFloatOrPercent, bridge_acceleration))
|
||||
((ConfigOptionFloat, travel_acceleration))
|
||||
((ConfigOptionFloatOrPercent, sparse_infill_acceleration))
|
||||
((ConfigOptionBools, activate_air_filtration))
|
||||
((ConfigOptionInts, during_print_exhaust_fan_speed))
|
||||
((ConfigOptionInts, complete_print_exhaust_fan_speed))
|
||||
((ConfigOptionFloatOrPercent, internal_solid_infill_acceleration))
|
||||
((ConfigOptionFloatOrPercent, initial_layer_line_width))
|
||||
((ConfigOptionFloat, initial_layer_print_height))
|
||||
|
|
@ -1015,6 +1034,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
|||
((ConfigOptionInts, fan_min_speed))
|
||||
((ConfigOptionFloats, min_layer_height))
|
||||
((ConfigOptionFloat, printable_height))
|
||||
((ConfigOptionPoint, best_object_pos))
|
||||
((ConfigOptionFloats, slow_down_min_speed))
|
||||
((ConfigOptionFloats, nozzle_diameter))
|
||||
((ConfigOptionBool, reduce_infill_retraction))
|
||||
|
|
@ -1036,7 +1056,6 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
|||
((ConfigOptionInts , chamber_temperature))
|
||||
((ConfigOptionBools, wipe))
|
||||
// BBS
|
||||
((ConfigOptionInts, bed_temperature_difference))
|
||||
((ConfigOptionInts, nozzle_temperature_range_low))
|
||||
((ConfigOptionInts, nozzle_temperature_range_high))
|
||||
((ConfigOptionFloats, wipe_distance))
|
||||
|
|
@ -1384,6 +1403,8 @@ Points get_bed_shape(const DynamicPrintConfig &cfg);
|
|||
Points get_bed_shape(const PrintConfig &cfg);
|
||||
Points get_bed_shape(const SLAPrinterConfig &cfg);
|
||||
Slic3r::Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg);
|
||||
bool has_skirt(const DynamicPrintConfig& cfg);
|
||||
float get_real_skirt_dist(const DynamicPrintConfig& cfg);
|
||||
|
||||
// ModelConfig is a wrapper around DynamicPrintConfig with an addition of a timestamp.
|
||||
// Each change of ModelConfig is tracked by assigning a new timestamp from a global counter.
|
||||
|
|
|
|||
|
|
@ -507,7 +507,7 @@ void PrintObject::generate_support_material()
|
|||
{LargeOverhang,L("large overhangs")} };
|
||||
std::string warning_message = format(L("It seems object %s has %s. Please re-orient the object or enable support generation."),
|
||||
this->model_object()->name, reasons[sntype]);
|
||||
this->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, warning_message, PrintStateBase::SlicingNeedSupportOn);
|
||||
this->active_step_add_warning(PrintStateBase::WarningLevel::NON_CRITICAL, warning_message, PrintStateBase::SlicingNeedSupportOn);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
@ -874,7 +874,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
} else if (
|
||||
opt_key == "bottom_shell_layers"
|
||||
|| opt_key == "top_shell_layers") {
|
||||
|
||||
|
||||
steps.emplace_back(posPrepareInfill);
|
||||
|
||||
const auto *old_shell_layers = old_config.option<ConfigOptionInt>(opt_key);
|
||||
|
|
@ -886,7 +886,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
|
||||
if (value_changed && this->object_extruders().size() > 1) {
|
||||
steps.emplace_back(posSlice);
|
||||
}
|
||||
}
|
||||
else if (m_print->config().spiral_mode && opt_key == "bottom_shell_layers") {
|
||||
// Changing the number of bottom layers when a spiral vase is enabled requires re-slicing the object again.
|
||||
// Otherwise, holes in the bottom layers could be filled, as is reported in GH #5528.
|
||||
|
|
|
|||
|
|
@ -23,8 +23,9 @@ class BBLModelTask;
|
|||
enum MachineBedType {
|
||||
//BED_TYPE_AUTO = 0,
|
||||
BED_TYPE_PC = 0,
|
||||
BED_TYPE_PEI,
|
||||
BED_TYPE_PE,
|
||||
BED_TYPE_PEI,
|
||||
BED_TYPE_PTE,
|
||||
BED_TYPE_COUNT,
|
||||
};
|
||||
|
||||
|
|
@ -191,6 +192,8 @@ public:
|
|||
static BBLSubTask::SubTaskStatus parse_user_service_task_status(int status);
|
||||
};
|
||||
|
||||
typedef std::function<void(BBLModelTask* subtask)> OnGetSubTaskFn;
|
||||
|
||||
class BBLTask {
|
||||
public:
|
||||
enum TaskStatus {
|
||||
|
|
|
|||
|
|
@ -97,7 +97,8 @@ void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_
|
|||
|
||||
//shuffle the faces and traverse in random order, this MASSIVELY improves the quality of the result
|
||||
std::shuffle(face_indices.begin(), face_indices.end(), generator);
|
||||
|
||||
|
||||
int allowed_face_removals = int(face_indices.size()) - int(target_triangle_count);
|
||||
for (const size_t &face_idx : face_indices) {
|
||||
if (face_removal_flags[face_idx]) {
|
||||
// if face already removed from previous collapses, skip (each collapse removes two triangles [at least] )
|
||||
|
|
@ -130,10 +131,13 @@ void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_
|
|||
// remove faces
|
||||
remove_face(face_idx, neighbor_to_remove_face_idx);
|
||||
remove_face(neighbor_to_remove_face_idx, face_idx);
|
||||
allowed_face_removals-=2;
|
||||
|
||||
// break. this triangle is done
|
||||
break;
|
||||
}
|
||||
|
||||
if (allowed_face_removals <= 0) { break; }
|
||||
}
|
||||
|
||||
// filter face_indices, remove those that have been collapsed
|
||||
|
|
|
|||
|
|
@ -419,6 +419,7 @@ private:
|
|||
std::vector<std::vector<MinimumSpanningTree>> m_spanning_trees;
|
||||
std::vector< std::unordered_map<Line, bool, LineHash>> m_mst_line_x_layer_contour_caches;
|
||||
coordf_t MAX_BRANCH_RADIUS = 10.0;
|
||||
coordf_t MAX_BRANCH_RADIUS_FIRST_LAYER = 12.0;
|
||||
coordf_t MIN_BRANCH_RADIUS = 0.5;
|
||||
float tree_support_branch_diameter_angle = 5.0;
|
||||
bool is_strong = false;
|
||||
|
|
|
|||
|
|
@ -254,8 +254,7 @@ void TriangleSelector::select_patch(int facet_start, std::unique_ptr<Cursor> &&c
|
|||
}
|
||||
}
|
||||
|
||||
const float highlight_angle_limit = cos(Geometry::deg2rad(highlight_by_angle_deg));
|
||||
Vec3f vec_down = (trafo_no_translate.inverse() * -Vec3d::UnitZ()).normalized().cast<float>();
|
||||
const float highlight_angle_limit = -cos(Geometry::deg2rad(highlight_by_angle_deg));
|
||||
|
||||
// BBS
|
||||
std::vector<int> start_facets;
|
||||
|
|
@ -291,7 +290,9 @@ void TriangleSelector::select_patch(int facet_start, std::unique_ptr<Cursor> &&c
|
|||
while (facet_idx < int(facets_to_check.size())) {
|
||||
int facet = facets_to_check[facet_idx];
|
||||
const Vec3f& facet_normal = m_face_normals[m_triangles[facet].source_triangle];
|
||||
if (!visited[facet] && (highlight_by_angle_deg == 0.f || vec_down.dot(facet_normal) >= highlight_angle_limit)) {
|
||||
Matrix3f normal_matrix = static_cast<Matrix3f>(trafo_no_translate.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>());
|
||||
float world_normal_z = (normal_matrix* facet_normal).normalized().z();
|
||||
if (!visited[facet] && (highlight_by_angle_deg == 0.f || world_normal_z < highlight_angle_limit)) {
|
||||
if (select_triangle(facet, new_state, triangle_splitting)) {
|
||||
// add neighboring facets to list to be processed later
|
||||
for (int neighbor_idx : m_neighbors[facet])
|
||||
|
|
@ -331,8 +332,7 @@ void TriangleSelector::seed_fill_select_triangles(const Vec3f &hit, int facet_st
|
|||
facet_queue.push(facet_start);
|
||||
|
||||
const double facet_angle_limit = cos(Geometry::deg2rad(seed_fill_angle)) - EPSILON;
|
||||
const float highlight_angle_limit = cos(Geometry::deg2rad(highlight_by_angle_deg));
|
||||
Vec3f vec_down = (trafo_no_translate.inverse() * -Vec3d::UnitZ()).normalized().cast<float>();
|
||||
const float highlight_angle_limit = -cos(Geometry::deg2rad(highlight_by_angle_deg));
|
||||
|
||||
// Depth-first traversal of neighbors of the face hit by the ray thrown from the mouse cursor.
|
||||
while (!facet_queue.empty()) {
|
||||
|
|
@ -340,7 +340,9 @@ void TriangleSelector::seed_fill_select_triangles(const Vec3f &hit, int facet_st
|
|||
facet_queue.pop();
|
||||
|
||||
const Vec3f &facet_normal = m_face_normals[m_triangles[current_facet].source_triangle];
|
||||
if (!visited[current_facet] && (highlight_by_angle_deg == 0.f || vec_down.dot(facet_normal) >= highlight_angle_limit)) {
|
||||
Matrix3f normal_matrix = static_cast<Matrix3f>(trafo_no_translate.matrix().block(0, 0, 3, 3).inverse().transpose().cast<float>());
|
||||
float world_normal_z = (normal_matrix * facet_normal).normalized().z();
|
||||
if (!visited[current_facet] && (highlight_by_angle_deg == 0.f || world_normal_z < highlight_angle_limit)) {
|
||||
if (m_triangles[current_facet].is_split()) {
|
||||
for (int split_triangle_idx = 0; split_triangle_idx <= m_triangles[current_facet].number_of_split_sides(); ++split_triangle_idx) {
|
||||
assert(split_triangle_idx < int(m_triangles[current_facet].children.size()));
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
#define CLI_FILAMENTS_DIFFERENT_TEMP -62
|
||||
#define CLI_OBJECT_COLLISION_IN_SEQ_PRINT -63
|
||||
#define CLI_OBJECT_COLLISION_IN_LAYER_PRINT -64
|
||||
#define CLI_SPIRAL_MODE_CANNOT_DUPLICATE -65
|
||||
|
||||
#define CLI_SLICING_ERROR -100
|
||||
#define CLI_GCODE_PATH_CONFLICTS -101
|
||||
|
|
|
|||
|
|
@ -666,6 +666,17 @@ void CalibPressureAdvancePattern::generate_custom_gcodes(const DynamicPrintConfi
|
|||
model.plates_custom_gcodes[model.curr_plate_index] = info;
|
||||
}
|
||||
|
||||
void CalibPressureAdvancePattern::set_start_offset(const Vec3d &offset)
|
||||
{
|
||||
m_starting_point = offset;
|
||||
m_is_start_point_fixed = true;
|
||||
}
|
||||
|
||||
Vec3d CalibPressureAdvancePattern::get_start_offset()
|
||||
{
|
||||
return m_starting_point;
|
||||
}
|
||||
|
||||
void CalibPressureAdvancePattern::refresh_setup(const DynamicPrintConfig &config,
|
||||
bool is_bbl_machine,
|
||||
const Model &model,
|
||||
|
|
@ -683,6 +694,9 @@ void CalibPressureAdvancePattern::refresh_setup(const DynamicPrintConfig &config
|
|||
|
||||
void CalibPressureAdvancePattern::_refresh_starting_point(const Model &model)
|
||||
{
|
||||
if (m_is_start_point_fixed)
|
||||
return;
|
||||
|
||||
ModelObject *obj = model.objects.front();
|
||||
BoundingBoxf3 bbox = obj->instance_bounding_box(*obj->instances.front(), false);
|
||||
|
||||
|
|
|
|||
|
|
@ -251,6 +251,9 @@ public:
|
|||
|
||||
void generate_custom_gcodes(const DynamicPrintConfig &config, bool is_bbl_machine, Model &model, const Vec3d &origin);
|
||||
|
||||
void set_start_offset(const Vec3d &offset);
|
||||
Vec3d get_start_offset();
|
||||
|
||||
protected:
|
||||
double speed_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_speed")->value; };
|
||||
double speed_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_speed")->value; };
|
||||
|
|
@ -293,6 +296,7 @@ private:
|
|||
GCodeWriter m_writer;
|
||||
bool m_is_delta;
|
||||
Vec3d m_starting_point;
|
||||
bool m_is_start_point_fixed = false;
|
||||
|
||||
const double m_handle_xy_size{5};
|
||||
const double m_handle_spacing{2};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue