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:
SoftFever 2023-09-30 08:44:32 +08:00
commit 59bab91da9
579 changed files with 23269 additions and 11097 deletions

View file

@ -37,8 +37,9 @@ struct NfpPConfig {
BOTTOM_RIGHT,
TOP_LEFT,
TOP_RIGHT,
DONT_ALIGN //!> Warning: parts may end up outside the bin with the
DONT_ALIGN, //!> Warning: parts may end up outside the bin with the
//! default object function.
USER_DEFINED
};
/// Which angles to try out for better results.
@ -50,6 +51,8 @@ struct NfpPConfig {
/// Where to start putting objects in the bin.
Alignment starting_point;
TPoint<RawShape> best_object_pos;
/**
* @brief A function object representing the fitting function in the
* placement optimization process. (Optional)
@ -1093,6 +1096,11 @@ private:
cb = bbin.maxCorner();
break;
}
case Config::Alignment::USER_DEFINED: {
ci = bb.center();
cb = config_.best_object_pos;
break;
}
default: ; // DONT_ALIGN
}
@ -1115,11 +1123,9 @@ private:
return;
{ // find a best position inside NFP of fixed items (excluded regions), so the center of pile is cloest to bed center
RawShape objs_convex_hull = sl::convexHull(objs);
for (const Item &item : config_.m_excluded_regions) { excludes.push_back(item.transformedShape()); }
for (const Item &item : items_) {
if (item.isFixed()) {
if (!(item.is_wipe_tower && !need_wipe_tower))
excludes.push_back(item.transformedShape());
excludes.push_back(item.transformedShape());
}
}

View file

@ -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 &params) {
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);

View file

@ -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.
*

View file

@ -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()

View file

@ -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) {

View file

@ -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;
}

View file

@ -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),

View file

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

View 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);
}

View 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

View file

@ -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";

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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

View file

@ -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();
}

View file

@ -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);

View file

@ -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()) {

View file

@ -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(); }

View file

@ -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();

View file

@ -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(

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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...

View file

@ -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",

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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.

View file

@ -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>

View file

@ -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.

View file

@ -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.

View file

@ -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 {

View file

@ -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

View file

@ -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;

View file

@ -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()));

View file

@ -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

View file

@ -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);

View file

@ -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};

View file

@ -747,16 +747,6 @@ bool AMSMaterialsSetting::Show(bool show)
m_input_nozzle_min->GetTextCtrl()->SetSize(wxSize(-1, FromDIP(20)));
//m_clr_picker->set_color(m_clr_picker->GetParent()->GetBackgroundColour());
/*if (obj && (obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI) || obj->is_high_printer_type())) {
m_ratio_text->Show();
m_k_param->Show();
m_input_k_val->Show();
}
else {
m_ratio_text->Hide();
m_k_param->Hide();
m_input_k_val->Hide();
}*/
m_ratio_text->Show();
m_k_param->Show();
m_input_k_val->Show();

View file

@ -192,8 +192,8 @@ void AMSSetting::create()
wxPanel* m_panel_img = new wxPanel(m_panel_body, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_panel_img->SetBackgroundColour(AMS_SETTING_GREY200);
wxBoxSizer *m_sizer_img = new wxBoxSizer(wxVERTICAL);
auto img = new wxStaticBitmap(m_panel_img, wxID_ANY, create_scaled_bitmap("ams_icon", nullptr, 126), wxDefaultPosition, wxDefaultSize);
m_sizer_img->Add(img, 0, wxALIGN_CENTER | wxTOP, 26);
ams_img = new wxStaticBitmap(m_panel_img, wxID_ANY, create_scaled_bitmap("ams_icon", nullptr, 126), wxDefaultPosition, wxDefaultSize);
m_sizer_img->Add(ams_img, 0, wxALIGN_CENTER | wxTOP, 26);
m_sizer_img->Add(0, 0, 0, wxTOP, 18);
m_panel_img->SetSizer(m_sizer_img);
m_panel_img->Layout();
@ -262,6 +262,19 @@ void AMSSetting::update_insert_material_read_mode(bool selected)
Fit();
}
void AMSSetting::update_image(std::string ams_type)
{
if (ams_type == m_current_ams_type) return;
if (ams_type == "generic") {
ams_img->SetBitmap(create_scaled_bitmap("monitor_upgrade_f1", nullptr, 126));
}
else {
ams_img->SetBitmap(create_scaled_bitmap("ams_icon", nullptr, 126));
}
m_current_ams_type = ams_type;
Layout();
}
void AMSSetting::update_starting_read_mode(bool selected)
{
m_checkbox_starting_auto_read->SetValue(selected);

View file

@ -28,6 +28,7 @@ public:
void create();
void update_insert_material_read_mode(bool selected);
void update_image(std::string ams_type);
void update_starting_read_mode(bool selected);
void update_remain_mode(bool selected);
void update_switch_filament(bool selected);
@ -46,6 +47,7 @@ protected:
void on_dpi_changed(const wxRect &suggested_rect) override;
protected:
std::string m_current_ams_type;
wxPanel * m_panel_body;
CheckBox * m_checkbox_Insert_material_auto_read;
wxStaticText *m_title_Insert_material_auto_read;
@ -68,7 +70,7 @@ protected:
wxStaticText *m_tip_ams_img;
Button * m_button_auto_demarcate;
wxStaticBitmap* ams_img;
wxBoxSizer *m_sizer_Insert_material_tip_inline;
wxBoxSizer *m_sizer_starting_tip_inline;
wxBoxSizer *m_sizer_remain_inline;

View file

@ -273,7 +273,7 @@ void BackgroundSlicingProcess::process_sla()
//BBS: add plate id for thumbnail generation
ThumbnailsList thumbnails = this->render_thumbnails(
ThumbnailsParams{ THUMBNAIL_SIZE, true, true, true, true, 0 });
ThumbnailsParams{ current_print()->full_print_config().option<ConfigOptionPoints>("thumbnail_size")->values, true, true, true, true, 0 });
Zipper zipper(export_path);
m_sla_archive.export_print(zipper, *m_sla_print); // true, false, true, true); // renders also supports and pad

View file

@ -50,16 +50,16 @@ CalibrationDialog::CalibrationDialog(Plater *plater)
select_xcam_cali = create_check_option(_L("Micro lidar calibration"), cali_left_panel, _L("Micro lidar calibration"), "xcam_cali");
select_bed_leveling = create_check_option(_L("Bed leveling"), cali_left_panel, _L("Bed leveling"), "bed_leveling");
select_vibration = create_check_option(_L("Resonance frequency identification"), cali_left_panel, _L("Resonance frequency identification"), "vibration");
select_vibration = create_check_option(_L("Vibration compensation"), cali_left_panel, _L("Vibration compensation"), "vibration");
select_motor_noise = create_check_option(_L("Motor noise cancellation"), cali_left_panel, _L("Motor noise cancellation"), "motor_noise");
m_checkbox_list["xcam_cali"]->SetValue(true);
m_checkbox_list["bed_leveling"]->SetValue(true);
m_checkbox_list["vibration"]->SetValue(true);
cali_left_sizer->Add(0, FromDIP(18), 0, wxEXPAND, 0);
cali_left_sizer->Add(select_xcam_cali, 0, wxLEFT, FromDIP(15));
cali_left_sizer->Add(select_bed_leveling, 0, wxLEFT, FromDIP(15));
cali_left_sizer->Add(select_vibration, 0, wxLEFT, FromDIP(15));
cali_left_sizer->Add(select_motor_noise, 0, wxLEFT, FromDIP(15));
cali_left_sizer->Add(0, FromDIP(30), 0, wxEXPAND, 0);
auto cali_left_text_top = new wxStaticText(cali_left_panel, wxID_ANY, _L("Calibration program"), wxDefaultPosition, wxDefaultSize, 0);
@ -208,6 +208,7 @@ wxWindow* CalibrationDialog::create_check_option(wxString title, wxWindow* paren
text->Bind(wxEVT_LEFT_DOWN, [this, check](wxMouseEvent&) { check->SetValue(check->GetValue() ? false : true); });
m_checkbox_list[param] = check;
m_checkbox_list[param]->SetValue(true);
return checkbox;
}
@ -219,6 +220,30 @@ void CalibrationDialog::update_cali(MachineObject *obj)
select_xcam_cali->Show();
} else {
select_xcam_cali->Hide();
m_checkbox_list["xcam_cali"]->SetValue(false);
}
if(obj->is_function_supported(PrinterFunction::FUNC_AUTO_LEVELING)){
select_bed_leveling->Show();
}else{
select_bed_leveling->Hide();
m_checkbox_list["bed_leveling"]->SetValue(false);
}
if (obj->is_function_supported(PrinterFunction::FUNC_MOTOR_NOISE_CALI)) {
select_motor_noise->Show();
} else {
select_motor_noise->Hide();
m_checkbox_list["motor_noise"]->SetValue(false);
}
if (!m_checkbox_list["vibration"]->GetValue() && !m_checkbox_list["bed_leveling"]->GetValue() && !m_checkbox_list["xcam_cali"]->GetValue() &&
!m_checkbox_list["motor_noise"]->GetValue()) {
m_calibration_btn->Disable();
m_calibration_btn->SetLabel(_L("No step selected"));
return ;
} else {
m_calibration_btn->Enable();
}
if (obj->is_calibration_running() || obj->is_calibration_done()) {
@ -284,7 +309,8 @@ void CalibrationDialog::on_start_calibration(wxMouseEvent &event)
m_obj->command_start_calibration(
m_checkbox_list["vibration"]->GetValue(),
m_checkbox_list["bed_leveling"]->GetValue(),
m_checkbox_list["xcam_cali"]->GetValue()
m_checkbox_list["xcam_cali"]->GetValue(),
m_checkbox_list["motor_noise"]->GetValue()
);
}
}

View file

@ -42,6 +42,7 @@ private:
wxWindow* select_xcam_cali { nullptr };
wxWindow* select_bed_leveling { nullptr };
wxWindow* select_vibration { nullptr };
wxWindow* select_motor_noise { nullptr };
wxWindow* create_check_option(wxString title, wxWindow *parent, wxString tooltip, std::string param);

View file

@ -526,6 +526,14 @@ void CalibrationPanel::update_all() {
if (!dev) return;
obj = dev->get_selected_machine();
// check valid machine
if (obj && dev->get_my_machine(obj->dev_id) == nullptr) {
dev->set_selected_machine("");
if (m_agent) m_agent->set_user_selected_machine("");
show_status((int) MONITOR_NO_PRINTER);
return;
}
// update current wizard only
int curr_selected = m_tabpanel->GetSelection();
@ -543,15 +551,6 @@ void CalibrationPanel::update_all() {
}
}
// check valid machine
if (obj && dev->get_my_machine(obj->dev_id) == nullptr) {
dev->set_selected_machine("");
if (m_agent)
m_agent->set_user_selected_machine("");
show_status((int)MONITOR_NO_PRINTER);
return;
}
if (wxGetApp().is_user_login()) {
dev->check_pushing();
try {

View file

@ -15,6 +15,9 @@ wxDEFINE_EVENT(EVT_DEVICE_CHANGED, wxCommandEvent);
wxDEFINE_EVENT(EVT_CALIBRATION_JOB_FINISHED, wxCommandEvent);
static const wxString NA_STR = _L("N/A");
static const float MIN_PA_K_VALUE = 0.0;
static const float MAX_PA_K_VALUE = 0.5;
static const float MIN_PA_K_VALUE_STEP = 0.001;
bool check_preset_name_valid(const wxString& name) {
wxString error_message;
@ -46,6 +49,18 @@ std::map<int, Preset*> get_cached_selected_filament(MachineObject* obj) {
return selected_filament_map;
}
bool is_pa_params_valid(const Calib_Params& params)
{
if (params.start < MIN_PA_K_VALUE || params.end > MAX_PA_K_VALUE || params.step < EPSILON || params.end < params.start + params.step) {
MessageDialog msg_dlg(nullptr,
wxString::Format(_L("Please input valid values:\nStart value: >= %.1f\nEnd value: <= %.1f\nEnd value: > Start value\nValue step: >= %.3f)"), MIN_PA_K_VALUE, MAX_PA_K_VALUE, MIN_PA_K_VALUE_STEP),
wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return false;
}
return true;
}
CalibrationWizard::CalibrationWizard(wxWindow* parent, CalibMode mode, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
: wxPanel(parent, id, pos, size, style)
, m_mode(mode)
@ -136,6 +151,25 @@ void CalibrationWizard::on_device_connected(MachineObject* obj)
recover_preset_info(obj);
BOOST_LOG_TRIVIAL(info) << "on_device_connected - machine object status:"
<< " dev_id = " << obj->dev_id
<< ", print_type = " << obj->printer_type
<< ", printer_status = " << obj->print_status
<< ", cali_finished = " << obj->cali_finished
<< ", cali_version = " << obj->cali_version
<< ", cache_flow_ratio = " << obj->cache_flow_ratio
<< ", sub_task_name = " << obj->subtask_name
<< ", gcode_file_name = " << obj->m_gcode_file;
for (const CaliPresetInfo& preset_info : obj->selected_cali_preset) {
BOOST_LOG_TRIVIAL(info) << "on_device_connected - selected preset: "
<< "tray_id = " << preset_info.tray_id
<< ", nozzle_diameter = " << preset_info.nozzle_diameter
<< ", filament_id = " << preset_info.filament_id
<< ", settring_id = " << preset_info.setting_id
<< ", name = " << preset_info.name;
}
for (int i = 0; i < m_page_steps.size(); i++) {
if (m_page_steps[i]->page)
m_page_steps[i]->page->on_device_connected(obj);
@ -154,14 +188,14 @@ void CalibrationWizard::set_cali_method(CalibrationMethod method)
bool CalibrationWizard::save_preset(const std::string &old_preset_name, const std::string &new_preset_name, const std::map<std::string, ConfigOption *> &key_values, std::string& message)
{
if (new_preset_name.empty()) {
message = L("The name cannot be empty.");
message = _u8L("The name cannot be empty.");
return false;
}
PresetCollection *filament_presets = &wxGetApp().preset_bundle->filaments;
Preset* preset = filament_presets->find_preset(old_preset_name);
if (!preset) {
message = (boost::format(L("The selected preset: %1% is not found.")) % old_preset_name).str();
message = (boost::format(_u8L("The selected preset: %1% is not found.")) % old_preset_name).str();
return false;
}
@ -173,12 +207,12 @@ bool CalibrationWizard::save_preset(const std::string &old_preset_name, const st
Preset *new_preset = filament_presets->find_preset(new_name);
if (new_preset) {
if (new_preset->is_system) {
message = L("The name cannot be the same as the system preset name.");
message = _u8L("The name cannot be the same as the system preset name.");
return false;
}
if (new_preset != preset) {
message = L("The name is the same as another existing preset name");
message = _u8L("The name is the same as another existing preset name");
return false;
}
if (new_preset != &filament_presets->get_edited_preset()) new_preset = &temp_preset;
@ -199,7 +233,7 @@ bool CalibrationWizard::save_preset(const std::string &old_preset_name, const st
// Preset* preset = &m_presets.preset(it - m_presets.begin(), true);
if (!new_preset) {
BOOST_LOG_TRIVIAL(info) << "create new preset failed";
message = L("create new preset failed.");
message = _u8L("create new preset failed.");
return false;
}
@ -339,6 +373,18 @@ PressureAdvanceWizard::PressureAdvanceWizard(wxWindow* parent, wxWindowID id, co
create_pages();
}
void PressureAdvanceWizard::on_cali_job_finished(wxString evt_data)
{
int cali_stage = 0;
CalibMode obj_cali_mode = CalibUtils::get_calib_mode_by_name(evt_data.ToStdString(), cali_stage);
if (obj_cali_mode == m_mode) {
show_step(cali_step);
}
// change ui, hide
static_cast<CalibrationPresetPage *>(preset_step->page)->on_cali_finished_job();
}
void PressureAdvanceWizard::create_pages()
{
start_step = new CalibrationWizardPageStep(new CalibrationPAStartPage(m_scrolledWindow));
@ -422,6 +468,7 @@ void PressureAdvanceWizard::on_device_connected(MachineObject* obj)
CalibrationMethod method;
int cali_stage = 0;
CalibMode obj_cali_mode = get_obj_calibration_mode(obj, method, cali_stage);
obj->manual_pa_cali_method = ManualPaCaliMethod(cali_stage);
// show cali step when obj is in pa calibration
if (obj) {
@ -431,6 +478,8 @@ void PressureAdvanceWizard::on_device_connected(MachineObject* obj)
if (obj_cali_mode == m_mode) {
if (!obj->cali_finished && (obj->is_in_printing() || obj->is_printing_finished())) {
CalibrationWizard::set_cali_method(method);
CalibrationCaliPage *cali_page = (static_cast<CalibrationCaliPage *>(cali_step->page));
cali_page->set_pa_cali_image(cali_stage);
show_step(cali_step);
}
}
@ -504,11 +553,13 @@ void PressureAdvanceWizard::on_cali_start()
return;
}
if (curr_obj->get_printer_series() == PrinterSeries::SERIES_X1) {
//std::string error_message;
wxString wx_err_string;
if (m_cali_method == CalibrationMethod::CALI_METHOD_AUTO && curr_obj->get_printer_series() == PrinterSeries::SERIES_X1) {
X1CCalibInfos calib_infos;
for (auto& item : selected_filaments) {
int nozzle_temp = -1;
int bed_temp = -1;
for (auto &item : selected_filaments) {
int nozzle_temp = -1;
int bed_temp = -1;
float max_volumetric_speed = -1;
if (!get_preset_info(item.second->config, plate_type, nozzle_temp, bed_temp, max_volumetric_speed)) {
@ -517,54 +568,93 @@ void PressureAdvanceWizard::on_cali_start()
}
X1CCalibInfos::X1CCalibInfo calib_info;
calib_info.tray_id = item.first;
calib_info.nozzle_diameter = nozzle_dia;
calib_info.filament_id = item.second->filament_id;
calib_info.setting_id = item.second->setting_id;
calib_info.bed_temp = bed_temp;
calib_info.nozzle_temp = nozzle_temp;
calib_info.tray_id = item.first;
calib_info.nozzle_diameter = nozzle_dia;
calib_info.filament_id = item.second->filament_id;
calib_info.setting_id = item.second->setting_id;
calib_info.bed_temp = bed_temp;
calib_info.nozzle_temp = nozzle_temp;
calib_info.max_volumetric_speed = max_volumetric_speed;
calib_infos.calib_datas.push_back(calib_info);
}
CalibUtils::calib_PA(calib_infos, 0, wx_err_string); // mode = 0 for auto
std::string error_message;
wxString wx_err_string;
if (m_cali_method == CalibrationMethod::CALI_METHOD_AUTO) {
CalibUtils::calib_PA(calib_infos, 0, error_message); // mode = 0 for auto
wx_err_string = from_u8(error_message);
} else if (m_cali_method == CalibrationMethod::CALI_METHOD_MANUAL) {
CalibUtils::calib_PA(calib_infos, 1, error_message); // mode = 1 for manual
wx_err_string = from_u8(error_message);
} else {
assert(false);
}
if (!wx_err_string.empty()) {
MessageDialog msg_dlg(nullptr, wx_err_string, wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
}
}
else if (curr_obj->get_printer_series() == PrinterSeries::SERIES_P1P) {
show_step(m_curr_step->next);
} else if (m_cali_method == CalibrationMethod::CALI_METHOD_MANUAL) {
if (selected_filaments.empty()) {
BOOST_LOG_TRIVIAL(warning) << "CaliPreset: selected filaments is empty";
return;
}
else {
int nozzle_temp = -1;
int bed_temp = -1;
float max_volumetric_speed = -1;
if (!get_preset_info(selected_filaments.begin()->second->config, plate_type, nozzle_temp, bed_temp, max_volumetric_speed)) {
BOOST_LOG_TRIVIAL(error) << "CaliPreset: get preset info error";
return;
}
CalibInfo calib_info;
calib_info.dev_id = curr_obj->dev_id;
calib_info.select_ams = "[" + std::to_string(selected_filaments.begin()->first) + "]";
Preset *preset = selected_filaments.begin()->second;
Preset * temp_filament_preset = new Preset(preset->type, preset->name + "_temp");
temp_filament_preset->config = preset->config;
int nozzle_temp = -1;
int bed_temp = -1;
float max_volumetric_speed = -1;
if (!get_preset_info(selected_filaments.begin()->second->config, plate_type, nozzle_temp, bed_temp, max_volumetric_speed)) {
BOOST_LOG_TRIVIAL(error) << "CaliPreset: get preset info error";
return;
calib_info.bed_type = plate_type;
calib_info.process_bar = preset_page->get_sending_progress_bar();
calib_info.printer_prest = preset_page->get_printer_preset(curr_obj, nozzle_dia);
calib_info.print_prest = preset_page->get_print_preset();
calib_info.filament_prest = temp_filament_preset;
wxArrayString values = preset_page->get_custom_range_values();
if (values.size() != 3) {
MessageDialog msg_dlg(nullptr, _L("The input value size must be 3."), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
} else {
values[0].ToDouble(&calib_info.params.start);
values[1].ToDouble(&calib_info.params.end);
values[2].ToDouble(&calib_info.params.step);
}
calib_info.params.mode = preset_page->get_pa_cali_method();
calib_info.params.print_numbers = true;
if (!is_pa_params_valid(calib_info.params))
return;
ManualPaCaliMethod pa_cali_method = ManualPaCaliMethod::PA_LINE;
CalibrationCaliPage *cali_page = (static_cast<CalibrationCaliPage *>(cali_step->page));
if (calib_info.params.mode == CalibMode::Calib_PA_Line)
pa_cali_method = ManualPaCaliMethod::PA_LINE;
else if (calib_info.params.mode == CalibMode::Calib_PA_Pattern)
pa_cali_method = ManualPaCaliMethod::PA_PATTERN;
cali_page->set_pa_cali_image(int(pa_cali_method));
curr_obj->manual_pa_cali_method = pa_cali_method;
CalibUtils::calib_generic_PA(calib_info, wx_err_string);
if (!wx_err_string.empty()) {
MessageDialog msg_dlg(nullptr, wx_err_string, wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
}
preset_page->on_cali_start_job();
}
curr_obj->command_start_extrusion_cali(selected_filaments.begin()->first,
nozzle_temp, bed_temp, max_volumetric_speed, setting_id);
} else {
assert(false);
BOOST_LOG_TRIVIAL(error) << "CaliPreset: unsupported printer type or cali method";
return;
}
show_step(m_curr_step->next);
CalibrationCaliPage* cali_page = (static_cast<CalibrationCaliPage*>(cali_step->page));
cali_page->clear_last_job_status();
}
@ -853,6 +943,7 @@ void FlowRateWizard::on_cali_start(CaliPresetStage stage, float cali_value, Flow
if (!wx_err_string.empty()) {
MessageDialog msg_dlg(nullptr, wx_err_string, wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
}
show_step(m_curr_step->next);
@ -903,9 +994,7 @@ void FlowRateWizard::on_cali_start(CaliPresetStage stage, float cali_value, Flow
calib_info.filament_prest = temp_filament_preset;
if (cali_stage > 0) {
std::string error_message;
CalibUtils::calib_flowrate(cali_stage, calib_info, error_message);
wx_err_string = from_u8(error_message);
CalibUtils::calib_flowrate(cali_stage, calib_info, wx_err_string);
}
else {
wx_err_string = _L("Internal Error") + wxString(": Invalid calibration stage");
@ -917,6 +1006,7 @@ void FlowRateWizard::on_cali_start(CaliPresetStage stage, float cali_value, Flow
if (!wx_err_string.empty()) {
MessageDialog msg_dlg(nullptr, wx_err_string, wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
}
preset_page->on_cali_start_job();
if (temp_filament_preset)
@ -1009,7 +1099,7 @@ void FlowRateWizard::on_cali_save()
std::string message;
if (!save_preset(old_preset_name, into_u8(new_preset_name), key_value_map, message)) {
MessageDialog error_msg_dlg(nullptr, message, wxEmptyString, wxICON_WARNING | wxOK);
MessageDialog error_msg_dlg(nullptr, from_u8(message), wxEmptyString, wxICON_WARNING | wxOK);
error_msg_dlg.ShowModal();
return;
}
@ -1248,12 +1338,11 @@ void MaxVolumetricSpeedWizard::on_cali_start()
calib_info.print_prest = preset_page->get_print_preset();
wxString wx_err_string;
std::string error_message;
CalibUtils::calib_max_vol_speed(calib_info, error_message);
wx_err_string = from_u8(error_message);
CalibUtils::calib_max_vol_speed(calib_info, wx_err_string);
if (!wx_err_string.empty()) {
MessageDialog msg_dlg(nullptr, wx_err_string, wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
}
preset_page->on_cali_start_job();
@ -1288,7 +1377,7 @@ void MaxVolumetricSpeedWizard::on_cali_save()
std::string message;
if (!save_preset(old_preset_name, new_preset_name, key_value_map, message)) {
MessageDialog error_msg_dlg(nullptr, message, wxEmptyString, wxICON_WARNING | wxOK);
MessageDialog error_msg_dlg(nullptr, from_u8(message), wxEmptyString, wxICON_WARNING | wxOK);
error_msg_dlg.ShowModal();
return;
}

View file

@ -105,6 +105,9 @@ class PressureAdvanceWizard : public CalibrationWizard {
public:
PressureAdvanceWizard(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL);
~PressureAdvanceWizard() {};
void on_cali_job_finished(wxString evt_data) override;
protected:
void create_pages();

View file

@ -125,6 +125,17 @@ void CalibrationCaliPage::set_cali_img()
}
}
void CalibrationCaliPage::set_pa_cali_image(int stage)
{
if (m_cali_mode == CalibMode::Calib_PA_Line && m_cali_method == CALI_METHOD_MANUAL) {
if (stage == 0) {
m_picture_panel->set_img(create_scaled_bitmap("fd_calibration_manual", nullptr, 400));
} else if (stage == 1) {
m_picture_panel->set_img(create_scaled_bitmap("fd_pattern_manual", nullptr, 400));
}
}
}
void CalibrationCaliPage::clear_last_job_status()
{
m_is_between_start_and_running = true;
@ -132,6 +143,29 @@ void CalibrationCaliPage::clear_last_job_status()
void CalibrationCaliPage::update(MachineObject* obj)
{
if (this->IsShown()) {
if (obj) {
if (obj->print_status != "RUNNING") {
BOOST_LOG_TRIVIAL(info) << "on_show_cali_page - machine object status:"
<< " dev_id = " << obj->dev_id
<< ", print_type = " << obj->printer_type
<< ", printer_status = " << obj->print_status
<< ", is_connected = " << obj->is_connected()
<< ", m_is_between_start_and_running = " << m_is_between_start_and_running
<< ", cali_finished = " << obj->cali_finished
<< ", cali_version = " << obj->cali_version
<< ", cache_flow_ratio = " << obj->cache_flow_ratio
<< ", sub_task_name = " << obj->subtask_name
<< ", gcode_file_name = " << obj->m_gcode_file
<< ", get_pa_calib_result" << obj->get_pa_calib_result
<< ", get_flow_calib_result" << obj->get_flow_calib_result;
}
}
else {
BOOST_LOG_TRIVIAL(info) << "on_show_cali_page - machine object is nullptr";
}
}
static int get_result_count = 0;
// enable calibration when finished
bool enable_cali = false;

View file

@ -27,6 +27,7 @@ public:
void update_basic_print_data(bool def, float weight = 0.0, int prediction = 0);
void reset_printing_values();
void clear_last_job_status();
void set_pa_cali_image(int stage);
void on_device_connected(MachineObject* obj) override;

View file

@ -5,6 +5,9 @@
#include "libslic3r/Print.hpp"
namespace Slic3r { namespace GUI {
static int PA_LINE = 0;
static int PA_PATTERN = 1;
CaliPresetCaliStagePanel::CaliPresetCaliStagePanel(
wxWindow* parent,
wxWindowID id,
@ -124,6 +127,71 @@ void CaliPresetCaliStagePanel::set_flow_ratio_value(float flow_ratio)
m_flow_ratio_value = flow_ratio;
}
CaliComboBox::CaliComboBox(wxWindow* parent,
wxString title,
wxArrayString values,
int default_index, // default delected id
std::function<void(wxCommandEvent&)> on_value_change,
wxWindowID id,
const wxPoint& pos,
const wxSize& size,
long style)
: wxPanel(parent, id, pos, size, style)
, m_title(title)
, m_on_value_change_call_back(on_value_change)
{
SetBackgroundColour(*wxWHITE);
m_top_sizer = new wxBoxSizer(wxVERTICAL);
m_top_sizer->AddSpacer(PRESET_GAP);
auto combo_title = new Label(this, title);
combo_title->SetFont(Label::Head_14);
combo_title->Wrap(-1);
m_top_sizer->Add(combo_title, 0, wxALL, 0);
m_top_sizer->AddSpacer(FromDIP(10));
m_combo_box = new ComboBox(this, wxID_ANY, "", wxDefaultPosition, CALIBRATION_COMBOX_SIZE, 0, nullptr, wxCB_READONLY);
m_top_sizer->Add(m_combo_box, 0, wxALL, 0);
m_top_sizer->AddSpacer(PRESET_GAP);
this->SetSizer(m_top_sizer);
m_top_sizer->Fit(this);
// set values
for (int i = 0; i < values.size(); ++i) {
m_combo_box->AppendString(values[i]);
}
m_combo_box->SetSelection(default_index);
// bind call back function
if (m_on_value_change_call_back)
m_combo_box->Bind(wxEVT_COMBOBOX, m_on_value_change_call_back);
}
int CaliComboBox::get_selection() const
{
if (m_combo_box)
return m_combo_box->GetSelection();
return 0;
}
wxString CaliComboBox::get_value() const
{
if (m_combo_box)
return m_combo_box->GetValue();
return wxString();
}
void CaliComboBox::set_values(const wxArrayString &values)
{
if (m_combo_box) {
for (int i = 0; i < values.size(); ++i) {
m_combo_box->AppendString(values[i]);
}
m_combo_box->SetSelection(0);
}
}
CaliPresetWarningPanel::CaliPresetWarningPanel(
wxWindow* parent,
wxWindowID id,
@ -704,6 +772,13 @@ void CalibrationPresetPage::create_page(wxWindow* parent)
m_filament_list_panel = new wxPanel(parent);
m_filament_list_panel->SetBackgroundColour(*wxWHITE);
create_filament_list_panel(m_filament_list_panel);
if (m_cali_mode == CalibMode::Calib_PA_Line || m_cali_mode == CalibMode::Calib_PA_Pattern) {
wxArrayString pa_cali_modes;
pa_cali_modes.push_back(_L("Line"));
pa_cali_modes.push_back(_L("Pattern"));
m_pa_cali_method_combox = new CaliComboBox(parent, _L("Method"), pa_cali_modes);
}
m_ext_spool_panel = new wxPanel(parent);
create_ext_spool_panel(m_ext_spool_panel);
@ -719,9 +794,7 @@ void CalibrationPresetPage::create_page(wxWindow* parent)
m_sending_panel->Hide();
if (m_show_custom_range) {
m_custom_range_panel = new CaliPresetCustomRangePanel(parent);
}
m_custom_range_panel = new CaliPresetCustomRangePanel(parent);
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_PRESET);
@ -732,11 +805,10 @@ void CalibrationPresetPage::create_page(wxWindow* parent)
m_top_sizer->Add(m_selection_panel, 0);
m_top_sizer->Add(m_filament_list_panel, 0);
m_top_sizer->Add(m_ext_spool_panel, 0);
m_top_sizer->Add(m_pa_cali_method_combox, 0);
m_top_sizer->Add(m_custom_range_panel, 0);
m_top_sizer->AddSpacer(FromDIP(15));
m_top_sizer->Add(m_warning_panel, 0);
if (m_show_custom_range) {
m_top_sizer->Add(m_custom_range_panel, 0);
m_top_sizer->AddSpacer(FromDIP(15));
}
m_top_sizer->Add(m_tips_panel, 0);
m_top_sizer->AddSpacer(PRESET_GAP);
m_top_sizer->Add(m_sending_panel, 0, wxALIGN_CENTER);
@ -1430,16 +1502,50 @@ void CalibrationPresetPage::set_cali_filament_mode(CalibrationFilamentMode mode)
void CalibrationPresetPage::set_cali_method(CalibrationMethod method)
{
CalibrationWizardPage::set_cali_method(method);
if (method == CalibrationMethod::CALI_METHOD_MANUAL && m_cali_mode == CalibMode::Calib_Flow_Rate) {
wxArrayString steps;
steps.Add(_L("Preset"));
steps.Add(_L("Calibration1"));
steps.Add(_L("Calibration2"));
steps.Add(_L("Record Factor"));
m_step_panel->set_steps_string(steps);
m_step_panel->set_steps(0);
if (m_cali_stage_panel)
m_cali_stage_panel->Show();
if (method == CalibrationMethod::CALI_METHOD_MANUAL) {
if (m_cali_mode == CalibMode::Calib_Flow_Rate) {
wxArrayString steps;
steps.Add(_L("Preset"));
steps.Add(_L("Calibration1"));
steps.Add(_L("Calibration2"));
steps.Add(_L("Record Factor"));
m_step_panel->set_steps_string(steps);
m_step_panel->set_steps(0);
if (m_cali_stage_panel)
m_cali_stage_panel->Show();
if (m_pa_cali_method_combox)
m_pa_cali_method_combox->Show(false);
if (m_custom_range_panel)
m_custom_range_panel->Show(false);
}
else if (m_cali_mode == CalibMode::Calib_PA_Line || m_cali_mode == CalibMode::Calib_PA_Pattern) {
if (m_cali_stage_panel)
m_cali_stage_panel->Show(false);
if (m_pa_cali_method_combox)
m_pa_cali_method_combox->Show();
if (m_custom_range_panel) {
wxArrayString titles;
titles.push_back(_L("From k Value"));
titles.push_back(_L("To k Value"));
titles.push_back(_L("Step value"));
m_custom_range_panel->set_titles(titles);
wxArrayString values;
Preset* printer_preset = get_printer_preset(curr_obj, get_nozzle_value());
int extruder_type = printer_preset->config.opt_enum("extruder_type", 0);
values.push_back(_L("0"));
values.push_back(_L("0.5"));
values.push_back(_L("0.005"));
m_custom_range_panel->set_values(values);
m_custom_range_panel->set_unit(_L(""));
m_custom_range_panel->Show();
}
}
}
else {
wxArrayString steps;
@ -1450,6 +1556,10 @@ void CalibrationPresetPage::set_cali_method(CalibrationMethod method)
m_step_panel->set_steps(0);
if (m_cali_stage_panel)
m_cali_stage_panel->Show(false);
if (m_custom_range_panel)
m_custom_range_panel->Show(false);
if (m_pa_cali_method_combox)
m_pa_cali_method_combox->Show(false);
}
}
@ -1847,12 +1957,26 @@ std::string CalibrationPresetPage::get_print_preset_name()
wxArrayString CalibrationPresetPage::get_custom_range_values()
{
if (m_show_custom_range && m_custom_range_panel) {
if (m_custom_range_panel) {
return m_custom_range_panel->get_values();
}
return wxArrayString();
}
CalibMode CalibrationPresetPage::get_pa_cali_method()
{
if (m_pa_cali_method_combox) {
int selected_mode = m_pa_cali_method_combox->get_selection();
if (selected_mode == PA_LINE) {
return CalibMode::Calib_PA_Line;
}
else if (selected_mode == PA_PATTERN) {
return CalibMode::Calib_PA_Pattern;
}
}
return CalibMode::Calib_PA_Line;
}
MaxVolumetricSpeedPresetPage::MaxVolumetricSpeedPresetPage(
wxWindow *parent, CalibMode cali_mode, bool custom_range, wxWindowID id, const wxPoint &pos, const wxSize &size, long style)
: CalibrationPresetPage(parent, cali_mode, custom_range, id, pos, size, style)
@ -1861,7 +1985,7 @@ MaxVolumetricSpeedPresetPage::MaxVolumetricSpeedPresetPage(
wxArrayString titles;
titles.push_back(_L("From Volumetric Speed"));
titles.push_back(_L("To Volumetric Speed"));
titles.push_back(_L("Step"));
titles.push_back(_L("Step value"));
m_custom_range_panel->set_titles(titles);
m_custom_range_panel->set_unit(_L("mm\u00B3/s"));

View file

@ -40,6 +40,30 @@ protected:
float m_flow_ratio_value;
};
class CaliComboBox : public wxPanel
{
public:
CaliComboBox(wxWindow *parent,
wxString title,
wxArrayString values,
int default_index = 0, // default delected id
std::function<void(wxCommandEvent &)> on_value_change = nullptr,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL);
int get_selection() const;
wxString get_value() const;
void set_values(const wxArrayString& values);
private:
wxBoxSizer* m_top_sizer;
wxString m_title;
ComboBox* m_combo_box;
std::function<void(wxCommandEvent&)> m_on_value_change_call_back;
};
class CaliPresetWarningPanel : public wxPanel
{
public:
@ -181,6 +205,7 @@ public:
std::string get_print_preset_name();
wxArrayString get_custom_range_values();
CalibMode get_pa_cali_method();
CaliPresetPageStatus get_page_status() { return m_page_status; }
protected:
@ -227,6 +252,7 @@ protected:
CaliPresetPageStatus get_status() { return m_page_status; }
CaliPageStepGuide* m_step_panel{ nullptr };
CaliComboBox * m_pa_cali_method_combox{nullptr};
CaliPresetCaliStagePanel* m_cali_stage_panel { nullptr };
wxPanel* m_selection_panel { nullptr };
wxPanel* m_filament_from_panel { nullptr };

View file

@ -462,10 +462,10 @@ void CaliPASaveManualPanel::create_panel(wxWindow* parent)
auto complete_text_panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
complete_text_panel->SetBackgroundColour(*wxWHITE);
wxBoxSizer* complete_text_sizer = new wxBoxSizer(wxVERTICAL);
auto complete_text = new Label(complete_text_panel, _L("Please find the best line on your plate"));
complete_text->SetFont(Label::Head_14);
complete_text->Wrap(CALIBRATION_TEXT_MAX_LENGTH);
complete_text_sizer->Add(complete_text, 0);
m_complete_text = new Label(complete_text_panel, _L("Please find the best line on your plate"));
m_complete_text->SetFont(Label::Head_14);
m_complete_text->Wrap(CALIBRATION_TEXT_MAX_LENGTH);
complete_text_sizer->Add(m_complete_text, 0);
complete_text_panel->SetSizer(complete_text_sizer);
m_top_sizer->Add(complete_text_panel, 0, wxEXPAND, 0);
@ -523,6 +523,21 @@ void CaliPASaveManualPanel::set_save_img() {
}
}
void CaliPASaveManualPanel::set_pa_cali_method(ManualPaCaliMethod method)
{
if (method == ManualPaCaliMethod::PA_LINE) {
m_complete_text->SetLabel(_L("Please find the best line on your plate"));
set_save_img();
} else if (method == ManualPaCaliMethod::PA_PATTERN) {
m_complete_text->SetLabel(_L("Please find the cornor with perfect degree of extrusion"));
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
m_picture_panel->set_img(create_scaled_bitmap("fd_pattern_manual_result_CN", nullptr, 350));
} else {
m_picture_panel->set_img(create_scaled_bitmap("fd_pattern_manual_result", nullptr, 350));
}
}
}
void CaliPASaveManualPanel::set_default_name(const wxString& name) {
m_save_name_input->GetTextCtrl()->SetValue(name);
}
@ -610,10 +625,10 @@ void CaliPASaveP1PPanel::create_panel(wxWindow* parent)
auto complete_text_panel = new wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
complete_text_panel->SetBackgroundColour(*wxWHITE);
wxBoxSizer* complete_text_sizer = new wxBoxSizer(wxVERTICAL);
auto complete_text = new Label(complete_text_panel, _L("Please find the best line on your plate"));
complete_text->SetFont(Label::Head_14);
complete_text->Wrap(CALIBRATION_TEXT_MAX_LENGTH);
complete_text_sizer->Add(complete_text, 0, wxEXPAND);
m_complete_text = new Label(complete_text_panel, _L("Please find the best line on your plate"));
m_complete_text->SetFont(Label::Head_14);
m_complete_text->Wrap(CALIBRATION_TEXT_MAX_LENGTH);
complete_text_sizer->Add(m_complete_text, 0, wxEXPAND);
complete_text_panel->SetSizer(complete_text_sizer);
m_top_sizer->Add(complete_text_panel, 0, wxEXPAND, 0);
@ -662,6 +677,22 @@ void CaliPASaveP1PPanel::set_save_img() {
}
}
void CaliPASaveP1PPanel::set_pa_cali_method(ManualPaCaliMethod method)
{
if (method == ManualPaCaliMethod::PA_LINE) {
m_complete_text->SetLabel(_L("Please find the best line on your plate"));
set_save_img();
}
else if (method == ManualPaCaliMethod::PA_PATTERN) {
m_complete_text->SetLabel(_L("Please find the cornor with perfect degree of extrusion"));
if (wxGetApp().app_config->get_language_code() == "zh-cn") {
m_picture_panel->set_img(create_scaled_bitmap("fd_pattern_manual_result_CN", nullptr, 350));
} else {
m_picture_panel->set_img(create_scaled_bitmap("fd_pattern_manual_result", nullptr, 350));
}
}
}
bool CaliPASaveP1PPanel::get_result(float* out_k, float* out_n){
// Check if the value is valid
if (!CalibUtils::validate_input_k_value(m_k_val->GetTextCtrl()->GetValue(), out_k)) {
@ -808,6 +839,7 @@ void CalibrationPASavePage::sync_cali_result(MachineObject* obj)
void CalibrationPASavePage::show_panels(CalibrationMethod method, const PrinterSeries printer_ser) {
if (printer_ser == PrinterSeries::SERIES_X1) {
if (method == CalibrationMethod::CALI_METHOD_MANUAL) {
m_manual_panel->set_pa_cali_method(curr_obj->manual_pa_cali_method);
m_manual_panel->Show();
m_auto_panel->Show(false);
}
@ -820,10 +852,12 @@ void CalibrationPASavePage::show_panels(CalibrationMethod method, const PrinterS
else if (printer_ser == PrinterSeries::SERIES_P1P) {
m_auto_panel->Show(false);
m_manual_panel->Show(false);
m_p1p_panel->set_pa_cali_method(curr_obj->manual_pa_cali_method);
m_p1p_panel->Show();
} else {
m_auto_panel->Show(false);
m_manual_panel->Show(false);
m_p1p_panel->set_pa_cali_method(curr_obj->manual_pa_cali_method);
m_p1p_panel->Show();
assert(false);
}
@ -1158,10 +1192,10 @@ void CalibrationFlowCoarseSavePage::create_page(wxWindow* parent)
coarse_block_items.Add(std::to_string(-20 + (i * 5)));
}
m_optimal_block_coarse->Set(coarse_block_items);
auto coarse_calc_result_text = new Label(parent, "");
m_coarse_calc_result_text = new Label(parent, "");
coarse_value_sizer->Add(coarse_value_text, 0, 0);
coarse_value_sizer->Add(m_optimal_block_coarse, 0, 0);
coarse_value_sizer->Add(coarse_calc_result_text, 0);
coarse_value_sizer->Add(m_coarse_calc_result_text, 0);
m_top_sizer->Add(coarse_value_sizer, 0, 0, 0);
m_top_sizer->AddSpacer(FromDIP(20));
@ -1169,16 +1203,16 @@ void CalibrationFlowCoarseSavePage::create_page(wxWindow* parent)
checkBox_panel->SetBackgroundColour(*wxWHITE);
auto cb_sizer = new wxBoxSizer(wxHORIZONTAL);
checkBox_panel->SetSizer(cb_sizer);
auto checkBox_skip_calibration = new CheckBox(checkBox_panel);
cb_sizer->Add(checkBox_skip_calibration);
m_checkBox_skip_calibration = new CheckBox(checkBox_panel);
cb_sizer->Add(m_checkBox_skip_calibration);
auto cb_text = new Label(checkBox_panel, _L("Skip Calibration2"));
cb_sizer->Add(cb_text);
cb_text->Bind(wxEVT_LEFT_DOWN, [this, checkBox_skip_calibration](auto&) {
checkBox_skip_calibration->SetValue(!checkBox_skip_calibration->GetValue());
cb_text->Bind(wxEVT_LEFT_DOWN, [this](auto&) {
m_checkBox_skip_calibration->SetValue(!m_checkBox_skip_calibration->GetValue());
wxCommandEvent event(wxEVT_TOGGLEBUTTON);
event.SetEventObject(checkBox_skip_calibration);
checkBox_skip_calibration->GetEventHandler()->ProcessEvent(event);
event.SetEventObject(m_checkBox_skip_calibration);
m_checkBox_skip_calibration->GetEventHandler()->ProcessEvent(event);
});
m_top_sizer->Add(checkBox_panel, 0, 0, 0);
@ -1201,8 +1235,8 @@ void CalibrationFlowCoarseSavePage::create_page(wxWindow* parent)
m_top_sizer->AddSpacer(FromDIP(20));
checkBox_skip_calibration->Bind(wxEVT_TOGGLEBUTTON, [this, save_panel, checkBox_skip_calibration](wxCommandEvent& e) {
if (checkBox_skip_calibration->GetValue()) {
m_checkBox_skip_calibration->Bind(wxEVT_TOGGLEBUTTON, [this, save_panel](wxCommandEvent &e) {
if (m_checkBox_skip_calibration->GetValue()) {
m_skip_fine_calibration = true;
save_panel->Show();
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_FLOW_COARSE_SAVE);
@ -1219,9 +1253,9 @@ void CalibrationFlowCoarseSavePage::create_page(wxWindow* parent)
e.Skip();
});
m_optimal_block_coarse->Bind(wxEVT_COMBOBOX, [this, coarse_calc_result_text](auto& e) {
m_optimal_block_coarse->Bind(wxEVT_COMBOBOX, [this](auto& e) {
m_coarse_flow_ratio = m_curr_flow_ratio * (100.0f + stof(m_optimal_block_coarse->GetValue().ToStdString())) / 100.0f;
coarse_calc_result_text->SetLabel(wxString::Format(_L("flow ratio : %s "), std::to_string(m_coarse_flow_ratio)));
m_coarse_calc_result_text->SetLabel(wxString::Format(_L("flow ratio : %s "), std::to_string(m_coarse_flow_ratio)));
});
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_COARSE_SAVE);
@ -1237,8 +1271,15 @@ void CalibrationFlowCoarseSavePage::set_save_img() {
}
}
void CalibrationFlowCoarseSavePage::set_default_name(const wxString& name) {
void CalibrationFlowCoarseSavePage::set_default_options(const wxString& name) {
m_optimal_block_coarse->SetSelection(-1);
m_coarse_calc_result_text->SetLabelText("");
m_checkBox_skip_calibration->SetValue(false);
m_save_name_input->GetTextCtrl()->SetValue(name);
wxCommandEvent event(wxEVT_TOGGLEBUTTON);
event.SetEventObject(m_checkBox_skip_calibration);
m_checkBox_skip_calibration->GetEventHandler()->ProcessEvent(event);
}
bool CalibrationFlowCoarseSavePage::is_skip_fine_calibration() {
@ -1272,7 +1313,7 @@ bool CalibrationFlowCoarseSavePage::Show(bool show) {
assert(curr_obj->selected_cali_preset.size() <= 1);
if (!curr_obj->selected_cali_preset.empty()) {
wxString default_name = get_default_name(curr_obj->selected_cali_preset[0].name, CalibMode::Calib_Flow_Rate);
set_default_name(default_name);
set_default_options(default_name);
set_curr_flow_ratio(curr_obj->cache_flow_ratio);
}
}
@ -1337,10 +1378,10 @@ void CalibrationFlowFineSavePage::create_page(wxWindow* parent)
fine_block_items.Add(std::to_string(-9 + (i)));
}
m_optimal_block_fine->Set(fine_block_items);
auto fine_calc_result_text = new Label(parent, "");
m_fine_calc_result_text = new Label(parent, "");
fine_value_sizer->Add(fine_value_text, 0, 0);
fine_value_sizer->Add(m_optimal_block_fine, 0, 0);
fine_value_sizer->Add(fine_calc_result_text, 0);
fine_value_sizer->Add(m_fine_calc_result_text, 0);
m_top_sizer->Add(fine_value_sizer, 0, 0, 0);
m_top_sizer->AddSpacer(FromDIP(20));
@ -1354,9 +1395,9 @@ void CalibrationFlowFineSavePage::create_page(wxWindow* parent)
m_top_sizer->AddSpacer(FromDIP(20));
m_optimal_block_fine->Bind(wxEVT_COMBOBOX, [this, fine_calc_result_text](auto& e) {
m_optimal_block_fine->Bind(wxEVT_COMBOBOX, [this](auto& e) {
m_fine_flow_ratio = m_curr_flow_ratio * (100.0f + stof(m_optimal_block_fine->GetValue().ToStdString())) / 100.0f;
fine_calc_result_text->SetLabel(wxString::Format(_L("flow ratio : %s "), std::to_string(m_fine_flow_ratio)));
m_fine_calc_result_text->SetLabel(wxString::Format(_L("flow ratio : %s "), std::to_string(m_fine_flow_ratio)));
});
m_action_panel = new CaliPageActionPanel(parent, m_cali_mode, CaliPageType::CALI_PAGE_FINE_SAVE);
@ -1371,7 +1412,9 @@ void CalibrationFlowFineSavePage::set_save_img() {
}
}
void CalibrationFlowFineSavePage::set_default_name(const wxString& name) {
void CalibrationFlowFineSavePage::set_default_options(const wxString &name) {
m_optimal_block_fine->SetSelection(-1);
m_fine_calc_result_text->SetLabelText("");
m_save_name_input->GetTextCtrl()->SetValue(name);
}
@ -1402,7 +1445,7 @@ bool CalibrationFlowFineSavePage::Show(bool show) {
assert(curr_obj->selected_cali_preset.size() <= 1);
if (!curr_obj->selected_cali_preset.empty()) {
wxString default_name = get_default_name(curr_obj->selected_cali_preset[0].name, CalibMode::Calib_Flow_Rate);
set_default_name(default_name);
set_default_options(default_name);
set_curr_flow_ratio(curr_obj->cache_flow_ratio);
}
}

View file

@ -119,6 +119,7 @@ public:
long style = wxTAB_TRAVERSAL);
void create_panel(wxWindow* parent);
void set_save_img();
void set_pa_cali_method(ManualPaCaliMethod method);
void set_machine_obj(MachineObject* obj) { m_obj = obj; }
@ -130,6 +131,7 @@ public:
protected:
wxBoxSizer* m_top_sizer;
Label * m_complete_text;
CaliPagePicture* m_picture_panel;
::TextInput* m_save_name_input;
::TextInput* m_k_val;
@ -149,11 +151,13 @@ public:
long style = wxTAB_TRAVERSAL);
void create_panel(wxWindow* parent);
void set_save_img();
void set_pa_cali_method(ManualPaCaliMethod method);
bool get_result(float* out_k, float* out_n);
protected:
wxBoxSizer* m_top_sizer;
Label * m_complete_text;
CaliPagePicture* m_picture_panel;
::TextInput* m_k_val;
::TextInput* m_n_val;
@ -223,7 +227,7 @@ public:
void create_page(wxWindow* parent);
void set_save_img();
void set_default_name(const wxString& name);
void set_default_options(const wxString &name);
bool is_skip_fine_calibration();
@ -239,6 +243,9 @@ protected:
ComboBox* m_optimal_block_coarse;
TextInput* m_save_name_input;
Label* m_coarse_calc_result_text;
CheckBox* m_checkBox_skip_calibration;
bool m_skip_fine_calibration = false;
float m_curr_flow_ratio;
float m_coarse_flow_ratio;
@ -252,7 +259,7 @@ public:
void create_page(wxWindow* parent);
void set_save_img();
void set_default_name(const wxString& name);
void set_default_options(const wxString &name);
void set_curr_flow_ratio(float value);
@ -266,6 +273,8 @@ protected:
ComboBox* m_optimal_block_fine;
TextInput* m_save_name_input;
Label* m_fine_calc_result_text;
float m_curr_flow_ratio;
float m_fine_flow_ratio;
};

View file

@ -155,17 +155,11 @@ void CalibrationPAStartPage::on_device_connected(MachineObject* obj)
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false);
}
}
else if (obj->get_printer_series() == PrinterSeries::SERIES_P1P) {
else if (obj->get_printer_series() == PrinterSeries::SERIES_P1P || obj->get_printer_arch() == PrinterArch::ARCH_I3) {
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_MANAGE_RESULT, false);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_AUTO_CALI, false);
m_action_panel->show_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, true);
if (!obj->is_function_supported(PrinterFunction::FUNC_EXTRUSION_CALI)) {
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, true);
}
else {
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, false);
}
m_action_panel->bind_button(CaliPageActionType::CALI_ACTION_MANUAL_CALI, false);
}
//is support auto cali

View file

@ -109,39 +109,6 @@ void ConfigManipulation::check_nozzle_temperature_initial_layer_range(DynamicPri
}
}
void ConfigManipulation::check_bed_temperature_difference(int bed_type, DynamicPrintConfig* config)
{
if (is_msg_dlg_already_exist)
return;
if (config->has("bed_temperature_difference") && config->has("temperature_vitrification")) {
int bed_temp_difference = config->opt_int("bed_temperature_difference", 0);
int vitrification = config->opt_int("temperature_vitrification", 0);
const ConfigOptionInts* bed_temp_1st_layer_opt = config->option<ConfigOptionInts>(get_bed_temp_1st_layer_key((BedType)bed_type));
const ConfigOptionInts* bed_temp_opt = config->option<ConfigOptionInts>(get_bed_temp_key((BedType)bed_type));
if (bed_temp_1st_layer_opt != nullptr && bed_temp_opt != nullptr) {
int first_layer_bed_temp = bed_temp_1st_layer_opt->get_at(0);
int bed_temp = bed_temp_opt->get_at(0);
if (first_layer_bed_temp - bed_temp > bed_temp_difference) {
const wxString msg_text = wxString::Format(_L("Bed temperature of other layer is lower than bed temperature of initial layer for more than %d degree centigrade.\nThis may cause model broken free from build plate during printing"), bed_temp_difference);
MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK);
is_msg_dlg_already_exist = true;
dialog.ShowModal();
is_msg_dlg_already_exist = false;
}
if (first_layer_bed_temp > vitrification || bed_temp > vitrification) {
const wxString msg_text = wxString::Format(
_L("Bed temperature is higher than vitrification temperature of this filament.\nThis may cause nozzle blocked and printing failure\nPlease keep the printer open during the printing process to ensure air circulation or reduce the temperature of the hot bed"));
MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK);
is_msg_dlg_already_exist = true;
dialog.ShowModal();
is_msg_dlg_already_exist = false;
}
}
}
}
void ConfigManipulation::check_filament_max_volumetric_speed(DynamicPrintConfig *config)
{
@ -163,6 +130,32 @@ void ConfigManipulation::check_filament_max_volumetric_speed(DynamicPrintConfig
}
void ConfigManipulation::check_chamber_temperature(DynamicPrintConfig* config)
{
const static std::map<std::string, int>recommend_temp_map = {
{"PLA",45},
{"PLA-CF",45},
{"PVA",45},
{"TPU",50},
{"PETG",55},
{"PETG-CF",55}
};
bool support_chamber_temp_control=GUI::wxGetApp().preset_bundle->printers.get_selected_preset().config.opt_bool("support_chamber_temp_control");
if (support_chamber_temp_control&&config->has("chamber_temperatures")) {
std::string filament_type = config->option<ConfigOptionStrings>("filament_type")->get_at(0);
auto iter = recommend_temp_map.find(filament_type);
if (iter!=recommend_temp_map.end()) {
if (iter->second < config->option<ConfigOptionInts>("chamber_temperatures")->get_at(0)) {
wxString msg_text = wxString::Format(_L("Current chamber temperature is higher than the material's safe temperature,it may result in material softening and clogging.The maximum safe temperature for the material is %d"), iter->second);
MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK);
is_msg_dlg_already_exist = true;
dialog.ShowModal();
is_msg_dlg_already_exist = false;
}
}
}
}
void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, const bool is_global_config)
{
// #ys_FIXME_to_delete
@ -285,6 +278,12 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
config->opt_enum<TimelapseType>("timelapse_type") == TimelapseType::tlTraditional))
{
wxString msg_text = _(L("Spiral mode only works when wall loops is 1, support is disabled, top shell layers is 0, sparse infill density is 0 and timelapse type is traditional."));
auto printer_structure_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure");
if (printer_structure_opt && printer_structure_opt->value == PrinterStructure::psI3) {
msg_text += _(L(" But machines with I3 structure will not generate timelapse videos."));
}
if (is_global_config)
msg_text += "\n\n" + _(L("Change these settings automatically? \n"
"Yes - Change these settings and enable spiral mode automatically\n"

View file

@ -76,8 +76,8 @@ public:
//BBS: FFF filament nozzle temperature range
void check_nozzle_temperature_range(DynamicPrintConfig* config);
void check_nozzle_temperature_initial_layer_range(DynamicPrintConfig* config);
void check_bed_temperature_difference(int bed_type, DynamicPrintConfig* config);
void check_filament_max_volumetric_speed(DynamicPrintConfig *config);
void check_chamber_temperature(DynamicPrintConfig* config);
void set_is_BBL_Printer(bool is_bbl_printer) { is_BBL_Printer = is_bbl_printer; };
// SLA print
void update_print_sla_config(DynamicPrintConfig* config, const bool is_global_config = false);

View file

@ -8,7 +8,6 @@ namespace Slic3r { namespace GUI {
ConnectPrinterDialog::ConnectPrinterDialog(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos, const wxSize &size, long style)
: DPIDialog(parent, id, _L("ConnectPrinter(LAN)"), pos, size, style)
{
init_bitmap();
SetBackgroundColour(*wxWHITE);
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
@ -86,7 +85,7 @@ ConnectPrinterDialog::ConnectPrinterDialog(wxWindow *parent, wxWindowID id, cons
wxBoxSizer *sizer_diagram;
sizer_diagram = new wxBoxSizer(wxHORIZONTAL);
m_bitmap_diagram = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(340), FromDIP(190)), 0);
m_bitmap_diagram = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(340), -1), 0);
m_bitmap_diagram->SetBitmap(m_diagram_img);
sizer_diagram->Add(m_bitmap_diagram);
@ -117,19 +116,48 @@ void ConnectPrinterDialog::init_bitmap()
{
AppConfig *config = get_app_config();
std::string language = config->get("language");
if (language == "zh_CN") {
m_diagram_bmp = create_scaled_bitmap("input_access_code_cn", nullptr, 190);
if (m_obj) {
if (m_obj->printer_type == "C11" || m_obj->printer_type == "C12") {
m_diagram_bmp = create_scaled_bitmap("input_accesscode_help2", nullptr, 190);
}
else if (m_obj->printer_type == "BL-P001" || m_obj->printer_type == "BL-P002" || m_obj->printer_type == "C13") {
if (language == "zh_CN") {
m_diagram_bmp = create_scaled_bitmap("input_access_code_cn", nullptr, 190);
}
else {
m_diagram_bmp = create_scaled_bitmap("input_access_code_en", nullptr, 190);
}
}
else if (m_obj->printer_type == "N1") {
if (language == "zh_CN") {
m_diagram_bmp = create_scaled_bitmap("input_access_code_n1_cn", nullptr, 250);
}
else {
m_diagram_bmp = create_scaled_bitmap("input_access_code_n1_en", nullptr, 250);
}
}
}
else{
m_diagram_bmp = create_scaled_bitmap("input_access_code_en", nullptr, 190);
else {
if (language == "zh_CN") {
m_diagram_bmp = create_scaled_bitmap("input_access_code_cn", nullptr, 190);
}
else {
m_diagram_bmp = create_scaled_bitmap("input_access_code_en", nullptr, 190);
}
}
m_diagram_img = m_diagram_bmp.ConvertToImage();
m_diagram_img.Rescale(FromDIP(340), FromDIP(190));
auto bmp_size = m_diagram_bmp.GetSize();
float scale = (float)FromDIP(340) / (float)bmp_size.x;
m_diagram_img.Rescale(FromDIP(340), bmp_size.y * scale);
m_bitmap_diagram->SetBitmap(m_diagram_img);
Fit();
}
void ConnectPrinterDialog::set_machine_object(MachineObject* obj)
{
m_obj = obj;
init_bitmap();
}
void ConnectPrinterDialog::on_input_enter(wxCommandEvent& evt)

View file

@ -34,7 +34,7 @@ protected:
wxBitmap m_diagram_bmp;
wxImage m_diagram_img;
MachineObject* m_obj;
MachineObject* m_obj{ nullptr };
wxString m_input_access_code;
public:
ConnectPrinterDialog(wxWindow * parent,

View file

@ -21,7 +21,7 @@
namespace pt = boost::property_tree;
const int PRINTING_STAGE_COUNT = 20;
const int PRINTING_STAGE_COUNT = 32;
std::string PRINTING_STAGE_STR[PRINTING_STAGE_COUNT] = {
"printing",
"bed_leveling",
@ -42,7 +42,19 @@ std::string PRINTING_STAGE_STR[PRINTING_STAGE_COUNT] = {
"user_pause",
"toolhead_shell_off_pause",
"scanner_laser_para_cali",
"extruder_absolute_flow_cali"
"extruder_absolute_flow_cali",
"hotend_temperature_error_pause", // 20
"heated_bed_temperature_error_pause",
"filament_unloading",
"skip_step_pause",
"filament_loading",
"motor_noise_calibration",
"ams_lost_pause",
"heat_break_fan_pause",
"chamber_temperature_control_error_pause",
"chamber_cooling",
"user_insert_gcode_pause",
"motor_noise_showoff"
};
@ -97,6 +109,26 @@ wxString get_stage_string(int stage)
return _L("Paused due to nozzle temperature malfunction");
case 21:
return _L("Paused due to heat bed temperature malfunction");
case 22:
return _L("Filament unloading");
case 23:
return _L("Skip step pause");
case 24:
return _L("Filament loading");
case 25:
return _L("Motor noise calibration");
case 26:
return _L("Paused due to AMS lost");
case 27:
return _L("Paused due to low speed of the heat break fan");
case 28:
return _L("Paused due to chamber temperature control error");
case 29:
return _L("Cooling chamber");
case 30:
return _L("Paused by the Gcode inserted by user");
case 31:
return _L("Motor noise showoff");
default:
;
}
@ -139,6 +171,18 @@ void split_string(std::string s, std::vector<std::string>& v) {
v.push_back(t);
}
PrinterArch get_printer_arch_by_str(std::string arch_str)
{
if (arch_str == "i3") {
return PrinterArch::ARCH_I3;
}
else if (arch_str == "core_xy") {
return PrinterArch::ARCH_CORE_XY;
}
return PrinterArch::ARCH_CORE_XY;
}
void AmsTray::update_color_from_str(std::string color)
{
if (color.empty()) return;
@ -241,10 +285,7 @@ bool HMSItem::parse_hms_info(unsigned attr, unsigned code)
{
bool result = true;
unsigned int model_id_int = (attr >> 24) & 0xFF;
if (model_id_int < (unsigned) MODULE_MAX)
this->module_id = (ModuleID)model_id_int;
else
this->module_id = MODULE_UKNOWN;
this->module_id = (ModuleID)model_id_int;
this->module_num = (attr >> 16) & 0xFF;
this->part_id = (attr >> 8) & 0xFF;
this->reserved = (attr >> 0) & 0xFF;
@ -420,7 +461,7 @@ bool MachineObject::is_high_printer_type()
PrinterSeries MachineObject::get_printer_series() const
{
if (printer_type == "BL-P001" || printer_type == "BL-P002")
if (printer_type == "BL-P001" || printer_type == "BL-P002" || printer_type == "C13")
return PrinterSeries::SERIES_X1;
else if (printer_type == "C11" || printer_type == "C12")
return PrinterSeries::SERIES_P1P;
@ -428,6 +469,11 @@ PrinterSeries MachineObject::get_printer_series() const
return PrinterSeries::SERIES_P1P;
}
PrinterArch MachineObject::get_printer_arch() const
{
return DeviceManager::get_printer_arch(printer_type);
}
MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string id, std::string ip)
:dev_name(name),
dev_id(id),
@ -448,6 +494,7 @@ MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string
bed_temp = 0.0f;
bed_temp_target = 0.0f;
chamber_temp = 0.0f;
chamber_temp_target = 0.0f;
frame_temp = 0.0f;
/* ams fileds */
@ -693,7 +740,7 @@ bool MachineObject::is_U0_firmware()
bool MachineObject::is_support_ams_mapping()
{
if (get_printer_series() == PrinterSeries::SERIES_X1) {
if (get_printer_series() == PrinterSeries::SERIES_X1 && printer_type != "C13") {
AppConfig* config = Slic3r::GUI::wxGetApp().app_config;
if (config) {
if (config->get("check_ams_version") == "0")
@ -725,6 +772,27 @@ bool MachineObject::is_support_ams_mapping()
}
}
bool MachineObject::is_support_command_ams_switch()
{
auto ota_ver_it = module_vers.find("ota");
if (ota_ver_it != module_vers.end()) {
if (printer_type == "BL-P001" || printer_type == "BL-P002") {
if (ota_ver_it->second.sw_ver.compare("01.05.06.01") < 0) {
return false;
}
}else if (printer_type == "C11" || printer_type == "C12") {
if (ota_ver_it->second.sw_ver.compare("01.02.99.10") < 0) {
return false;
}
}
}
return true;
}
bool MachineObject::is_support_ams_mapping_version(std::string module, std::string version)
{
bool result = true;
@ -1311,7 +1379,15 @@ void MachineObject::parse_status(int flag)
ams_auto_switch_filament_flag = ((flag >> 10) & 0x1) != 0;
}
if (xcam_prompt_sound_hold_count > 0)
xcam_prompt_sound_hold_count--;
else {
xcam_allow_prompt_sound = ((flag >> 17) & 0x1) != 0;
}
sdcard_state = MachineObject::SdcardState((flag >> 8) & 0x11);
network_wired = ((flag >> 18) & 0x1) != 0;
}
PrintingSpeedLevel MachineObject::_parse_printing_speed_lvl(int lvl)
@ -1381,48 +1457,69 @@ void MachineObject::parse_version_func()
auto rv1126_version = module_vers.find("rv1126");
if (get_printer_series() == PrinterSeries::SERIES_X1) {
if (ota_version != module_vers.end()) {
if (ota_version->second.sw_ver.compare("01.01.01.00") <= 0) {
ams_support_remain = false;
ams_support_auto_switch_filament_flag = false;
is_xcam_buildplate_supported = false;
xcam_support_recovery_step_loss = false;
is_support_send_to_sdcard = false;
is_support_1080dpi = false;
is_support_ai_monitoring = false;
is_support_ams_humidity = false;
} else {
ams_support_remain = true;
ams_support_auto_switch_filament_flag = true;
is_xcam_buildplate_supported = true;
xcam_support_recovery_step_loss = true;
is_support_send_to_sdcard = true;
is_support_1080dpi = true;
is_support_ai_monitoring = true;
is_support_ams_humidity = true;
}
if (ota_version != module_vers.end()) {
if (firmware_type == PrinterFirmwareType::FIRMWARE_TYPE_PRODUCTION) {
local_use_ssl_for_mqtt = ota_version->second.sw_ver.compare("01.03.01.04") >= 0;
}
if (lifecycle == PrinterFirmwareType::FIRMWARE_TYPE_PRODUCTION) {
is_support_mqtt_alive = ota_version->second.sw_ver.compare("01.05.06.05") >= 0;
}
else if (lifecycle == PrinterFirmwareType::FIRMWARE_TYPE_ENGINEER) {
is_support_mqtt_alive = ota_version->second.sw_ver.compare("00.03.10.05") >= 0;
if (printer_type != "C13") {
if (ota_version->second.sw_ver.compare("01.01.01.00") <= 0) {
ams_support_remain = false;
ams_support_auto_switch_filament_flag = false;
is_xcam_buildplate_supported = false;
xcam_support_recovery_step_loss = false;
is_support_send_to_sdcard = false;
is_support_1080dpi = false;
is_support_ai_monitoring = false;
is_support_ams_humidity = false;
}
else {
is_support_mqtt_alive = ota_version->second.sw_ver.compare("01.05.06.05") >= 0;
ams_support_remain = true;
ams_support_auto_switch_filament_flag = true;
is_xcam_buildplate_supported = true;
xcam_support_recovery_step_loss = true;
is_support_send_to_sdcard = true;
is_support_1080dpi = true;
is_support_ai_monitoring = true;
is_support_ams_humidity = true;
}
is_support_remote_tunnel = true;
is_support_tunnel_mqtt = (ota_version->second.sw_ver.compare("01.05.06.06") >= 0
|| (rv1126_version != module_vers.end() && rv1126_version->second.sw_ver.compare("00.00.21.20") >= 0));
if (ota_version != module_vers.end()) {
if (firmware_type == PrinterFirmwareType::FIRMWARE_TYPE_PRODUCTION) {
local_use_ssl_for_mqtt = ota_version->second.sw_ver.compare("01.03.01.04") >= 0;
}
if (lifecycle == PrinterFirmwareType::FIRMWARE_TYPE_PRODUCTION) {
is_support_mqtt_alive = ota_version->second.sw_ver.compare("01.05.06.05") >= 0;
}
else if (lifecycle == PrinterFirmwareType::FIRMWARE_TYPE_ENGINEER) {
is_support_mqtt_alive = ota_version->second.sw_ver.compare("00.03.10.05") >= 0;
}
else {
is_support_mqtt_alive = ota_version->second.sw_ver.compare("01.05.06.05") >= 0;
}
is_support_remote_tunnel = true;
is_support_tunnel_mqtt = (ota_version->second.sw_ver.compare("01.05.06.06") >= 0
|| (rv1126_version != module_vers.end() && rv1126_version->second.sw_ver.compare("00.00.21.20") >= 0));
}
local_camera_proto = local_rtsp_url.empty() ? -1 : local_rtsp_url == "disable" ? 0
: boost::algorithm::starts_with(local_rtsp_url, "rtsps") ? 2 : 3;
file_proto = 2;
}
else {
ams_support_remain = true;
ams_support_auto_switch_filament_flag = true;
is_xcam_buildplate_supported = true;
xcam_support_recovery_step_loss = true;
is_support_send_to_sdcard = true;
is_support_1080dpi = true;
is_support_ai_monitoring = true;
is_support_ams_humidity = true;
is_support_mqtt_alive = true;
local_use_ssl_for_mqtt = true;
is_support_remote_tunnel = true;
is_support_tunnel_mqtt = true;
local_camera_proto = local_rtsp_url.empty() ? -1 : local_rtsp_url == "disable" ? 0
: boost::algorithm::starts_with(local_rtsp_url, "rtsps") ? 2 : 3;
file_proto = 2;
}
local_camera_proto = local_rtsp_url.empty() ? -1 : local_rtsp_url == "disable" ? 0
: boost::algorithm::starts_with(local_rtsp_url, "rtsps") ? 2 : 3;
file_proto = 2;
}
} else if (printer_type == "C11") {
is_cloud_print_only = true;
@ -1469,6 +1566,13 @@ void MachineObject::parse_version_func()
is_support_mqtt_alive = ota_version->second.sw_ver.compare("01.03.50.01") >= 0;
}
}
} else if (printer_type == "N1") {
is_support_remote_tunnel = true;
local_camera_proto = 1;
is_support_tunnel_mqtt = true;
is_support_ams_humidity = false;
is_support_1080dpi = true;
ams_support_remain = false;
}
}
@ -1672,24 +1776,46 @@ int MachineObject::command_set_nozzle(int temp)
return this->publish_gcode(gcode_str);
}
int MachineObject::command_set_chamber(int temp)
{
json j;
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
j["print"]["command"] = "set_ctt";
j["print"]["ctt_val"] = temp;
return this->publish_json(j.dump(), 1);
}
int MachineObject::command_ams_switch(int tray_index, int old_temp, int new_temp)
{
BOOST_LOG_TRIVIAL(trace) << "ams_switch to " << tray_index << " with temp: " << old_temp << ", " << new_temp;
if (old_temp < 0) old_temp = FILAMENT_DEF_TEMP;
if (new_temp < 0) new_temp = FILAMENT_DEF_TEMP;
int tray_id_int = tray_index;
int result = 0;
std::string gcode = "";
if (tray_index == 255) {
gcode = DeviceManager::load_gcode(printer_type, "ams_unload.gcode");
} else {
// include VIRTUAL_TRAY_ID
gcode = DeviceManager::load_gcode(printer_type, "ams_load.gcode");
boost::replace_all(gcode, "[next_extruder]", std::to_string(tray_index));
boost::replace_all(gcode, "[new_filament_temp]", std::to_string(new_temp));
//command
if (is_support_command_ams_switch()) {
command_ams_change_filament(tray_index, old_temp, new_temp);
}
//gcode
else {
std::string gcode = "";
if (tray_index == 255) {
gcode = DeviceManager::load_gcode(printer_type, "ams_unload.gcode");
}
else {
// include VIRTUAL_TRAY_ID
gcode = DeviceManager::load_gcode(printer_type, "ams_load.gcode");
boost::replace_all(gcode, "[next_extruder]", std::to_string(tray_index));
boost::replace_all(gcode, "[new_filament_temp]", std::to_string(new_temp));
}
result = this->publish_gcode(gcode);
}
return this->publish_gcode(gcode);
return result;
}
int MachineObject::command_ams_change_filament(int tray_id, int old_temp, int new_temp)
@ -1902,6 +2028,15 @@ int MachineObject::command_set_printing_option(bool auto_recovery)
return this->publish_json(j.dump());
}
int MachineObject::command_set_prompt_sound(bool prompt_sound){
json j;
j["print"]["command"] = "print_option";
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
j["print"]["sound_enable"] = prompt_sound;
return this->publish_json(j.dump());
}
int MachineObject::command_ams_switch_filament(bool switch_filament)
{
json j;
@ -1916,8 +2051,17 @@ int MachineObject::command_ams_switch_filament(bool switch_filament)
return this->publish_json(j.dump());
}
int MachineObject::command_axis_control(std::string axis, double unit, double value, int speed)
int MachineObject::command_axis_control(std::string axis, double unit, double input_val, int speed)
{
double value = input_val;
if (!is_core_xy()) {
if ( axis.compare("Y") == 0
|| axis.compare("Z") == 0) {
value = -1.0 * input_val;
}
}
char cmd[256];
if (axis.compare("X") == 0
|| axis.compare("Y") == 0
@ -1956,7 +2100,7 @@ bool MachineObject::is_support_command_calibration()
return true;
}
int MachineObject::command_start_calibration(bool vibration, bool bed_leveling, bool xcam_cali)
int MachineObject::command_start_calibration(bool vibration, bool bed_leveling, bool xcam_cali, bool motor_noise)
{
if (!is_support_command_calibration()) {
// fixed gcode file
@ -1969,7 +2113,8 @@ int MachineObject::command_start_calibration(bool vibration, bool bed_leveling,
json j;
j["print"]["command"] = "calibration";
j["print"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++);
j["print"]["option"] = (vibration ? 1 << 2 : 0)
j["print"]["option"]= (motor_noise ? 1 << 3 : 0)
+ (vibration ? 1 << 2 : 0)
+ (bed_leveling ? 1 << 1 : 0)
+ (xcam_cali ? 1 << 0 : 0);
return this->publish_json(j.dump());
@ -2264,6 +2409,13 @@ int MachineObject::command_xcam_control_auto_recovery_step_loss(bool on_off)
return command_set_printing_option(on_off);
}
int MachineObject::command_xcam_control_allow_prompt_sound(bool on_off)
{
xcam_allow_prompt_sound = on_off;
xcam_prompt_sound_hold_count = HOLD_COUNT_MAX;
return command_set_prompt_sound(on_off);
}
void MachineObject::set_bind_status(std::string status)
{
bind_user_name = status;
@ -2347,6 +2499,13 @@ bool MachineObject::is_printing_finished()
return false;
}
bool MachineObject::is_core_xy()
{
if (get_printer_arch() == PrinterArch::ARCH_CORE_XY)
return true;
return false;
}
void MachineObject::reset_update_time()
{
BOOST_LOG_TRIVIAL(trace) << "reset reset_update_time, dev_id =" << dev_id;
@ -2373,6 +2532,8 @@ void MachineObject::reset()
m_is_support_show_bak = false;
extruder_axis_status = LOAD;
nozzle_diameter = 0.0f;
network_wired = false;
dev_connection_name = "";
// reset print_json
json empty_j;
@ -2513,7 +2674,10 @@ bool MachineObject::is_function_supported(PrinterFunction func)
func_name = "FUNC_CAMERA_VIDEO";
break;
case FUNC_MEDIA_FILE:
func_name = "FUNC_MEDIA_FILE";
func_name = "FUNC_MEDIA_FILE";
break;
case FUNC_PROMPT_SOUND:
func_name = "FUNC_PROMPT_SOUND";
break;
case FUNC_REMOTE_TUNNEL:
parse_version_func();
@ -2551,6 +2715,9 @@ bool MachineObject::is_function_supported(PrinterFunction func)
case FUNC_CHAMBER_FAN:
func_name = "FUNC_CHAMBER_FAN";
break;
case FUNC_AUX_FAN:
func_name = "FUNC_AUX_FAN";
break;
case FUNC_EXTRUSION_CALI:
if (!ams_support_virtual_tray)
return false;
@ -2567,6 +2734,9 @@ bool MachineObject::is_function_supported(PrinterFunction func)
case FUNC_FILAMENT_BACKUP:
func_name = "FUNC_FILAMENT_BACKUP";
break;
case FUNC_MOTOR_NOISE_CALI:
func_name = "FUNC_MOTOR_NOISE_CALI";
break;
default:
return true;
}
@ -2586,7 +2756,7 @@ bool MachineObject::is_support_print_with_timelapse()
bool MachineObject::is_camera_busy_off()
{
if (printer_type == "C11" || printer_type == "C12")
if (printer_type == "C11" || printer_type == "C12" || printer_type == "N1")
return is_in_prepare() || is_in_upgrading();
return false;
}
@ -2708,6 +2878,34 @@ int MachineObject::parse_json(std::string payload)
}
}
if (jj.contains("command")) {
if (jj["command"].get<std::string>() == "ams_change_filament") {
if (jj.contains("errno")) {
if (jj["errno"].is_number()) {
if (jj["errno"].get<int>() == -2) {
wxString text = _L("The current chamber temperature or the target chamber temperature exceeds 45\u2103.In order to avoid extruder clogging,low temperature filament(PLA/PETG/TPU) is not allowed to be loaded.");
GUI::wxGetApp().show_dialog(text);
}
}
}
}
if (jj["command"].get<std::string>() == "set_ctt") {
if (m_agent && is_studio_cmd(sequence_id)) {
if (jj["errno"].is_number()) {
if (jj["errno"].get<int>() == -2) {
wxString text = _L("Low temperature filament(PLA/PETG/TPU) is loaded in the extruder.In order to avoid extruder clogging,it is not allowed to set the chamber temperature above 45\u2103.");
GUI::wxGetApp().show_dialog(text);
}
else if (jj["errno"].get<int>() == -4) {
wxString text = _L("When you set the chamber temperature below 40\u2103, the chamber temperature control will not be activated. And the target chamber temperature will automatically be set to 0\u2103.");
GUI::wxGetApp().show_dialog(text);
}
}
}
}
if (jj["command"].get<std::string>() == "push_status") {
m_push_count++;
last_push_time = std::chrono::system_clock::now();
@ -2910,6 +3108,11 @@ int MachineObject::parse_json(std::string payload)
chamber_temp = jj["chamber_temper"].get<float>();
}
}
if (jj.contains("ctt")) {
if (jj["ctt"].is_number()) {
chamber_temp_target = jj["ctt"].get<float>();
}
}
/* signals */
if (jj.contains("link_th_state"))
link_th = jj["link_th_state"].get<std::string>();
@ -4087,7 +4290,7 @@ int MachineObject::parse_json(std::string payload)
if (it->contains("confidence")) {
flow_ratio_calib_result.confidence = (*it)["confidence"].get<int>();
} else {
flow_ratio_calib_result.confidence = 0;
flow_ratio_calib_result.confidence = 0;
}
flow_ratio_results.push_back(flow_ratio_calib_result);
@ -4256,7 +4459,8 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil
}
if (project_id.compare("0") == 0
|| profile_id.compare("0") == 0) return;
|| profile_id.compare("0") == 0
|| subtask_id.compare("0") == 0) return;
BOOST_LOG_TRIVIAL(trace) << "slice_info: start";
slice_info = new BBLSliceInfo();
@ -4268,9 +4472,35 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil
if (plate_idx >= 0) {
plate_index = plate_idx;
} else {
if (subtask_id.compare("0") == 0)
return;
m_agent->get_task_plate_index(subtask_id, &plate_index);
std::string subtask_json;
unsigned http_code = 0;
std::string http_body;
if (m_agent->get_subtask_info(subtask_id, &subtask_json, &http_code, &http_body) == 0) {
try {
json task_j = json::parse(subtask_json);
if (task_j.contains("content")) {
std::string content_str = task_j["content"].get<std::string>();
json content_j = json::parse(content_str);
plate_index = content_j["info"]["plate_idx"].get<int>();
}
if (task_j.contains("context") && task_j["context"].contains("plates")) {
for (int i = 0; i < task_j["context"]["plates"].size(); i++) {
if (task_j["context"]["plates"][i].contains("index") && task_j["context"]["plates"][i]["index"].get<int>() == plate_index) {
slice_info->thumbnail_url = task_j["context"]["plates"][i]["thumbnail"]["url"].get<std::string>();
BOOST_LOG_TRIVIAL(trace) << "task_info: thumbnail url=" << slice_info->thumbnail_url;
}
}
} else {
BOOST_LOG_TRIVIAL(error) << "task_info: no context or plates";
}
}
catch(...) {
}
} else {
BOOST_LOG_TRIVIAL(error) << "task_info: get subtask id failed!";
}
}
if (plate_index >= 0) {
@ -4285,7 +4515,7 @@ void MachineObject::update_slice_info(std::string project_id, std::string profil
if (!j["weight"].is_null())
slice_info->weight = j["weight"].get<float>();
if (!j["thumbnail"].is_null()) {
slice_info->thumbnail_url = j["thumbnail"]["url"].get<std::string>();
//slice_info->thumbnail_url = j["thumbnail"]["url"].get<std::string>();
BOOST_LOG_TRIVIAL(trace) << "slice_info: thumbnail url=" << slice_info->thumbnail_url;
}
if (!j["filaments"].is_null()) {
@ -4479,6 +4709,10 @@ void DeviceManager::on_machine_alive(std::string json_str)
if (j.contains("sec_link")) {
sec_link = j["sec_link"].get<std::string>();
}
std::string connection_name = "";
if (j.contains("connection_name")) {
connection_name = j["connection_name"].get<std::string>();
}
MachineObject* obj;
@ -4497,11 +4731,24 @@ void DeviceManager::on_machine_alive(std::string json_str)
// update properties
/* ip changed */
obj = it->second;
if (obj->dev_ip.compare(dev_ip) != 0 && !obj->dev_ip.empty()) {
BOOST_LOG_TRIVIAL(info) << "MachineObject IP changed from " << obj->dev_ip << " to " << dev_ip;
obj->dev_ip = dev_ip;
if (obj->dev_ip.compare(dev_ip) != 0) {
if ( connection_name.empty() ) {
BOOST_LOG_TRIVIAL(info) << "MachineObject IP changed from " << obj->dev_ip << " to " << dev_ip;
obj->dev_ip = dev_ip;
}
else {
if ( obj->dev_connection_name.empty() || obj->dev_connection_name.compare(connection_name) == 0) {
BOOST_LOG_TRIVIAL(info) << "MachineObject IP changed from " << obj->dev_ip << " to " << dev_ip << " connection_name is " << connection_name;
if(obj->dev_connection_name.empty()){obj->dev_connection_name = connection_name;}
obj->dev_ip = dev_ip;
}
}
/* ip changed reconnect mqtt */
}
obj->wifi_signal = printer_signal;
obj->dev_connection_type= connect_type;
obj->bind_state = bind_state;
@ -4529,6 +4776,7 @@ void DeviceManager::on_machine_alive(std::string json_str)
obj->dev_connection_type = connect_type;
obj->bind_state = bind_state;
obj->bind_sec_link = sec_link;
obj->dev_connection_name = connection_name;
//load access code
AppConfig* config = Slic3r::GUI::wxGetApp().app_config;
@ -4968,6 +5216,21 @@ std::string DeviceManager::get_ftp_folder(std::string type_str)
return "";
}
PrinterArch DeviceManager::get_printer_arch(std::string type_str)
{
PrinterArch arch = PrinterArch::ARCH_CORE_XY;
if (DeviceManager::function_table.contains("printers")) {
for (auto printer : DeviceManager::function_table["printers"]) {
if (printer.contains("model_id") && printer["model_id"].get<std::string>() == type_str) {
if (printer.contains("printer_arch")) {
return get_printer_arch_by_str(printer["printer_arch"].get<std::string>());
}
}
}
}
return arch;
}
std::string DeviceManager::get_printer_thumbnail_img(std::string type_str)
{
if (DeviceManager::function_table.contains("printers")) {
@ -5029,6 +5292,22 @@ bool DeviceManager::get_bed_temperature_limit(std::string type_str, int &limit)
return result;
}
bool DeviceManager::get_nozzle_max_temperature(std::string type_str, int& limit)
{
bool result = false;
if (DeviceManager::function_table.contains("printers")) {
for (auto printer : DeviceManager::function_table["printers"]) {
if (printer.contains("model_id") && printer["model_id"].get<std::string>() == type_str) {
if (printer.contains("nozzle_max_temperature")) {
limit = printer["nozzle_max_temperature"].get<int>();
return true;
}
}
}
}
return result;
}
bool DeviceManager::load_functional_config(std::string config_file)
{
std::ifstream json_file(config_file.c_str());

View file

@ -52,6 +52,11 @@ using namespace nlohmann;
namespace Slic3r {
enum PrinterArch {
ARCH_CORE_XY,
ARCH_I3,
};
enum PrinterSeries {
SERIES_X1 = 0,
SERIES_P1P,
@ -100,10 +105,13 @@ enum PrinterFunction {
FUNC_SEND_TO_SDCARD,
FUNC_AUTO_SWITCH_FILAMENT,
FUNC_CHAMBER_FAN,
FUNC_AUX_FAN,
FUNC_EXTRUSION_CALI,
FUNC_PROMPT_SOUND,
FUNC_VIRTUAL_TYAY,
FUNC_PRINT_ALL,
FUNC_FILAMENT_BACKUP,
FUNC_MOTOR_NOISE_CALI,
FUNC_MAX
};
@ -166,6 +174,11 @@ enum AmsOptionType {
AMS_OP_CALIBRATE_REMAIN
};
enum ManualPaCaliMethod {
PA_LINE = 0,
PA_PATTERN,
};
class AmsTray {
public:
AmsTray(std::string tray_id) {
@ -431,6 +444,7 @@ public:
float nozzle_diameter { 0.0f };
std::string dev_connection_type; /* lan | cloud */
std::string connection_type() { return dev_connection_type; }
std::string dev_connection_name; /* lan | eth */
void set_dev_ip(std::string ip) {dev_ip = ip;};
bool has_access_right() { return !get_access_code().empty(); }
std::string get_ftp_folder();
@ -446,6 +460,7 @@ public:
//PRINTER_TYPE printer_type = PRINTER_3DPrinter_UKNOWN;
std::string printer_type; /* model_id */
PrinterSeries get_printer_series() const;
PrinterArch get_printer_arch() const;
std::string printer_thumbnail_img;
std::string monitor_upgrade_printer_img;
@ -529,6 +544,7 @@ public:
bool can_unload_filament();
bool is_U0_firmware();
bool is_support_ams_mapping();
bool is_support_command_ams_switch();
static bool is_support_ams_mapping_version(std::string module, std::string version);
int ams_filament_mapping(std::vector<FilamentInfo> filaments, std::vector<FilamentInfo> &result, std::vector<int> exclude_id = std::vector<int>());
@ -549,6 +565,7 @@ public:
float bed_temp;
float bed_temp_target;
float chamber_temp;
float chamber_temp_target;
float frame_temp;
/* cooling */
@ -562,6 +579,7 @@ public:
std::string wifi_signal;
std::string link_th;
std::string link_ams;
bool network_wired { false };
/* lights */
LIGHT_EFFECT chamber_light;
@ -632,6 +650,7 @@ public:
float cache_flow_ratio { 0.0 };
bool cali_finished = true;
ManualPaCaliMethod manual_pa_cali_method = ManualPaCaliMethod::PA_LINE;
bool has_get_pa_calib_tab{ false };
std::vector<PACalibResult> pa_calib_tab;
float pa_calib_tab_nozzle_dia;
@ -711,7 +730,9 @@ public:
int xcam_buildplate_marker_hold_count = 0;
bool xcam_support_recovery_step_loss { true };
bool xcam_auto_recovery_step_loss{ false };
bool xcam_allow_prompt_sound{ false };
int xcam_auto_recovery_hold_count = 0;
int xcam_prompt_sound_hold_count = 0;
int ams_print_option_count = 0;
/*not support U2*/
@ -786,6 +807,7 @@ public:
int command_task_resume();
int command_set_bed(int temp);
int command_set_nozzle(int temp);
int command_set_chamber(int temp);
// ams controls
int command_ams_switch(int tray_index, int old_temp = 210, int new_temp = 210);
int command_ams_change_filament(int tray_id, int old_temp = 210, int new_temp = 210);
@ -806,15 +828,18 @@ public:
// set printing speed
int command_set_printing_speed(PrintingSpeedLevel lvl);
//set pormpt sound
int command_set_prompt_sound(bool prompt_sound);
// set print option
int command_set_printing_option(bool auto_recovery);
// axis string is X, Y, Z, E
int command_axis_control(std::string axis, double unit = 1.0f, double value = 1.0f, int speed = 3000);
int command_axis_control(std::string axis, double unit = 1.0f, double input_val = 1.0f, int speed = 3000);
// calibration printer
bool is_support_command_calibration();
int command_start_calibration(bool vibration, bool bed_leveling, bool xcam_cali);
int command_start_calibration(bool vibration, bool bed_leveling, bool xcam_cali, bool motor_noise);
// PA calibration
int command_start_pa_calibration(const X1CCalibInfos& pa_data, int mode = 0); // 0: automatic mode; 1: manual mode. default: automatic mode
@ -839,6 +864,7 @@ public:
int command_xcam_control_first_layer_inspector(bool on_off, bool print_halt);
int command_xcam_control_buildplate_marker_detector(bool on_off);
int command_xcam_control_auto_recovery_step_loss(bool on_off);
int command_xcam_control_allow_prompt_sound(bool on_off);
/* common apis */
inline bool is_local() { return !dev_ip.empty(); }
@ -851,6 +877,7 @@ public:
bool is_in_printing();
bool is_in_prepare();
bool is_printing_finished();
bool is_core_xy();
void reset_update_time();
void reset();
static bool is_in_printing_status(std::string status);
@ -944,11 +971,13 @@ public:
static std::string parse_printer_type(std::string type_str);
static std::string get_printer_display_name(std::string type_str);
static std::string get_printer_thumbnail_img(std::string type_str);
static PrinterArch get_printer_arch(std::string type_str);
static std::string get_ftp_folder(std::string type_str);
static bool is_function_supported(std::string type_str, std::string function_name);
static std::vector<std::string> get_resolution_supported(std::string type_str);
static bool get_bed_temperature_limit(std::string type_str, int& limit);
static bool get_nozzle_max_temperature(std::string type_str, int& limit);
static bool load_functional_config(std::string config_file);
static bool load_filaments_blacklist_config(std::string config_file);
static void check_filaments_in_blacklist(std::string tag_vendor, std::string tag_type, bool& in_blacklist, std::string& ac, std::string& info);

View file

@ -66,6 +66,12 @@ wxString double_to_string(double const value, const int max_precision /*= 4*/)
return s;
}
wxString get_thumbnail_string(const Vec2d& value)
{
wxString ret_str = wxString::Format("%.2fx%.2f", value[0], value[1]);
return ret_str;
}
wxString get_thumbnails_string(const std::vector<Vec2d>& values)
{
wxString ret_str;
@ -367,6 +373,34 @@ void Field::get_value_by_opt_type(wxString& str, const bool check_value/* = true
m_value = into_u8(str);
break; }
case coPoint:{
Vec2d out_value;
str.Replace(" ", wxEmptyString, true);
if (!str.IsEmpty()) {
bool invalid_val = true;
double x, y;
wxStringTokenizer thumbnail(str, "x");
if (thumbnail.HasMoreTokens()) {
wxString x_str = thumbnail.GetNextToken();
if (x_str.ToDouble(&x) && thumbnail.HasMoreTokens()) {
wxString y_str = thumbnail.GetNextToken();
if (y_str.ToDouble(&y) && !thumbnail.HasMoreTokens()) {
out_value = Vec2d(x, y);
invalid_val = false;
}
}
}
if (invalid_val) {
wxString text_value;
if (!m_value.empty()) text_value = get_thumbnail_string(boost::any_cast<Vec2d>(m_value));
set_value(text_value, true);
show_error(m_parent, format_wxstr(_L("Invalid format. Expected vector format: \"%1%\""), "XxY, XxY, ..."));
}
}
m_value = out_value;
break; }
case coPoints: {
std::vector<Vec2d> out_values;
@ -446,7 +480,7 @@ void Field::sys_color_changed()
template<class T>
bool is_defined_input_value(wxWindow* win, const ConfigOptionType& type)
{
if (!win || (static_cast<T*>(win)->GetValue().empty() && type != coString && type != coStrings && type != coPoints))
if (!win || (static_cast<T*>(win)->GetValue().empty() && type != coString && type != coStrings && type != coPoints && type != coPoint))
return false;
return true;
}
@ -495,6 +529,9 @@ void TextCtrl::BUILD() {
text_value = vec->get_at(m_opt_idx);
break;
}
case coPoint:
text_value = get_thumbnail_string(m_opt.get_default_value<ConfigOptionPoint>()->value);
break;
case coPoints:
text_value = get_thumbnails_string(m_opt.get_default_value<ConfigOptionPoints>()->values);
break;
@ -1622,8 +1659,11 @@ void PointCtrl::BUILD()
auto temp = new wxBoxSizer(wxHORIZONTAL);
const wxSize field_size(4 * m_em_unit, -1);
auto default_pt = m_opt.get_default_value<ConfigOptionPoints>()->values.at(0);
Slic3r::Vec2d default_pt;
if(m_opt.type == coPoints)
default_pt = m_opt.get_default_value<ConfigOptionPoints>()->values.at(0);
else
default_pt = m_opt.get_default_value<ConfigOptionPoint>()->value;
double val = default_pt(0);
wxString X = val - int(val) == 0 ? wxString::Format(_T("%i"), int(val)) : wxNumberFormatter::ToString(val, 2, wxNumberFormatter::Style_None);
val = default_pt(1);
@ -1734,14 +1774,19 @@ void PointCtrl::set_value(const Vec2d& value, bool change_event)
void PointCtrl::set_value(const boost::any& value, bool change_event)
{
Vec2d pt(Vec2d::Zero());
const Vec2d *ptf = boost::any_cast<Vec2d>(&value);
if (!ptf)
{
ConfigOptionPoints* pts = boost::any_cast<ConfigOptionPoints*>(value);
pt = pts->values.at(0);
}
else
pt = *ptf;
const Vec2d* ptf = boost::any_cast<Vec2d>(&value);
if (!ptf) {
if (m_opt.type == coPoint) {
ConfigOptionPoint* pts = boost::any_cast<ConfigOptionPoint*>(value);
pt = pts->value;
}
else {
ConfigOptionPoints* pts = boost::any_cast<ConfigOptionPoints*>(value);
pt = pts->values.at(0);
}
}
else
pt = *ptf;
set_value(pt, change_event);
}

View file

@ -38,6 +38,7 @@ using t_change = std::function<void(const t_config_option_key&, const boost::any
using t_back_to_init = std::function<void(const std::string&)>;
wxString double_to_string(double const value, const int max_precision = 4);
wxString get_thumbnail_string(const Vec2d& value);
wxString get_thumbnails_string(const std::vector<Vec2d>& values);
class Field {

View file

@ -5379,6 +5379,7 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
std::string bed_shrink_x_key = "bed_shrink_x", bed_shrink_y_key = "bed_shrink_y";
std::string multi_material_key = "allow_multi_materials_on_same_plate";
std::string avoid_extrusion_key = "avoid_extrusion_cali_region";
std::string align_to_y_axis_key = "align_to_y_axis";
std::string postfix;
//BBS:
bool seq_print = false;
@ -5394,7 +5395,7 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
//BBS:
seq_print = true;
} else {
dist_min = 0.1f;
dist_min = 0.0f;
postfix = "_fff";
}
}
@ -5446,6 +5447,22 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
settings_out.avoid_extrusion_cali_region = false;
}
// Align to Y axis. Only enable this option when auto rotation not enabled
{
if (settings_out.enable_rotation) { // do not allow align to Y axis if rotation is enabled
imgui->disabled_begin(true);
settings_out.align_to_y_axis = false;
}
if (imgui->bbl_checkbox(_L("Align to Y axis"), settings.align_to_y_axis)) {
settings_out.align_to_y_axis = settings.align_to_y_axis;
appcfg->set("arrange", align_to_y_axis_key, settings_out.align_to_y_axis ? "1" : "0");
settings_changed = true;
}
if (settings_out.enable_rotation == true) { imgui->disabled_end(); }
}
ImGui::Separator();
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(15.0f, 10.0f));
if (imgui->button(_L("Arrange"))) {
@ -5460,8 +5477,16 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo
settings_out.distance = std::max(dist_min, settings_out.distance);
//BBS: add specific arrange settings
if (seq_print) settings_out.is_seq_print = true;
appcfg->set("arrange", dist_key.c_str(), float_to_string_decimal_point(settings_out.distance));
appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation? "1" : "0");
if (auto printer_structure_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure")) {
settings_out.align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3);
}
else
settings_out.align_to_y_axis = false;
appcfg->set("arrange", dist_key, float_to_string_decimal_point(settings_out.distance));
appcfg->set("arrange", rot_key, settings_out.enable_rotation ? "1" : "0");
appcfg->set("arrange", align_to_y_axis_key, settings_out.align_to_y_axis ? "1" : "0");
settings_changed = true;
}
ImGui::PopStyleVar(1);

View file

@ -472,7 +472,7 @@ public:
struct ArrangeSettings
{
float distance = 5.;
float distance = 0.f;
// float distance_sla = 6.;
float accuracy = 0.65f; // Unused currently
bool enable_rotation = false;
@ -482,6 +482,7 @@ public:
bool is_seq_print = false;
float bed_shrink_x = 0.f;
float bed_shrink_y = 0.f;
bool align_to_y_axis = false;
};
struct OrientSettings
@ -624,7 +625,6 @@ private:
return *ptr;
}
ArrangeSettings &get_arrange_settings() { return get_arrange_settings(this); }
//BBS:record key botton frequency
@ -650,6 +650,7 @@ public:
}
void load_arrange_settings();
ArrangeSettings& get_arrange_settings() { return get_arrange_settings(this); }
class SequentialPrintClearance
{

View file

@ -198,6 +198,10 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
config.option<ConfigOptionEnumsGeneric>(opt_key)->set_at(vec_new, opt_index, 0);
}
break;
case coPoint:{
config.set_key_value(opt_key, new ConfigOptionPoint(boost::any_cast<Vec2d>(value)));
}
break;
case coPoints:{
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "thumbnails") {
config.option<ConfigOptionPoints>(opt_key)->values = boost::any_cast<std::vector<Vec2d>>(value);

View file

@ -737,7 +737,11 @@ static const FileWildcards file_wildcards_by_type[FT_SIZE] = {
/* FT_AMF */ { "AMF files"sv, { ".amf"sv, ".zip.amf"sv, ".xml"sv } },
/* FT_3MF */ { "3MF files"sv, { ".3mf"sv } },
/* FT_GCODE */ { "G-code files"sv, { ".gcode"sv, ".3mf"sv } },
#ifdef __APPLE__
/* FT_MODEL */ { "Supported files"sv, { ".3mf"sv, ".stl"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv , ".usd"sv, ".usda"sv, ".usdc"sv, ".usdz"sv, ".abc"sv, ".ply"sv} },
#else
/* FT_MODEL */ {"Supported files"sv, {".3mf"sv, ".stl"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv }},
#endif
/* FT_PROJECT */ { "Project files"sv, { ".3mf"sv} },
/* FT_GALLERY */ { "Known files"sv, { ".stl"sv, ".obj"sv } },
@ -3001,7 +3005,7 @@ bool GUI_App::has_model_mall()
{
if (auto cc = app_config->get_country_code(); cc == "CN" || cc == "")
return false;
return false;
return true;
}
void GUI_App::update_label_colours()
@ -3625,7 +3629,11 @@ void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files) const
{
input_files.Clear();
wxFileDialog dialog(parent ? parent : GetTopWindow(),
#ifdef __APPLE__
_L("Choose one or more files (3mf/step/stl/svg/obj/amf/usd*/abc/ply):"),
#else
_L("Choose one or more files (3mf/step/stl/svg/obj/amf):"),
#endif
from_u8(app_config->get_last_dir()), "",
file_wildcards(FT_MODEL), wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);

View file

@ -229,7 +229,7 @@ private:
#endif
//import model from mall
std::string m_download_file_url;
wxString m_download_file_url;
//#ifdef _WIN32
wxColour m_color_label_modified;
@ -627,6 +627,7 @@ private:
bool check_networking_version();
void cancel_networking_install();
void restart_networking();
void check_config_updates_from_updater() { check_updates(false); }
private:
int updating_bambu_networking();

View file

@ -1710,7 +1710,8 @@ bool GLGizmoAdvancedCut::render_combo(const std::string &label, const std::vecto
size_t selection_out = selection_idx;
if (ImGui::BBLBeginCombo(("##" + label).c_str(), lines[selection_idx].c_str(), 0)) {
const char* selected_str = (selection_idx >= 0 && selection_idx < int(lines.size())) ? lines[selection_idx].c_str() : "";
if (ImGui::BBLBeginCombo(("##" + label).c_str(), selected_str, 0)) {
for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) {
ImGui::PushID(int(line_idx));
if (ImGui::Selectable("", line_idx == selection_idx))

View file

@ -1002,8 +1002,9 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
Vec3d temp_position = m_mouse_position_world;
Vec3d temp_normal = m_mouse_normal_world;
Vec3d cut_plane = Vec3d::UnitY();
if (temp_normal != Vec3d::UnitZ()) {
Vec3d cut_plane = Vec3d::UnitY();
double epson = 1e-6;
if (!(abs(temp_normal.x()) <= epson && abs(temp_normal.y()) <= epson && abs(temp_normal.z()) > epson)) { // temp_normal != Vec3d::UnitZ()
Vec3d v_plane = temp_normal.cross(Vec3d::UnitZ());
cut_plane = v_plane.cross(temp_normal);
}
@ -1092,6 +1093,9 @@ bool GLGizmoText::update_text_positions(const std::vector<std::string>& texts)
MeshSlicingParams slicing_params;
slicing_params.trafo = transfo * mi->get_transformation().get_matrix() /** volume->get_transformation().get_matrix()*/;
// for debug
// its_write_obj(slice_meshs.its, "D:/debug_files/mesh.obj");
// generate polygons
const Polygons temp_polys = slice_mesh(slice_meshs.its, click_point.z(), slicing_params);

View file

@ -279,9 +279,22 @@ std::string get_hms_wiki_url(std::string error_code)
std::string hms_host = wxGetApp().app_config->get_hms_host();
std::string lang_code = HMSQuery::hms_language_code();
std::string url = (boost::format("https://%1%/index.php?e=%2%&s=device_hms&lang=%3%")
% hms_host
% error_code
% lang_code).str();
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return url;
MachineObject* obj = dev->get_selected_machine();
if (!obj) return url;
if (!obj->dev_id.empty()) {
url = (boost::format("https://%1%/index.php?e=%2%&d=%3%&s=device_hms&lang=%4%")
% hms_host
% error_code
% obj->dev_id
% lang_code).str();
}
return url;
}

View file

@ -234,7 +234,7 @@ void IMSlider::SetTicksValues(const Info &custom_gcode_per_print_z)
m_ticks.ticks.clear();
const std::vector<CustomGCode::Item> &heights = custom_gcode_per_print_z.gcodes;
for (auto h : heights) {
int tick = get_tick_from_value(h.print_z);
int tick = get_tick_from_value(h.print_z, true);
if (tick >= 0) m_ticks.ticks.emplace(TickCode{tick, h.type, h.extruder, h.color, h.extra});
}

View file

@ -257,7 +257,12 @@ void ArrangeJob::prepare_wipe_tower()
// if wipe tower is explicitly disabled, no need to estimate
DynamicPrintConfig &current_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
auto op = current_config.option("enable_prime_tower");
if (op && op->getBool() == false || params.is_seq_print) return;
bool enable_prime_tower = op && op->getBool();
if (!enable_prime_tower || params.is_seq_print) return;
bool smooth_timelapse = false;
auto sop = current_config.option("timelapse_type");
if (sop) { smooth_timelapse = sop->getInt() == TimelapseType::tlSmooth; }
if (smooth_timelapse) { need_wipe_tower = true; }
// estimate if we need wipe tower for all plates:
// need wipe tower if some object has multiple extruders (has paint-on colors or support material)
@ -270,7 +275,7 @@ void ArrangeJob::prepare_wipe_tower()
break;
}
}
// if multile extruders have same bed temp, we need wipe tower
// 允许不同材料落在相同盘,且所有选定对象中使用了多种热床温度相同的材料
if (params.allow_multi_materials_on_same_plate) {
@ -287,35 +292,24 @@ void ArrangeJob::prepare_wipe_tower()
}
BOOST_LOG_TRIVIAL(info) << "arrange: need_wipe_tower=" << need_wipe_tower;
if (need_wipe_tower) {
// check all plates to see if wipe tower is already there
ArrangePolygon wipe_tower_ap;
std::vector<bool> plates_have_wipe_tower(MAX_NUM_PLATES, false);
for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++)
if (auto wti = get_wipe_tower(*m_plater, bedid)) {
ArrangePolygon &&ap = get_wipetower_arrange_poly(&wti);
wipe_tower_ap = ap;
ap.bed_idx = bedid;
m_unselected.emplace_back(std::move(ap));
plates_have_wipe_tower[bedid] = true;
}
// if wipe tower is not init yet (no wipe tower in any plate before arrangement)
//if (wipe_tower_ap.poly.empty()) {
// auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
// wipe_tower_ap.poly.contour.points = print.first_layer_wipe_tower_corners(false);
wipe_tower_ap.name = "WipeTower";
wipe_tower_ap.is_virt_object = true;
wipe_tower_ap.is_wipe_tower = true;
//}
const GLCanvas3D* canvas3D=static_cast<const GLCanvas3D *>(m_plater->canvas3D());
for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++) {
if (!plates_have_wipe_tower[bedid]) {
wipe_tower_ap.translation = {0, 0};
wipe_tower_ap.poly.contour.points = canvas3D->estimate_wipe_tower_points(bedid, !only_on_partplate);
wipe_tower_ap.bed_idx = bedid;
m_unselected.emplace_back(wipe_tower_ap);
}
// check all plates to see if wipe tower is already there
ArrangePolygon wipe_tower_ap;
wipe_tower_ap.name = "WipeTower";
wipe_tower_ap.is_virt_object = true;
wipe_tower_ap.is_wipe_tower = true;
const GLCanvas3D *canvas3D = static_cast<const GLCanvas3D *>(m_plater->canvas3D());
for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++) {
if (auto wti = get_wipe_tower(*m_plater, bedid)) {
// wipe tower is already there
wipe_tower_ap = get_wipetower_arrange_poly(&wti);
wipe_tower_ap.bed_idx = bedid;
m_unselected.emplace_back(wipe_tower_ap);
} else if (need_wipe_tower) {
wipe_tower_ap.translation = {0, 0};
wipe_tower_ap.poly.contour.points = canvas3D->estimate_wipe_tower_points(bedid, !only_on_partplate);
wipe_tower_ap.bed_idx = bedid;
m_unselected.emplace_back(wipe_tower_ap);
}
}
}
@ -395,8 +389,13 @@ void ArrangeJob::prepare()
params = init_arrange_params(m_plater);
//BBS update extruder params and speed table before arranging
Plater::setExtruderParams(Model::extruderParamsMap);
Plater::setPrintSpeedTable(Model::printSpeedMap);
const Slic3r::DynamicPrintConfig& config = wxGetApp().preset_bundle->full_config();
auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
auto print_config = print.config();
int numExtruders = wxGetApp().preset_bundle->filament_presets.size();
Model::setExtruderParams(config, numExtruders);
Model::setPrintSpeedTable(config, print_config);
int state = m_plater->get_prepare_state();
if (state == Job::JobPrepareState::PREPARE_STATE_DEFAULT) {
@ -502,17 +501,17 @@ void ArrangeJob::process()
const bool is_bbl = wxGetApp().preset_bundle->is_bbl_vendor();
if (is_bbl && params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
update_arrange_params(params, *m_plater, m_selected);
update_selected_items_inflation(m_selected, *m_plater, params);
update_unselected_items_inflation(m_unselected, *m_plater, params);
Points bedpts = get_shrink_bedpts(*m_plater,params);
update_arrange_params(params, *m_plater, m_selected);
update_selected_items_inflation(m_selected, m_plater->config(), params);
update_unselected_items_inflation(m_unselected, m_plater->config(), params);
update_selected_items_axis_align(m_selected, m_plater->config(), params);
Points bedpts = get_shrink_bedpts(m_plater->config(),params);
double scaled_exclusion_gap = scale_(1);
partplate_list.preprocess_exclude_areas(params.excluded_regions, 1, scaled_exclusion_gap);
BOOST_LOG_TRIVIAL(debug) << "arrange bed_shrink_x=" << params.bed_shrink_x
<< "; bedpts:" << bedpts[0].transpose() << ", " << bedpts[1].transpose() << ", " << bedpts[2].transpose() << ", " << bedpts[3].transpose();
BOOST_LOG_TRIVIAL(debug) << "arrange bedpts:" << bedpts[0].transpose() << ", " << bedpts[1].transpose() << ", " << bedpts[2].transpose() << ", " << bedpts[3].transpose();
params.stopcondition = [this]() { return was_canceled(); };
@ -521,14 +520,14 @@ void ArrangeJob::process()
};
{
BOOST_LOG_TRIVIAL(debug)<< "Arrange full params: "<< params.to_json();
BOOST_LOG_TRIVIAL(debug) << "items selected before arrange: ";
for (auto selected : m_selected)
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx
<< ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp;
BOOST_LOG_TRIVIAL(debug) << "items unselected before arrange: ";
for (auto item : m_unselected)
if (!item.is_virt_object)
BOOST_LOG_TRIVIAL(debug) << item.name << ", extruder: " << item.extrude_ids.back() << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose();
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose();
}
arrangement::arrange(m_selected, m_unselected, bedpts, params);
@ -543,9 +542,7 @@ void ArrangeJob::process()
<< ", trans: " << unscale<double>(selected.translation(X)) << ","<< unscale<double>(selected.translation(Y));
BOOST_LOG_TRIVIAL(debug) << "items unselected after arrange: ";
for (auto item : m_unselected)
if (!item.is_virt_object)
BOOST_LOG_TRIVIAL(debug) << item.name << ", extruder: " << item.extrude_ids.back() << ", bed: " << item.bed_idx
<< ", trans: " << item.translation.transpose();
BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose();
}
arrangement::arrange(m_unprintable, {}, bedpts, params);
@ -735,18 +732,22 @@ arrangement::ArrangeParams init_arrange_params(Plater *p)
arrangement::ArrangeParams params;
const GLCanvas3D::ArrangeSettings &settings = static_cast<const GLCanvas3D *>(p->canvas3D())->get_arrange_settings();
auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
const PrintConfig& print_config = print.config();
params.clearance_height_to_rod = print.config().extruder_clearance_height_to_rod.value;
params.clearance_height_to_lid = print.config().extruder_clearance_height_to_lid.value;
params.cleareance_radius = print.config().extruder_clearance_radius.value;
params.printable_height = print.config().printable_height.value;
params.allow_rotations = settings.enable_rotation;
params.align_center = print_config.best_object_pos.value;
params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate;
params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region;
params.is_seq_print = settings.is_seq_print;
params.min_obj_distance = scaled(settings.distance);
params.bed_shrink_x = settings.bed_shrink_x;
params.bed_shrink_y = settings.bed_shrink_y;
params.align_to_y_axis = settings.align_to_y_axis;
int state = p->get_prepare_state();
if (state == Job::JobPrepareState::PREPARE_STATE_MENU) {
@ -760,17 +761,15 @@ arrangement::ArrangeParams init_arrange_params(Plater *p)
return params;
}
//after get selected.call this to update bed_shrink
//after get selected call this to update bed_shrink
void update_arrange_params(arrangement::ArrangeParams &params, const Plater &p, const arrangement::ArrangePolygons &selected)
{
const GLCanvas3D::ArrangeSettings &settings = static_cast<const GLCanvas3D *>(p.canvas3D())->get_arrange_settings();
auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
double skirt_distance = print.has_skirt() ? print.config().skirt_distance.value : 0;
double brim_max = 0;
std::for_each(selected.begin(), selected.end(), [&](const ArrangePolygon &ap) { brim_max = std::max(brim_max, ap.brim_width); });
// 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 + brim_max;
params.brim_skirt_distance = skirt_distance;
params.bed_shrink_x = settings.bed_shrink_x + params.brim_skirt_distance;
params.bed_shrink_y = settings.bed_shrink_y + params.brim_skirt_distance;
// for sequential print, we need to inflate the bed because cleareance_radius is so large
@ -781,55 +780,4 @@ void update_arrange_params(arrangement::ArrangeParams &params, const Plater &p,
}
}
//it will bed accurate after call update_params
Points get_shrink_bedpts(const Plater &plater, const arrangement::ArrangeParams &params)
{
Points bedpts = get_bed_shape(*plater.config());
// 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;
}
void update_selected_items_inflation(arrangement::ArrangePolygons &selected, const Plater &p, const arrangement::ArrangeParams &params) {
// do not inflate brim_width. Objects are allowed to have overlapped brim.
Points bedpts = get_shrink_bedpts(p, params);
BoundingBox bedbb = Polygon(bedpts).bounding_box();
std::for_each(selected.begin(), selected.end(), [&](ArrangePolygon &ap) {
ap.inflation = std::max(scaled(ap.brim_width), params.min_obj_distance / 2);
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(arrangement::ArrangePolygons &unselected, const Plater &p, const arrangement::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 ? std::max(scaled(ap.brim_width), params.min_obj_distance / 2)
: (ap.is_extrusion_cali_object ? 0 : scaled_exclusion_gap); });
}
}} // namespace Slic3r::GUI

View file

@ -80,14 +80,8 @@ arrangement::ArrangeParams get_arrange_params(Plater *p);
arrangement::ArrangeParams init_arrange_params(Plater *p);
Points get_shrink_bedpts(const Plater& plater,const arrangement::ArrangeParams& params);
void update_arrange_params(arrangement::ArrangeParams &params, const Plater &p, const arrangement::ArrangePolygons &selected);
void update_selected_items_inflation(arrangement::ArrangePolygons &selected, const Plater &p, const arrangement::ArrangeParams &params);
void update_unselected_items_inflation(arrangement::ArrangePolygons &unselected, const Plater &p, const arrangement::ArrangeParams &params);
}} // namespace Slic3r::GUI
#endif // ARRANGEJOB_HPP

View file

@ -206,7 +206,7 @@ void FillBedJob::process()
static_cast<const GLCanvas3D*>(m_plater->canvas3D())->get_arrange_settings();
update_arrange_params(params, *m_plater, m_selected);
m_bedpts = get_shrink_bedpts(*m_plater, params);
m_bedpts = get_shrink_bedpts(m_plater->config(), params);
auto &partplate_list = m_plater->get_partplate_list();
auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
@ -216,8 +216,8 @@ void FillBedJob::process()
if (is_bbl && params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
update_selected_items_inflation(m_selected, *m_plater, params);
update_unselected_items_inflation(m_unselected, *m_plater, params);
update_selected_items_inflation(m_selected, m_plater->config(), params);
update_unselected_items_inflation(m_unselected, m_plater->config(), params);
bool do_stop = false;
params.stopcondition = [this, &do_stop]() {

View file

@ -31,7 +31,8 @@ static wxString sending_over_cloud_str = _L("Sending print job through clou
PrintJob::PrintJob(std::shared_ptr<ProgressIndicator> pri, Plater* plater, std::string dev_id)
: PlaterJob{ std::move(pri), plater },
m_dev_id(dev_id)
m_dev_id(dev_id),
m_is_calibration_task(false)
{
m_print_job_completed_id = plater->get_print_finished_event();
}
@ -208,7 +209,7 @@ void PrintJob::process()
params.filename = job_data._temp_path.string();
params.connection_type = this->connection_type;
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr);
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr, nullptr);
if (result != 0) {
BOOST_LOG_TRIVIAL(error) << "access code is invalid";
m_enter_ip_address_fun_fail();
@ -280,6 +281,11 @@ void PrintJob::process()
if (params.preset_name.empty() && m_print_type == "from_normal") { params.preset_name = wxString::Format("%s_plate_%d", m_project_name, curr_plate_idx).ToStdString(); }
if (params.project_name.empty()) {params.project_name = m_project_name;}
if (m_is_calibration_task) {
params.project_name = m_project_name;
params.origin_model_id = "";
}
wxString error_text;
wxString msg_text;
@ -385,6 +391,12 @@ void PrintJob::process()
return was_canceled();
};
auto wait_fn = [this](int state, std::string job_info) {
// TODO
return true;
};
if (params.connection_type != "lan") {
if (params.dev_ip.empty())
params.comments = "no_ip";
@ -407,7 +419,7 @@ void PrintJob::process()
BOOST_LOG_TRIVIAL(info) << "print_job: use ftp send print only";
this->update_status(curr_percent, _L("Sending print job over LAN"));
is_try_lan_mode = true;
result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn);
result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn, wait_fn);
if (result < 0) {
error_text = wxString::Format("Access code:%s Ip address:%s", params.password, params.dev_ip);
// try to send with cloud
@ -423,7 +435,7 @@ void PrintJob::process()
// try to send local with record
BOOST_LOG_TRIVIAL(info) << "print_job: try to start local print with record";
this->update_status(curr_percent, _L("Sending print job over LAN"));
result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn);
result = m_agent->start_local_print_with_record(params, update_fn, cancel_fn, wait_fn);
if (result == 0) {
params.comments = "";
}
@ -438,13 +450,13 @@ void PrintJob::process()
// try to send with cloud
BOOST_LOG_TRIVIAL(warning) << "print_job: try to send with cloud";
this->update_status(curr_percent, _L("Sending print job through cloud service"));
result = m_agent->start_print(params, update_fn, cancel_fn);
result = m_agent->start_print(params, update_fn, cancel_fn, wait_fn);
}
}
else {
BOOST_LOG_TRIVIAL(info) << "print_job: send with cloud";
this->update_status(curr_percent, _L("Sending print job through cloud service"));
result = m_agent->start_print(params, update_fn, cancel_fn);
result = m_agent->start_print(params, update_fn, cancel_fn, wait_fn);
}
}
} else {
@ -483,6 +495,8 @@ void PrintJob::process()
BOOST_LOG_TRIVIAL(error) << "print_job: failed, result = " << result;
} else {
// wait for printer mqtt ready the same job id
wxGetApp().plater()->record_slice_preset("print");
BOOST_LOG_TRIVIAL(error) << "print_job: send ok.";
@ -534,5 +548,9 @@ void PrintJob::connect_to_local_mqtt()
this->update_status(0, wxEmptyString);
}
void PrintJob::set_calibration_task(bool is_calibration)
{
m_is_calibration_task = is_calibration;
}
}} // namespace Slic3r::GUI

View file

@ -63,6 +63,8 @@ public:
std::string m_print_type;
std::string m_dst_path;
bool m_is_calibration_task = false;
int m_print_from_sdc_plate_idx = 0;
bool m_local_use_ssl_for_mqtt { true };
@ -106,6 +108,7 @@ public:
void connect_to_local_mqtt();
wxString get_http_error_msg(unsigned int status, std::string body);
std::string truncate_string(const std::string& str, size_t maxLength);
void set_calibration_task(bool is_calibration);
};

View file

@ -139,7 +139,7 @@ void SendJob::process()
params.filename = job_data._temp_path.string();
params.connection_type = this->connection_type;
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr);
result = m_agent->start_send_gcode_to_sdcard(params, nullptr, nullptr, nullptr);
if (result != 0) {
BOOST_LOG_TRIVIAL(error) << "access code is invalid";
m_enter_ip_address_fun_fail();
@ -317,7 +317,7 @@ void SendJob::process()
// try to send local with record
BOOST_LOG_TRIVIAL(info) << "send_job: try to send gcode to printer";
this->update_status(curr_percent, _L("Sending gcode file over LAN"));
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn);
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn, nullptr);
if (result == BAMBU_NETWORK_ERR_FTP_UPLOAD_FAILED) {
params.comments = "upload_failed";
} else {
@ -335,7 +335,7 @@ void SendJob::process()
} else {
if (this->has_sdcard) {
this->update_status(curr_percent, _L("Sending gcode file over LAN"));
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn);
result = m_agent->start_send_gcode_to_sdcard(params, update_fn, cancel_fn, nullptr);
} else {
this->update_status(curr_percent, _L("An SD card needs to be inserted before sending to printer."));
return;

View file

@ -179,11 +179,11 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
set_miniaturizable(GetHandle());
#endif
//reset developer_mode to false and user_mode to comAdvanced
wxGetApp().app_config->set_bool("developer_mode", false);
if (wxGetApp().app_config->get("user_mode") == "develop") {
wxGetApp().app_config->set("user_mode", "advanced");
}
if (!wxGetApp().app_config->has("user_mode")) {
wxGetApp().app_config->set("user_mode", "simple");
wxGetApp().app_config->set_bool("developer_mode", false);
wxGetApp().app_config->save();
}
wxGetApp().app_config->set_bool("internal_developer_mode", false);
@ -876,8 +876,8 @@ void MainFrame::update_title()
void MainFrame::show_publish_button(bool show)
{
m_publish_btn->Show(show);
Layout();
// m_publish_btn->Show(show);
// Layout();
}
void MainFrame::show_calibration_button(bool show)
@ -1461,18 +1461,18 @@ wxBoxSizer* MainFrame::create_side_tools()
m_slice_select = eSlicePlate;
m_print_select = ePrintPlate;
m_publish_btn = new Button(this, _L("Upload"), "bar_publish", 0, FromDIP(16));
// m_publish_btn = new Button(this, _L("Upload"), "bar_publish", 0, FromDIP(16));
m_slice_btn = new SideButton(this, _L("Slice plate"), "");
m_slice_option_btn = new SideButton(this, "", "sidebutton_dropdown", 0, FromDIP(14));
m_print_btn = new SideButton(this, _L("Print plate"), "");
m_print_option_btn = new SideButton(this, "", "sidebutton_dropdown", 0, FromDIP(14));
update_side_button_style();
m_publish_btn->Hide();
// m_publish_btn->Hide();
m_slice_option_btn->Enable();
m_print_option_btn->Enable();
sizer->Add(m_publish_btn, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(1));
sizer->Add(FromDIP(15), 0, 0, 0, 0);
// sizer->Add(m_publish_btn, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(1));
// sizer->Add(FromDIP(15), 0, 0, 0, 0);
sizer->Add(m_slice_option_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, FromDIP(1));
sizer->Add(m_slice_btn, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(1));
sizer->Add(FromDIP(15), 0, 0, 0, 0);
@ -1482,25 +1482,25 @@ wxBoxSizer* MainFrame::create_side_tools()
sizer->Layout();
m_publish_btn->Bind(wxEVT_BUTTON, [this](auto& e) {
CallAfter([this] {
wxGetApp().open_publish_page_dialog();
// m_publish_btn->Bind(wxEVT_BUTTON, [this](auto& e) {
// CallAfter([this] {
// wxGetApp().open_publish_page_dialog();
if (!wxGetApp().getAgent()) {
BOOST_LOG_TRIVIAL(info) << "publish: no agent";
return;
}
// if (!wxGetApp().getAgent()) {
// BOOST_LOG_TRIVIAL(info) << "publish: no agent";
// return;
// }
// record
json j;
NetworkAgent* agent = GUI::wxGetApp().getAgent();
});
});
// // record
// json j;
// NetworkAgent* agent = GUI::wxGetApp().getAgent();
// });
// });
m_slice_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event)
{
//this->m_plater->select_view_3D("Preview");
m_plater->update();
m_plater->update(false, true);
if (m_slice_select == eSliceAll)
wxPostEvent(m_plater, SimpleEvent(EVT_GLTOOLBAR_SLICE_ALL));
else
@ -1858,12 +1858,12 @@ void MainFrame::update_side_button_style()
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal)
);
m_publish_btn->SetMinSize(wxSize(FromDIP(125), FromDIP(24)));
m_publish_btn->SetCornerRadius(FromDIP(12));
m_publish_btn->SetBackgroundColor(m_btn_bg_enable);
m_publish_btn->SetBorderColor(m_btn_bg_enable);
m_publish_btn->SetBackgroundColour(wxColour(59,68,70));
m_publish_btn->SetTextColor(StateColor::darkModeColorFor("#FFFFFE"));
// m_publish_btn->SetMinSize(wxSize(FromDIP(125), FromDIP(24)));
// m_publish_btn->SetCornerRadius(FromDIP(12));
// m_publish_btn->SetBackgroundColor(m_btn_bg_enable);
// m_publish_btn->SetBorderColor(m_btn_bg_enable);
// m_publish_btn->SetBackgroundColour(wxColour(59,68,70));
// m_publish_btn->SetTextColor(StateColor::darkModeColorFor("#FFFFFE"));
m_slice_btn->SetTextLayout(SideButton::EHorizontalOrientation::HO_Left, FromDIP(15));
m_slice_btn->SetCornerRadius(FromDIP(12));

View file

@ -376,10 +376,10 @@ public:
wxWindow* m_plater_page{ nullptr };
PrintHostQueueDialog* m_printhost_queue_dlg;
// BBS
mutable int m_print_select{ ePrintAll };
mutable int m_slice_select{ eSliceAll };
Button* m_publish_btn{ nullptr };
// Button* m_publish_btn{ nullptr };
SideButton* m_slice_btn{ nullptr };
SideButton* m_slice_option_btn{ nullptr };
SideButton* m_print_btn{ nullptr };

View file

@ -153,7 +153,7 @@ void MediaPlayCtrl::Play()
m_button_play->SetIcon("media_stop");
NetworkAgent *agent = wxGetApp().getAgent();
std::string agent_version = agent ? agent->get_version() : "";
if (m_lan_proto > 0 && (m_lan_mode ||!m_remote_support) && !m_disable_lan && !m_lan_ip.empty()) {
if (m_lan_proto > 0 && (m_lan_mode || m_lan_proto == 1 || !m_remote_support) && !m_disable_lan && !m_lan_ip.empty()) {
m_disable_lan = m_remote_support && !m_lan_mode; // try remote next time
if (m_lan_proto == 1)
m_url = "bambu:///local/" + m_lan_ip + ".?port=6000&user=" + m_lan_user + "&passwd=" + m_lan_passwd + "&device=" + m_machine + "&version=" + agent_version;
@ -161,7 +161,7 @@ void MediaPlayCtrl::Play()
m_url = "bambu:///rtsps___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?device=" + m_machine + "&version=" + agent_version;
else if (m_lan_proto == 3)
m_url = "bambu:///rtsp___" + m_lan_user + ":" + m_lan_passwd + "@" + m_lan_ip + "/streaming/live/1?device=" + m_machine + "&version=" + agent_version;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl camera_url: " << m_url;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << m_url.substr(0, 16);
m_last_state = MEDIASTATE_LOADING;
SetStatus(_L("Loading..."));
if (wxGetApp().app_config->get("internal_developer_mode") == "true") {
@ -207,7 +207,7 @@ void MediaPlayCtrl::Play()
url += "&device=" + m;
url += "&version=" + v;
}
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl camera_url: " << url << ", machine: " << m_machine;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl: " << url.substr(0, 16) << ", machine: " << m_machine;
CallAfter([this, m, url] {
if (m != m_machine) {
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl drop late ttcode for machine: " << m;
@ -263,6 +263,7 @@ void MediaPlayCtrl::Stop(wxString const &msg)
}
bool remote = m_url.find("/local/") == wxString::npos && m_url.find("/rtsp") == wxString::npos;
if (last_state != wxMEDIASTATE_PLAYING && m_failed_code != 0
&& m_last_failed_codes.find(m_failed_code) == m_last_failed_codes.end()
&& (m_user_triggered || m_failed_retry > 3)) {
@ -273,7 +274,6 @@ void MediaPlayCtrl::Stop(wxString const &msg)
j["result"] = "failed";
j["user_triggered"] = m_user_triggered;
j["failed_retry"] = m_failed_retry;
bool remote = m_url.find("/local/") == wxString::npos;
j["tunnel"] = remote ? "remote" : "local";
j["code"] = m_failed_code;
if (remote)
@ -285,7 +285,7 @@ void MediaPlayCtrl::Stop(wxString const &msg)
m_url.clear();
++m_failed_retry;
if (m_failed_code < 0 && last_state != wxMEDIASTATE_PLAYING && (!m_remote_support || m_lan_mode) && (m_failed_retry > 1 || m_user_triggered)) {
if (m_failed_code < 0 && last_state != wxMEDIASTATE_PLAYING && !remote && (m_failed_retry > 1 || m_user_triggered)) {
m_next_retry = wxDateTime(); // stop retry
if (wxGetApp().show_modal_ip_address_enter_dialog(_L("LAN Connection Failed (Failed to start liveview)"))) {
m_failed_retry = 0;
@ -384,7 +384,7 @@ void MediaPlayCtrl::ToggleStream()
url += "&device=" + m;
url += "&version=" + v;
}
BOOST_LOG_TRIVIAL(info) << "camera_url: " << url;
BOOST_LOG_TRIVIAL(info) << "MediaPlayCtrl::ToggleStream: " << url.substr(0, 16);
CallAfter([this, m, url] {
if (m != m_machine) return;
if (url.empty() || !boost::algorithm::starts_with(url, "bambu:///")) {

View file

@ -1903,7 +1903,7 @@ void NotificationManager::push_slicing_error_notification(const std::string &tex
push_notification_data({ NotificationType::SlicingError, NotificationLevel::ErrorNotificationLevel, 0, _u8L("Error:") + "\n" + text, link, callback }, 0);
set_slicing_progress_hidden();
}
void NotificationManager::push_slicing_warning_notification(const std::string& text, bool gray, ModelObject const * obj, ObjectID oid, int warning_step, int warning_msg_id)
void NotificationManager::push_slicing_warning_notification(const std::string& text, bool gray, ModelObject const * obj, ObjectID oid, int warning_step, int warning_msg_id, NotificationLevel level/* = NotificationLevel::WarningNotificationLevel*/)
{
auto callback = obj ? [id = obj->id()](wxEvtHandler *) {
auto & objects = wxGetApp().model().objects;
@ -1916,7 +1916,7 @@ void NotificationManager::push_slicing_warning_notification(const std::string& t
} : std::function<bool(wxEvtHandler *)>();
auto link = callback ? _u8L("Jump to") : "";
if (obj) link += std::string(" [") + obj->name + "]";
NotificationData data { NotificationType::SlicingWarning, NotificationLevel::WarningNotificationLevel, 0, _u8L("Warning:") + "\n" + text, link, callback };
NotificationData data { NotificationType::SlicingWarning, level, 0, _u8L("Warning:") + "\n" + text, link, callback };
data.sub_msg_id = warning_msg_id;
data.ori_text = text;
@ -2072,6 +2072,14 @@ void NotificationManager::push_exporting_finished_notification(const std::string
set_slicing_progress_hidden();
}
void NotificationManager::push_import_finished_notification(const std::string& path, const std::string& dir_path, bool on_removable)
{
close_notification_of_type(NotificationType::ExportFinished);
NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotificationLevel, on_removable ? 0 : 20, _u8L("Model file downloaded.") + "\n" + path };
push_notification_data(std::make_unique<NotificationManager::ExportFinishedNotification>(data, m_id_provider, m_evt_handler, on_removable, path, dir_path), 0);
set_slicing_progress_hidden();
}
void NotificationManager::push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage)
{
// find if upload with same id was not already in notification

View file

@ -200,7 +200,7 @@ public:
// Creates Slicing Error notification with a custom text and no fade out.
void push_slicing_error_notification(const std::string &text, std::vector<ModelObject const *> objs);
// Creates Slicing Warning notification with a custom text and no fade out.
void push_slicing_warning_notification(const std::string &text, bool gray, ModelObject const *obj, ObjectID oid, int warning_step, int warning_msg_id);
void push_slicing_warning_notification(const std::string &text, bool gray, ModelObject const *obj, ObjectID oid, int warning_step, int warning_msg_id, NotificationLevel level = NotificationLevel::WarningNotificationLevel);
// marks slicing errors as gray
void set_all_slicing_errors_gray(bool g);
// marks slicing warings as gray
@ -236,6 +236,7 @@ public:
void set_sla(bool b) { set_fff(!b); }
// Exporting finished, show this information with path, button to open containing folder and if ejectable - eject button
void push_exporting_finished_notification(const std::string& path, const std::string& dir_path, bool on_removable);
void push_import_finished_notification(const std::string& path, const std::string& dir_path, bool on_removable);
// notifications with progress bar
// slicing progress
void init_slicing_progress_notification(std::function<bool()> cancel_callback);

View file

@ -78,6 +78,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
case coEnums:
m_fields.emplace(id, Choice::Create<Choice>(this->ctrl_parent(), opt, id));
break;
case coPoint:
case coPoints:
m_fields.emplace(id, PointCtrl::Create<PointCtrl>(this->ctrl_parent(), opt, id));
break;
@ -1033,6 +1034,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
case coEnums:
ret = config.opt_int(opt_key, idx);
break;
case coPoint:
ret = config.option<ConfigOptionPoint>(opt_key)->value;
break;
case coPoints:
if (opt_key == "printable_area")
ret = config.option<ConfigOptionPoints>(opt_key)->values;
@ -1145,6 +1149,9 @@ boost::any ConfigOptionsGroup::get_config_value2(const DynamicPrintConfig& confi
case coEnums:
ret = config.opt_int(opt_key, idx);
break;
case coPoint:
ret = config.option<ConfigOptionPoint>(opt_key)->value;
break;
case coPoints:
if (opt_key == "printable_area")
ret = config.option<ConfigOptionPoints>(opt_key)->values;

View file

@ -2106,7 +2106,7 @@ void PartPlate::duplicate_all_instance(unsigned int dup_count, bool need_skip, s
ModelObject* newObj = m_model->add_object(*object);
newObj->name = object->name +"_"+ std::to_string(index+1);
int new_obj_id = m_model->objects.size() - 1;
for ( size_t new_instance_id = 0; new_instance_id < object->instances.size(); new_instance_id++ )
for ( size_t new_instance_id = 0; new_instance_id < newObj->instances.size(); new_instance_id++ )
{
obj_to_instance_set.emplace(std::pair(new_obj_id, new_instance_id));
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": duplicate object into plate: index_pair [%1%,%2%], obj_id %3%") % new_obj_id % new_instance_id % newObj->id().id;
@ -2115,6 +2115,31 @@ void PartPlate::duplicate_all_instance(unsigned int dup_count, bool need_skip, s
}
}
for (std::set<std::pair<int, int>>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it)
{
int obj_id = it->first;
int instance_id = it->second;
if ((obj_id >= 0) && (obj_id < m_model->objects.size()))
{
ModelObject* object = m_model->objects[obj_id];
ModelInstance* instance = object->instances[instance_id];
if (instance->printable)
{
instance->loaded_id = instance->id().id;
if (need_skip) {
while (skip_objects.find(instance->loaded_id) != skip_objects.end())
{
instance->loaded_id ++;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": duplicated id %1% with skip, try new one %2%") %instance->id().id % instance->loaded_id;
}
}
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": set obj %1% instance %2%'s loaded_id to its id %3%, name %4%") % obj_id %instance_id %instance->loaded_id % object->name;
}
}
}
return;
}
@ -4518,7 +4543,7 @@ bool PartPlateList::set_shapes(const Pointfs& shape, const Pointfs& exclude_area
pos = compute_shape_position(i, m_plate_cols);
plate->set_shape(shape, exclude_areas, pos, height_to_lid, height_to_rod);
}
is_load_bedtype_textures = false;//reload textures
calc_bounding_boxes();
auto check_texture = [](const std::string& texture) {
@ -4851,6 +4876,8 @@ int PartPlateList::store_to_3mf_structure(PlateDataPtrs& plate_data_list, bool w
plate_data_item->gcode_prediction = std::to_string(
(int) m_plate_list[i]->get_slice_result()->print_statistics.modes[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].time);
plate_data_item->toolpath_outside = m_plate_list[i]->m_gcode_result->toolpath_outside;
plate_data_item->timelapse_warning_code = m_plate_list[i]->m_gcode_result->timelapse_warning_code;
m_plate_list[i]->set_timelapse_warning_code(plate_data_item->timelapse_warning_code);
plate_data_item->is_label_object_enabled = m_plate_list[i]->m_gcode_result->label_object_enabled;
Print *print = nullptr;
m_plate_list[i]->get_print((PrintBase **) &print, nullptr, nullptr);
@ -4923,6 +4950,8 @@ int PartPlateList::load_from_3mf_structure(PlateDataPtrs& plate_data_list)
ps.total_used_filament *= 1000; //koef
gcode_result->toolpath_outside = plate_data_list[i]->toolpath_outside;
gcode_result->label_object_enabled = plate_data_list[i]->is_label_object_enabled;
gcode_result->timelapse_warning_code = plate_data_list[i]->timelapse_warning_code;
m_plate_list[index]->set_timelapse_warning_code(plate_data_list[i]->timelapse_warning_code);
m_plate_list[index]->slice_filaments_info = plate_data_list[i]->slice_filaments_info;
gcode_result->warnings = plate_data_list[i]->warnings;
if (m_plater && !plate_data_list[i]->thumbnail_file.empty()) {
@ -5054,15 +5083,17 @@ void PartPlateList::BedTextureInfo::TexturePart::update_buffer()
void PartPlateList::init_bed_type_info()
{
BedTextureInfo::TexturePart pc_part1( 5, 130, 10, 110, "bbl_bed_pc_left.svg");
BedTextureInfo::TexturePart pc_part2( 74, -12, 150, 12, "bbl_bed_pc_bottom.svg");
BedTextureInfo::TexturePart ep_part1( 4, 87, 12, 153, "bbl_bed_ep_left.svg");
BedTextureInfo::TexturePart ep_part2( 72, -11, 150, 12, "bbl_bed_ep_bottom.svg");
BedTextureInfo::TexturePart pei_part1( 6, 50, 12, 190, "bbl_bed_pei_left.svg");
BedTextureInfo::TexturePart pei_part2(72, -11, 150, 12, "bbl_bed_pei_bottom.svg");
BedTextureInfo::TexturePart pte_part1( 6, 40, 12, 200, "bbl_bed_pte_left.svg");
BedTextureInfo::TexturePart pte_part2(72, -11, 150, 12, "bbl_bed_pte_bottom.svg");
BedTextureInfo::TexturePart pc_part1(10, 130, 10, 110, "bbl_bed_pc_left.svg");
BedTextureInfo::TexturePart pc_part2(74, -10, 148, 12, "bbl_bed_pc_bottom.svg");
BedTextureInfo::TexturePart ep_part1(7.5, 90, 12.5, 150, "bbl_bed_ep_left.svg");
BedTextureInfo::TexturePart ep_part2(74, -10, 148, 12, "bbl_bed_ep_bottom.svg");
BedTextureInfo::TexturePart pei_part1(7.5, 50, 12.5, 190, "bbl_bed_pei_left.svg");
BedTextureInfo::TexturePart pei_part2(74, -10, 148, 12, "bbl_bed_pei_bottom.svg");
BedTextureInfo::TexturePart pte_part1(10, 80, 10, 160, "bbl_bed_pte_left.svg");
BedTextureInfo::TexturePart pte_part2(74, -10, 148, 12, "bbl_bed_pte_bottom.svg");
for (size_t i = 0; i < btCount; i++) {
bed_texture_info[i].parts.clear();
}
bed_texture_info[btPC].parts.push_back(pc_part1);
bed_texture_info[btPC].parts.push_back(pc_part2);
bed_texture_info[btEP].parts.push_back(ep_part1);
@ -5072,8 +5103,19 @@ void PartPlateList::init_bed_type_info()
bed_texture_info[btPTE].parts.push_back(pte_part1);
bed_texture_info[btPTE].parts.push_back(pte_part2);
auto bed_ext = get_extents(m_shape);
int bed_width = bed_ext.size()(0);
int bed_height = bed_ext.size()(1);
float base_width = 256;
float base_height = 256;
float x_rate = bed_width / base_width;
float y_rate = bed_height / base_height;
for (int i = 0; i < btCount; i++) {
for (int j = 0; j < bed_texture_info[i].parts.size(); j++) {
bed_texture_info[i].parts[j].x *= x_rate;
bed_texture_info[i].parts[j].y *= y_rate;
bed_texture_info[i].parts[j].w *= x_rate;
bed_texture_info[i].parts[j].h *= y_rate;
bed_texture_info[i].parts[j].update_buffer();
}
}

View file

@ -144,6 +144,7 @@ private:
GLUquadricObject* m_quadric;
int m_hover_id;
bool m_selected;
int m_timelapse_warning_code = 0;
// BBS
DynamicPrintConfig m_config;
@ -263,6 +264,9 @@ public:
//set the plate's name
void set_plate_name(const std::string& name);
void set_timelapse_warning_code(int code) { m_timelapse_warning_code = code; }
int timelapse_warning_code() { return m_timelapse_warning_code; }
//get the print's object, result and index
void get_print(PrintBase **print, GCodeResult **result, int *index);
@ -560,16 +564,16 @@ public:
class TexturePart {
public:
// position
int x;
int y;
int w;
int h;
float x;
float y;
float w;
float h;
unsigned int vbo_id;
std::string filename;
GLTexture* texture { nullptr };
Vec2d offset;
GeometryBuffer* buffer { nullptr };
TexturePart(int xx, int yy, int ww, int hh, std::string file) {
TexturePart(float xx, float yy, float ww, float hh, std::string file){
x = xx; y = yy;
w = ww; h = hh;
filename = file;
@ -799,7 +803,8 @@ public:
template<class Archive> void serialize(Archive& ar)
{
//ar(cereal::base_class<ObjectBase>(this));
ar(m_shape, m_plate_width, m_plate_depth, m_plate_height, m_height_to_lid, m_height_to_rod, m_height_limit_mode, m_plate_count, m_current_plate, m_plate_list, unprintable_plate);
//Cancel undo/redo for m_shape ,Because the printing area of different models is different, currently if the grid changes, it cannot correspond to the model on the left ui
ar(m_plate_width, m_plate_depth, m_plate_height, m_height_to_lid, m_height_to_rod, m_height_limit_mode, m_plate_count, m_current_plate, m_plate_list, unprintable_plate);
//ar(m_plate_width, m_plate_depth, m_plate_height, m_plate_count, m_current_plate);
}

View file

@ -40,6 +40,7 @@
#include <wx/popupwin.h>
#endif
#include <wx/clrpicker.h>
#include <wx/tokenzr.h>
#include "libslic3r/libslic3r.h"
#include "libslic3r/Format/STL.hpp"
@ -174,7 +175,7 @@ wxDEFINE_EVENT(EVT_INSTALL_PLUGIN_HINT, wxCommandEvent);
wxDEFINE_EVENT(EVT_PREVIEW_ONLY_MODE_HINT, wxCommandEvent);
//BBS: change light/dark mode
wxDEFINE_EVENT(EVT_GLCANVAS_COLOR_MODE_CHANGED, SimpleEvent);
//BBS: print
//BBS: print
wxDEFINE_EVENT(EVT_PRINT_FROM_SDCARD_VIEW, SimpleEvent);
@ -1451,7 +1452,7 @@ std::map<int, DynamicPrintConfig> Sidebar::build_filament_ams_list(MachineObject
void Sidebar::load_ams_list(std::string const &device, MachineObject* obj)
{
std::map<int, DynamicPrintConfig> filament_ams_list = build_filament_ams_list(obj);
if (!obj) {
p->ams_list_device = device;
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << " clear list";
@ -2333,6 +2334,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
"enable_support", "support_filament", "support_interface_filament",
"support_top_z_distance", "support_bottom_z_distance", "raft_layers",
"wipe_tower_rotation_angle", "wipe_tower_cone_angle", "wipe_tower_extra_spacing", "wipe_tower_extruder",
"best_object_pos"
}))
, sidebar(new Sidebar(q))
, notification_manager(std::make_unique<NotificationManager>(q))
@ -2569,7 +2571,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
// update slice and print button
wxGetApp().mainframe->update_slice_print_status(MainFrame::SlicePrintEventType::eEventSliceUpdate, true, false);
update();
set_need_update(true);
});
}
if (wxGetApp().is_gcode_viewer())
@ -2807,97 +2809,6 @@ void Plater::priv::select_view(const std::string& direction)
assemble_view->select_view(direction);
}
}
// BBS set print speed table and find maximum speed
void Plater::setPrintSpeedTable(GlobalSpeedMap &printSpeedMap) {
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;
}
if (config.has("small_perimeter_speed")) {
printSpeedMap.smallPerimeterSpeed = config.get_abs_value("small_perimeter_speed");
if (printSpeedMap.smallPerimeterSpeed > printSpeedMap.maxSpeed)
printSpeedMap.maxSpeed = printSpeedMap.smallPerimeterSpeed;
}
/* "inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed",
"top_surface_speed", "support_speed", "support_object_xy_distance", "support_interface_speed",
"bridge_speed", "gap_infill_speed", "travel_speed", "initial_layer_speed"*/
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()));
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 Plater::setExtruderParams(std::map<size_t, Slic3r::ExtruderParams>& extParas) {
extParas.clear();
Slic3r::DynamicPrintConfig config = wxGetApp().preset_bundle->full_config();
// BBS
int numExtruders = wxGetApp().preset_bundle->filament_presets.size();
for (unsigned int i = 0; i != numExtruders; ++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) extParas.insert({ i,{matName, bedTemp, endTemp} });
extParas.insert({ i + 1,{matName, bedTemp, endTemp} });
}
}
wxColour Plater::get_next_color_for_filament()
{
@ -2930,7 +2841,12 @@ wxString Plater::get_slice_warning_string(GCodeProcessorResult::SliceWarning& wa
return _L("The bed temperature exceeds filament's vitrification temperature. Please open the front door of printer before printing to avoid nozzle clog.");
} else if (warning.msg == NOZZLE_HRC_CHECKER) {
return _L("The nozzle hardness required by the filament is higher than the default nozzle hardness of the printer. Please replace the hardened nozzle or filament, otherwise, the nozzle will be attrited or damaged.");
} else {
} else if (warning.msg == NOT_SUPPORT_TRADITIONAL_TIMELAPSE) {
return _L("Enabling traditional timelapse photography may cause surface imperfections. It is recommended to change to smooth mode.");
} else if (warning.msg == NOT_GENERATE_TIMELAPSE) {
return wxString();
}
else {
return wxString(warning.msg);
}
}
@ -2963,8 +2879,13 @@ void Plater::priv::select_view_3D(const std::string& name, bool no_slice)
else if (name == "Preview") {
BOOST_LOG_TRIVIAL(info) << "select preview";
//BBS update extruder params and speed table before slicing
Plater::setExtruderParams(Slic3r::Model::extruderParamsMap);
Plater::setPrintSpeedTable(Slic3r::Model::printSpeedMap);
const Slic3r::DynamicPrintConfig& config = wxGetApp().preset_bundle->full_config();
auto& print = q->get_partplate_list().get_current_fff_print();
auto print_config = print.config();
int numExtruders = wxGetApp().preset_bundle->filament_presets.size();
Model::setExtruderParams(config, numExtruders);
Model::setPrintSpeedTable(config, print_config);
set_current_panel(preview, no_slice);
}
else if (name == "Assemble") {
@ -4853,7 +4774,7 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const
Model new_model;
try {
new_model = Model::read_from_file(path, nullptr, nullptr, LoadStrategy::AddDefaultInstances);
new_model = Model::read_from_file(path, nullptr, nullptr, LoadStrategy::AddDefaultInstances | LoadStrategy::LoadModel);
for (ModelObject* model_object : new_model.objects) {
model_object->center_around_origin();
model_object->ensure_on_bed();
@ -5876,7 +5797,11 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
// Now process state.warnings.
for (auto const& warning : state.warnings) {
if (warning.current) {
notification_manager->push_slicing_warning_notification(warning.message, false, model_object, object_id, warning_step, warning.message_id);
NotificationManager::NotificationLevel notif_level = NotificationManager::NotificationLevel::WarningNotificationLevel;
if (evt.status.message_type == PrintStateBase::SlicingNotificationType::SlicingReplaceInitEmptyLayers | PrintStateBase::SlicingNotificationType::SlicingEmptyGcodeLayers) {
notif_level = NotificationManager::NotificationLevel::SeriousWarningNotificationLevel;
}
notification_manager->push_slicing_warning_notification(warning.message, false, model_object, object_id, warning_step, warning.message_id, notif_level);
add_warning(warning, object_id.id);
}
}
@ -6045,8 +5970,8 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
}
} else {
std::vector<const ModelObject *> ptrs;
for (auto oid : message.second)
{
for (auto oid : message.second)
{
const PrintObject *print_object = this->background_process.m_fff_print->get_object(ObjectID(oid));
if (print_object) { ptrs.push_back(print_object->model_object()); }
}
@ -6258,8 +6183,13 @@ void Plater::priv::on_action_slice_plate(SimpleEvent&)
if (q != nullptr) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received slice plate event\n" ;
//BBS update extruder params and speed table before slicing
Plater::setExtruderParams(Slic3r::Model::extruderParamsMap);
Plater::setPrintSpeedTable(Slic3r::Model::printSpeedMap);
const Slic3r::DynamicPrintConfig& config = wxGetApp().preset_bundle->full_config();
auto& print = q->get_partplate_list().get_current_fff_print();
auto print_config = print.config();
int numExtruders = wxGetApp().preset_bundle->filament_presets.size();
Model::setExtruderParams(config, numExtruders);
Model::setPrintSpeedTable(config, print_config);
m_slice_all = false;
q->reslice();
q->select_view_3D("Preview");
@ -6272,8 +6202,13 @@ void Plater::priv::on_action_slice_all(SimpleEvent&)
if (q != nullptr) {
BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << ":received slice project event\n" ;
//BBS update extruder params and speed table before slicing
Plater::setExtruderParams(Slic3r::Model::extruderParamsMap);
Plater::setPrintSpeedTable(Slic3r::Model::printSpeedMap);
const Slic3r::DynamicPrintConfig& config = wxGetApp().preset_bundle->full_config();
auto& print = q->get_partplate_list().get_current_fff_print();
auto print_config = print.config();
int numExtruders = wxGetApp().preset_bundle->filament_presets.size();
Model::setExtruderParams(config, numExtruders);
Model::setPrintSpeedTable(config, print_config);
m_slice_all = true;
m_slice_all_only_has_gcode = true;
m_cur_slice_plate = 0;
@ -7642,10 +7577,10 @@ void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bo
// triangle meshes may have gotten released from the scene or the background processing, therefore now being calculated into the Undo / Redo stack size.
this->undo_redo_stack().release_least_recently_used();
//YS_FIXME update obj_list from the deserialized model (maybe store ObjectIDs into the tree?) (no selections at this point of time)
get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
assemble_view->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances) :
this->view3D->get_canvas3d()->get_selection().set_deserialized(GUI::Selection::EMode(this->undo_redo_stack().selection_deserialized().mode), this->undo_redo_stack().selection_deserialized().volumes_and_instances);
get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
get_current_canvas3D()->get_canvas_type() == GLCanvas3D::CanvasAssembleView ?
assemble_view->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot) :
this->view3D->get_canvas3d()->get_gizmos_manager().update_after_undo_redo(snapshot);
@ -8039,26 +7974,25 @@ int Plater::save_project(bool saveAs)
//BBS import model by model id
void Plater::import_model_id(wxString download_info)
{
//std::string download_origin_url = wxGetApp().url_decode(download_info.ToStdString());
std::string download_origin_url = download_info.ToStdString();
std::string download_url;
std::string filename;
wxString download_origin_url = download_info;
wxString download_url;
wxString filename;
wxString separator = "&name=";
try
{
std::vector<std::string> origin_array = wxGetApp().split_str(download_origin_url, "&name=");
if (origin_array.size() >= 2) {
size_t namePos = download_info.Find(separator);
if (namePos != wxString::npos) {
download_url = download_info.Mid(0, namePos);
filename = download_info.Mid(namePos + separator.Length());
download_url = origin_array[0];
filename = origin_array[1];
}
else if (!download_origin_url.empty()) {
fs::path download_path = fs::path(download_origin_url);
else {
fs::path download_path = fs::path(download_origin_url.wx_str());
download_url = download_origin_url;
filename = download_path.filename().string();
}
}
catch (const std::exception& error)
{
@ -8066,7 +8000,8 @@ void Plater::import_model_id(wxString download_info)
}
bool download_ok = false;
/* save to a file */
int retry_count = 0;
const int max_retries = 3;
/* jump to 3D eidtor */
wxGetApp().mainframe->select_tab((size_t)MainFrame::TabPosition::tp3DEditor);
@ -8094,7 +8029,7 @@ void Plater::import_model_id(wxString download_info)
p->project.reset();
/* prepare project and profile */
boost::thread import_thread = Slic3r::create_thread([&percent, &cont, &cancel, &msg, &target_path, &download_ok, download_url, &filename] {
boost::thread import_thread = Slic3r::create_thread([&percent, &cont, &cancel, &retry_count, max_retries, &msg, &target_path, &download_ok, download_url, &filename] {
NetworkAgent* m_agent = Slic3r::GUI::wxGetApp().getAgent();
if (!m_agent) return;
@ -8115,7 +8050,7 @@ void Plater::import_model_id(wxString download_info)
try
{
vecFiles.clear();
wxString extension = fs::path(filename).extension().c_str();
wxString extension = fs::path(filename.wx_str()).extension().c_str();
auto name = filename.substr(0, filename.length() - extension.length() - 1);
for (const auto& iter : boost::filesystem::directory_iterator(target_path))
@ -8138,7 +8073,7 @@ void Plater::import_model_id(wxString download_info)
//update filename
if (is_already_exist && vecFiles.size() >= 1) {
wxString extension = fs::path(filename).extension().c_str();
wxString extension = fs::path(filename.wx_str()).extension().c_str();
wxString name = filename.substr(0, filename.length() - extension.length());
filename = wxString::Format("%s(%d)%s", name, vecFiles.size() + 1, extension).ToStdString();
}
@ -8158,43 +8093,49 @@ void Plater::import_model_id(wxString download_info)
}
//target_path /= (boost::format("%1%_%2%.3mf") % filename % unique).str();
target_path /= fs::path(wxString(filename).wc_str());
target_path /= fs::path(filename.wc_str());
fs::path tmp_path = target_path;
tmp_path += format(".%1%", ".download");
auto url = download_url;
auto http = Http::get(url);
http.on_progress([&percent, &cont, &msg](Http::Progress progress, bool& cancel) {
if (!cont) cancel = true;
if (progress.dltotal != 0) {
percent = progress.dlnow * 100 / progress.dltotal;
}
msg = wxString::Format(_L("Project downloaded %d%%"), percent);
})
.on_error([&msg, &cont](std::string body, std::string error, unsigned http_status) {
(void)body;
BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%",
body,
http_status,
error);
msg = wxString::Format("Download Failed! body=%s, error=%s, status=%d", body, error, http_status);
cont = false;
return;
auto http = Http::get(download_url.ToStdString());
while (cont && retry_count < max_retries) {
retry_count++;
http.on_progress([&percent, &cont, &msg](Http::Progress progress, bool& cancel) {
if (!cont) cancel = true;
if (progress.dltotal != 0) {
percent = progress.dlnow * 100 / progress.dltotal;
}
msg = wxString::Format(_L("Project downloaded %d%%"), percent);
})
.on_error([&msg, &cont, &retry_count, max_retries](std::string body, std::string error, unsigned http_status) {
(void)body;
BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%",
body,
http_status,
error);
if (retry_count == max_retries) {
msg = _L("Importing to Bambu Studio failed. Please download the file and manually import it.");
cont = false;
}
})
.on_complete([&cont, &download_ok, tmp_path, target_path](std::string body, unsigned /* http_status */) {
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
file.write(body.c_str(), body.size());
file.close();
fs::rename(tmp_path, target_path);
cont = false;
download_ok = true;
})
.perform_sync();
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
file.write(body.c_str(), body.size());
file.close();
fs::rename(tmp_path, target_path);
cont = false;
download_ok = true;
}).perform_sync();
// for break while
cont = false;
});
// for break while
//cont = false;
}
});
while (cont && cont_dlg) {
wxMilliSleep(50);
@ -8216,8 +8157,7 @@ void Plater::import_model_id(wxString download_info)
if (download_ok) {
BOOST_LOG_TRIVIAL(trace) << "import_model_id: target_path = " << target_path.string();
/* load project */
this->load_project(encode_path(target_path.string().c_str()));
this->load_project(target_path.wstring());
/*BBS set project info after load project, project info is reset in load project */
//p->project.project_model_id = model_id;
//p->project.project_design_id = design_id;
@ -8227,10 +8167,15 @@ void Plater::import_model_id(wxString download_info)
}
// show save new project
p->set_project_filename(wxString(filename));
p->set_project_filename(filename);
p->notification_manager->push_import_finished_notification(target_path.string(), target_path.parent_path().string(), false);
}
else {
if (!msg.empty()) wxMessageBox(msg);
if (!msg.empty()) {
MessageDialog msg_wingow(nullptr, msg, wxEmptyString, wxICON_WARNING | wxOK);
msg_wingow.SetSize(wxSize(FromDIP(480), -1));
msg_wingow.ShowModal();
}
return;
}
}
@ -9598,16 +9543,17 @@ void Plater::add_file()
}
}
void Plater::update(bool conside_update_flag)
void Plater::update(bool conside_update_flag, bool force_background_processing_update)
{
unsigned int flag = force_background_processing_update ? (unsigned int)Plater::priv::UpdateParams::FORCE_BACKGROUND_PROCESSING_UPDATE : 0;
if (conside_update_flag) {
if (need_update()) {
p->update();
p->update(flag);
p->set_need_update(false);
}
}
else
p->update();
p->update(flag);
}
void Plater::object_list_changed() { p->object_list_changed(); }
@ -11085,7 +11031,7 @@ void Plater::print_job_finished(wxCommandEvent &evt)
p->enter_prepare_mode();
}
Slic3r::DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
if (!dev) return;
@ -11220,7 +11166,7 @@ void Plater::on_filaments_change(size_t num_filaments)
for (int i = 0; i < plate_list.get_plate_count(); ++i) {
PartPlate* part_plate = plate_list.get_plate(i);
part_plate->update_first_layer_print_sequence(num_filaments);
}
}
for (ModelObject* mo : wxGetApp().model().objects) {
for (ModelVolume* mv : mo->volumes) {
@ -11481,7 +11427,7 @@ void Plater::update_print_error_info(int code, std::string msg, std::string extr
if (p->main_frame->m_calibration)
p->main_frame->m_calibration->update_print_error_info(code, msg, extra);
}
wxString Plater::get_project_filename(const wxString& extension) const
{
return p->get_project_filename(extension);
@ -12299,7 +12245,7 @@ int Plater::select_plate_by_hover_id(int hover_id, bool right_click, bool isModi
if (!ret) {
PlateNameEditDialog dlg(this, wxID_ANY, _L("Edit Plate Name"));
PartPlate * curr_plate = p->partplate_list.get_curr_plate();
wxString curr_plate_name = from_u8(curr_plate->get_plate_name());
dlg.set_plate_name(curr_plate_name);

View file

@ -259,9 +259,7 @@ public:
void update_all_plate_thumbnails(bool force_update = false);
void invalid_all_plate_thumbnails();
void force_update_all_plate_thumbnails();
//BBS static functions that update extruder params and speed table
static void setPrintSpeedTable(Slic3r::GlobalSpeedMap& printSpeedMap);
static void setExtruderParams(std::map<size_t, Slic3r::ExtruderParams>& extParas);
static wxColour get_next_color_for_filament();
static wxString get_slice_warning_string(GCodeProcessorResult::SliceWarning& warning);
@ -274,7 +272,7 @@ public:
const wxString& get_last_loaded_gcode() const { return m_last_loaded_gcode; }
void update(bool conside_update_flag = false);
void update(bool conside_update_flag = false, bool force_background_processing_update = false);
//BBS
void object_list_changed();
void stop_jobs();
@ -292,7 +290,7 @@ public:
bool is_view3D_overhang_shown() const;
void show_view3D_overhang(bool show);
bool is_sidebar_collapsed() const;
void collapse_sidebar(bool show);

View file

@ -55,6 +55,12 @@ PrintOptionsDialog::PrintOptionsDialog(wxWindow* parent)
}
evt.Skip();
});
m_cb_sup_sound->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent& evt) {
if (obj) {
obj->command_xcam_control_allow_prompt_sound(m_cb_sup_sound->GetValue());
}
evt.Skip();
});
wxGetApp().UpdateDlgDarkUI(this);
}
@ -131,14 +137,23 @@ void PrintOptionsDialog::update_options(MachineObject* obj_)
m_cb_auto_recovery->Hide();
line4->Hide();
}
if (obj_->is_function_supported(PrinterFunction::FUNC_PROMPT_SOUND)) {
text_sup_sound->Show();
m_cb_sup_sound->Show();
line5->Show();
}
else {
text_sup_sound->Hide();
m_cb_sup_sound->Hide();
line5->Hide();
}
this->Freeze();
auto test1 = obj_->xcam_first_layer_inspector;
auto test2 = obj_->xcam_buildplate_marker_detector;
auto test3 = obj_->xcam_auto_recovery_step_loss;
m_cb_first_layer->SetValue(obj_->xcam_first_layer_inspector);
m_cb_plate_mark->SetValue(obj_->xcam_buildplate_marker_detector);
m_cb_auto_recovery->SetValue(obj_->xcam_auto_recovery_step_loss);
m_cb_sup_sound->SetValue(obj_->xcam_allow_prompt_sound);
m_cb_ai_monitoring->SetValue(obj_->xcam_ai_monitoring);
for (auto i = AiMonitorSensitivityLevel::LOW; i < LEVELS_NUM; i = (AiMonitorSensitivityLevel) (i + 1)) {
@ -256,6 +271,22 @@ wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent)
sizer->Add(line4, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20));
sizer->Add(0,0,0,wxTOP, FromDIP(20));
//Allow prompt sound
line_sizer = new wxBoxSizer(wxHORIZONTAL);
m_cb_sup_sound = new CheckBox(parent);
text_sup_sound = new wxStaticText(parent, wxID_ANY, _L("Allow Prompt Sound"));
text_sup_sound->SetFont(Label::Body_14);
line_sizer->Add(FromDIP(5), 0, 0, 0);
line_sizer->Add(m_cb_sup_sound, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5));
line_sizer->Add(text_sup_sound, 1, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5));
sizer->Add(0, 0, 0, wxTOP, FromDIP(15));
sizer->Add(line_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(18));
line_sizer->Add(FromDIP(5), 0, 0, 0);
line5 = new StaticLine(parent, false);
line5->SetLineColour(STATIC_BOX_LINE_COL);
sizer->Add(line5, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20));
ai_monitoring_level_list->Connect( wxEVT_COMBOBOX, wxCommandEventHandler(PrintOptionsDialog::set_ai_monitor_sensitivity), NULL, this );
return sizer;

View file

@ -26,6 +26,7 @@ protected:
CheckBox* m_cb_ai_monitoring;
CheckBox* m_cb_plate_mark;
CheckBox* m_cb_auto_recovery;
CheckBox* m_cb_sup_sound;
wxStaticText* text_first_layer;
wxStaticText* text_ai_monitoring;
wxStaticText* text_ai_monitoring_caption;
@ -33,10 +34,12 @@ protected:
wxStaticText* text_plate_mark;
wxStaticText* text_plate_mark_caption;
wxStaticText* text_auto_recovery;
wxStaticText* text_sup_sound;
StaticLine* line1;
StaticLine* line2;
StaticLine* line3;
StaticLine* line4;
StaticLine* line5;
wxBoxSizer* create_settings_group(wxWindow* parent);
bool print_halt = false;

View file

@ -310,11 +310,18 @@ std::map<std::string, std::vector<json>> ProjectPanel::Reload(wxString aux_path)
pfile_obj["filename"] = wxGetApp().url_encode(file_path_obj.filename().string().c_str());
pfile_obj["size"] = formatBytes((unsigned long)filelen);
std::string file_extension = file_path_obj.extension().string();
boost::algorithm::to_lower(file_extension);
//image
if (file_path_obj.extension() == ".jpg" ||
file_path_obj.extension() == ".jpeg" ||
file_path_obj.extension() == ".png" ||
file_path_obj.extension() == ".bmp")
if (file_extension == ".jpg" ||
file_extension == ".jpeg" ||
file_extension == ".pjpeg" ||
file_extension == ".png" ||
file_extension == ".jfif" ||
file_extension == ".pjp" ||
file_extension == ".webp" ||
file_extension == ".bmp")
{
wxString base64_str = to_base64(file_path);
@ -343,25 +350,29 @@ std::string ProjectPanel::formatBytes(unsigned long bytes)
wxString ProjectPanel::to_base64(std::string file_path)
{
std::map<std::string, wxBitmapType> base64_format;
base64_format[".jpg"] = wxBITMAP_TYPE_JPEG;
base64_format[".jpeg"] = wxBITMAP_TYPE_JPEG;
base64_format[".png"] = wxBITMAP_TYPE_PNG;
base64_format[".bmp"] = wxBITMAP_TYPE_BMP;
std::ifstream imageFile(encode_path(file_path.c_str()), std::ios::binary);
if (!imageFile) {
return wxEmptyString;
}
std::string extension = file_path.substr(file_path.rfind("."), file_path.length());
std::ostringstream imageStream;
imageStream << imageFile.rdbuf();
auto image = new wxImage(encode_path(file_path.c_str()));
wxMemoryOutputStream mem;
image->SaveFile(mem, base64_format[extension]);
std::string binaryImageData = imageStream.str();
std::string extension;
size_t last_dot = file_path.find_last_of(".");
if (last_dot != std::string::npos) {
extension = file_path.substr(last_dot + 1);
}
wxString bease64_head = wxString::Format("data:image/%s;base64,", extension);
wxString km = wxBase64Encode(mem.GetOutputStreamBuffer()->GetBufferStart(),
mem.GetSize());
std::wstringstream wss;
wss << L"data:image/jpg;base64,";
//wss << wxBase64Encode(km.data(), km.size());
wss << km;
wss << bease64_head;
wss << wxBase64Encode(binaryImageData.data(), binaryImageData.size());
wxString base64_str = wss.str();
return base64_str;

View file

@ -225,14 +225,14 @@ void MachineObjectPanel::doRender(wxDC &dc)
}
auto sizet = dc.GetTextExtent(dev_name);
auto text_end = 0;
if (m_show_edit) {
text_end = size.x - m_unbind_img.GetBmpSize().x - 30;
}
else {
text_end = size.x - m_unbind_img.GetBmpSize().x;
}
wxString finally_name = dev_name;
if (sizet.x > (text_end - left)) {
auto limit_width = text_end - left - dc.GetTextExtent("...").x - 15;
@ -268,7 +268,7 @@ void MachineObjectPanel::doRender(wxDC &dc)
dc.DrawBitmap(m_edit_name_img.bmp(), left, (size.y - m_edit_name_img.GetBmpSize().y) / 2);
}
}
}
void MachineObjectPanel::update_machine_info(MachineObject *info, bool is_my_devices)
@ -867,14 +867,16 @@ void SelectMachinePopup::OnLeftUp(wxMouseEvent &event)
static wxString MACHINE_BED_TYPE_STRING[BED_TYPE_COUNT] = {
//_L("Auto"),
_L("Bambu Cool Plate") + " / " + _L("PLA Plate"),
_L("Bamabu Engineering Plate"),
_L("Bamabu High Temperature Plate")};
_L("Bambu Engineering Plate"),
_L("Bambu Smooth PEI Plate") + "/" + _L("High temperature Plate"),
_L("Bambu Textured PEI Plate")};
static std::string MachineBedTypeString[BED_TYPE_COUNT] = {
//"auto",
"pc",
"pei",
"pe",
"pei",
"pte",
};
void SelectMachineDialog::stripWhiteSpace(std::string& str)
@ -1205,7 +1207,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
m_sizer_prepare->Add(0, 0, 1, wxTOP, FromDIP(12));
auto hyperlink_sizer = new wxBoxSizer( wxHORIZONTAL );
m_hyperlink = new wxHyperlinkCtrl(m_panel_prepare, wxID_ANY, _L("Can't connect to the printer"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
m_hyperlink = new wxHyperlinkCtrl(m_panel_prepare, wxID_ANY, _L("Click here if you can't connect to the printer"), wxT("https://wiki.bambulab.com/en/software/bambu-studio/failed-to-connect-printer"), wxDefaultPosition, wxDefaultSize, wxHL_DEFAULT_STYLE);
hyperlink_sizer->Add(m_hyperlink, 0, wxALIGN_CENTER | wxALL, 5);
m_sizer_prepare->Add(hyperlink_sizer, 0, wxALIGN_CENTER | wxALL, 5);
@ -1297,7 +1299,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
m_st_txt_error_desc = new Label(m_sw_print_failed_info, wxEmptyString);
st_title_error_desc->SetForegroundColour(0x909090);
st_title_error_desc_doc->SetForegroundColour(0x909090);
m_st_txt_error_desc->SetForegroundColour(0x909090);
m_st_txt_error_desc->SetForegroundColour(0x909090);
st_title_error_desc->SetFont(::Label::Body_13);
st_title_error_desc_doc->SetFont(::Label::Body_13);
m_st_txt_error_desc->SetFont(::Label::Body_13);
@ -1314,7 +1316,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
m_st_txt_extra_info = new Label(m_sw_print_failed_info, wxEmptyString);
st_title_extra_info->SetForegroundColour(0x909090);
st_title_extra_info_doc->SetForegroundColour(0x909090);
m_st_txt_extra_info->SetForegroundColour(0x909090);
m_st_txt_extra_info->SetForegroundColour(0x909090);
st_title_extra_info->SetFont(::Label::Body_13);
st_title_extra_info_doc->SetFont(::Label::Body_13);
m_st_txt_extra_info->SetFont(::Label::Body_13);
@ -1369,7 +1371,7 @@ SelectMachineDialog::SelectMachineDialog(Plater *plater)
m_sizer_main->Add(0, 0, 0, wxEXPAND | wxTOP, FromDIP(11));
m_sizer_main->Add(m_statictext_printer_msg, 0, wxALIGN_CENTER_HORIZONTAL, 0);
m_sizer_main->Add(0, 1, 0, wxTOP, FromDIP(16));
m_sizer_main->Add(m_sizer_select, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(40));
m_sizer_main->Add(m_sizer_select, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, FromDIP(30));
m_sizer_main->Add(0, 1, 0, wxTOP, FromDIP(10));
m_sizer_main->Add(m_line_schedule, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(30));
m_sizer_main->Add(m_simplebook, 0, wxALIGN_CENTER_HORIZONTAL, 0);
@ -1440,7 +1442,7 @@ void SelectMachineDialog::init_bind()
}
}
}
});
});
m_bitmap_last_plate->Bind(wxEVT_LEFT_DOWN, [this](auto& e) {
if (m_print_plate_idx > 0) {
@ -1541,10 +1543,10 @@ wxWindow *SelectMachineDialog::create_ams_checkbox(wxString title, wxWindow *par
sizer_checkbox->Add(text, 0, wxALIGN_CENTER, 0);
enable_ams = new ScalableBitmap(this, "enable_ams", 16);
auto img_ams_tip = new wxStaticBitmap(checkbox, wxID_ANY, enable_ams->bmp(), wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16)), 0);
img_ams_tip = new wxStaticBitmap(checkbox, wxID_ANY, enable_ams->bmp(), wxDefaultPosition, wxSize(FromDIP(16), FromDIP(16)), 0);
sizer_checkbox->Add(img_ams_tip, 0, wxALIGN_CENTER | wxLEFT, FromDIP(5));
img_ams_tip->Bind(wxEVT_ENTER_WINDOW, [this, img_ams_tip](auto& e) {
img_ams_tip->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {
wxPoint img_pos = img_ams_tip->ClientToScreen(wxPoint(0, 0));
wxPoint popup_pos(img_pos.x, img_pos.y + img_ams_tip->GetRect().height);
m_mapping_tip_popup.Position(popup_pos, wxSize(0, 0));
@ -1561,7 +1563,6 @@ wxWindow *SelectMachineDialog::create_ams_checkbox(wxString title, wxWindow *par
img_ams_tip->Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& e) {
m_mapping_tip_popup.Dismiss();
});
ams_tip = img_ams_tip;
checkbox->SetSizer(sizer_checkbox);
checkbox->Layout();
@ -1637,7 +1638,7 @@ wxWindow *SelectMachineDialog::create_item_checkbox(wxString title, wxWindow *pa
config->set_str("print", param, "0");
}
});
text->Bind(wxEVT_LEFT_DOWN, [this, check, param](wxMouseEvent &) {
//if (!m_checkbox_state_list[param]) {return;}
check->SetValue(check->GetValue() ? false : true);
@ -1673,15 +1674,17 @@ void SelectMachineDialog::update_select_layout(MachineObject *obj)
&& obj->is_support_print_with_timelapse()
&& is_show_timelapse()) {
select_timelapse->Show();
update_timelapse_enable_status();
} else {
select_timelapse->Hide();
}
m_sizer_select->Layout();
Layout();
Fit();
}
void SelectMachineDialog::prepare_mode()
void SelectMachineDialog::prepare_mode(bool refresh_button)
{
// disable combobox
m_comboBox_printer->Enable();
@ -1696,7 +1699,9 @@ void SelectMachineDialog::prepare_mode()
if (wxIsBusy())
wxEndBusyCursor();
Enable_Send_Button(true);
if (refresh_button) {
Enable_Send_Button(true);
}
m_status_bar->reset();
if (m_simplebook->GetSelection() != 0) {
@ -1726,7 +1731,7 @@ void SelectMachineDialog::sending_mode()
Fit();
}
if (m_print_page_mode != PrintPageModeSending) {
m_print_page_mode = PrintPageModeSending;
for (auto it = m_materialList.begin(); it != m_materialList.end(); it++) {
@ -2014,12 +2019,6 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vector<wxSt
else
m_comboBox_printer->Enable();
// m_panel_warn m_simplebook
if (status == PrintDialogStatus::PrintStatusSending) {
sending_mode();
} else {
prepare_mode();
}
// other
if (status == PrintDialogStatus::PrintStatusInit) {
@ -2161,6 +2160,30 @@ void SelectMachineDialog::show_status(PrintDialogStatus status, std::vector<wxSt
update_print_status_msg(msg_text, true, true);
Enable_Send_Button(false);
Enable_Refresh_Button(true);
} else if (status == PrintDialogStatus::PrintStatusTimelapseWarning) {
wxString msg_text;
PartPlate *plate = m_plater->get_partplate_list().get_curr_plate();
for (auto warning : plate->get_slice_result()->warnings) {
if (warning.msg == NOT_GENERATE_TIMELAPSE) {
if (warning.error_code == "1001C001") {
msg_text = _L("When enable spiral vase mode, machines with I3 structure will not generate timelapse videos.");
}
else if (warning.error_code == "1001C002") {
msg_text = _L("When print by object, machines with I3 structure will not generate timelapse videos.");
}
}
}
update_print_status_msg(msg_text, true, true);
Enable_Send_Button(true);
Enable_Refresh_Button(true);
}
// m_panel_warn m_simplebook
if (status == PrintDialogStatus::PrintStatusSending) {
sending_mode();
}
else {
prepare_mode(false);
}
}
@ -2260,14 +2283,23 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event)
PartPlate* plate = m_plater->get_partplate_list().get_curr_plate();
for (auto warning : plate->get_slice_result()->warnings) {
if (warning.msg == BED_TEMP_TOO_HIGH_THAN_FILAMENT) {
if ((obj_->printer_type == "BL-P001" || obj_->printer_type == "BL-P002")) {
if ((obj_->get_printer_series() == PrinterSeries::SERIES_X1)) {
confirm_text.push_back(Plater::get_slice_warning_string(warning) + "\n");
has_slice_warnings = true;
}
}
else if (warning.msg == NOT_SUPPORT_TRADITIONAL_TIMELAPSE) {
if (obj_->get_printer_arch() == PrinterArch::ARCH_I3 && m_checkbox_list["timelapse"]->GetValue()) {
confirm_text.push_back(Plater::get_slice_warning_string(warning) + "\n");
has_slice_warnings = true;
}
}
else if (warning.msg == NOT_GENERATE_TIMELAPSE) {
continue;
}
else {
wxString error_info = Plater::get_slice_warning_string(warning);
if (error_info.IsEmpty()) {
@ -2345,7 +2377,7 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event)
else {
this->on_send_print();
}
});
confirm_text.push_back(_L("Please click the confirm button if you still want to proceed with printing.") + "\n");
@ -2939,7 +2971,6 @@ void SelectMachineDialog::on_timer(wxTimerEvent &event)
if (!obj_
|| obj_->amsList.empty()
|| obj_->ams_exist_bits == 0
|| !obj_->m_is_support_show_bak
|| !obj_->ams_support_auto_switch_filament_flag
|| !obj_->ams_auto_switch_filament_flag
|| !obj_->is_function_supported(PrinterFunction::FUNC_FILAMENT_BACKUP)
@ -3028,6 +3059,8 @@ void SelectMachineDialog::update_ams_check(MachineObject* obj)
&& obj->ams_support_use_ams
&& obj->has_ams()) {
select_use_ams->Show();
if (obj->printer_type == "N1") {img_ams_tip->Hide();}
else {img_ams_tip->Show();}
} else {
select_use_ams->Hide();
}
@ -3144,7 +3177,7 @@ void SelectMachineDialog::update_show_status()
}
}
if (is_blocking_printing()) {
if (m_print_type == PrintFromType::FROM_NORMAL && is_blocking_printing()) {
show_status(PrintDialogStatus::PrintStatusUnsupportedPrinter);
return;
}
@ -3173,6 +3206,11 @@ void SelectMachineDialog::update_show_status()
}
}
if (has_timelapse_warning()) {
show_status(PrintDialogStatus::PrintStatusTimelapseWarning);
return;
}
// no ams
if (!obj_->has_ams() || !m_checkbox_list["use_ams"]->GetValue()) {
if (!has_tips(obj_))
@ -3239,6 +3277,35 @@ void SelectMachineDialog::update_show_status()
}
}
bool SelectMachineDialog::has_timelapse_warning()
{
PartPlate *plate = m_plater->get_partplate_list().get_curr_plate();
for (auto warning : plate->get_slice_result()->warnings) {
if (warning.msg == NOT_GENERATE_TIMELAPSE) {
return true;
}
}
return false;
}
void SelectMachineDialog::update_timelapse_enable_status()
{
AppConfig *config = wxGetApp().app_config;
if (!has_timelapse_warning()) {
if (!config || config->get("print", "timelapse") == "0")
m_checkbox_list["timelapse"]->SetValue(false);
else
m_checkbox_list["timelapse"]->SetValue(true);
select_timelapse->Enable(true);
} else {
m_checkbox_list["timelapse"]->SetValue(false);
select_timelapse->Enable(false);
if (config) { config->set_str("print", "timelapse", "0"); }
}
}
bool SelectMachineDialog::is_show_timelapse()
{
auto compare_version = [](const std::string &version1, const std::string &version2) -> bool {
@ -3342,7 +3409,7 @@ void SelectMachineDialog::on_dpi_changed(const wxRect &suggested_rect)
enable_ams_mapping->msw_rescale();
amsmapping_tip->SetBitmap(enable_ams_mapping->bmp());
enable_ams->msw_rescale();
ams_tip->SetBitmap(enable_ams->bmp());
img_ams_tip->SetBitmap(enable_ams->bmp());
m_button_refresh->SetMinSize(SELECT_MACHINE_DIALOG_BUTTON_SIZE);
m_button_refresh->SetCornerRadius(FromDIP(12));
@ -3350,11 +3417,11 @@ void SelectMachineDialog::on_dpi_changed(const wxRect &suggested_rect)
m_button_ensure->SetCornerRadius(FromDIP(12));
m_status_bar->msw_rescale();
for (auto checkpire : m_checkbox_list) {
for (auto checkpire : m_checkbox_list) {
checkpire.second->Rescale();
}
for (auto material1 : m_materialList) {
for (auto material1 : m_materialList) {
material1.second->item->msw_rescale();
}
@ -3435,7 +3502,7 @@ void SelectMachineDialog::set_default()
filename = m_plater->get_export_gcode_filename("", true);
if (filename.empty()) filename = _L("Untitled");
}
fs::path filename_path(filename.c_str());
m_current_project_name = wxString::FromUTF8(filename_path.filename().string());
@ -3531,7 +3598,7 @@ void SelectMachineDialog::set_default_normal()
std::vector<std::string> materials;
std::vector<std::string> brands;
std::vector<std::string> display_materials;
auto preset_bundle = wxGetApp().preset_bundle;
for (auto filament_name : preset_bundle->filament_presets) {
for (auto iter = preset_bundle->filaments.lbegin(); iter != preset_bundle->filaments.end(); iter++) {
@ -3549,7 +3616,7 @@ void SelectMachineDialog::set_default_normal()
}
}
//init MaterialItem
//init MaterialItem
auto extruders = wxGetApp().plater()->get_partplate_list().get_curr_plate()->get_used_extruders();
BitmapCache bmcache;
@ -3716,8 +3783,8 @@ void SelectMachineDialog::set_default_from_sdcard()
materials.push_back(fo.type);
brands.push_back(fo.brand);
}
//init MaterialItem
//init MaterialItem
MaterialHash::iterator iter = m_materialList.begin();
while (iter != m_materialList.end()) {
int id = iter->first;
@ -3732,7 +3799,7 @@ void SelectMachineDialog::set_default_from_sdcard()
m_materialList.clear();
m_filaments.clear();
for (auto i = 0; i < m_required_data_plate_data_list[m_print_plate_idx]->slice_filaments_info.size(); i++) {
FilamentInfo fo = m_required_data_plate_data_list[m_print_plate_idx]->slice_filaments_info[i];
@ -3900,7 +3967,7 @@ bool SelectMachineDialog::Show(bool show)
if (obj_->is_connected()) {
obj_->disconnect();
}
}
}
}

View file

@ -272,7 +272,8 @@ enum PrintDialogStatus {
PrintStatusNotSupportedSendToSDCard,
PrintStatusNotSupportedPrintAll,
PrintStatusBlankPlate,
PrintStatusUnsupportedPrinter
PrintStatusUnsupportedPrinter,
PrintStatusTimelapseWarning
};
std::string get_print_status_info(PrintDialogStatus status);
@ -385,7 +386,7 @@ protected:
ScalableBitmap * print_weight{nullptr};
wxStaticBitmap * amsmapping_tip{nullptr};
ScalableBitmap * enable_ams_mapping{nullptr};
wxStaticBitmap * ams_tip{nullptr};
wxStaticBitmap * img_ams_tip{nullptr};
wxStaticBitmap * img_ams_backup{nullptr};
ScalableBitmap * enable_ams{nullptr};
@ -400,7 +401,7 @@ public:
void check_fcous_state(wxWindow* window);
void popup_filament_backup();
void update_select_layout(MachineObject *obj);
void prepare_mode();
void prepare_mode(bool refresh_button = true);
void sending_mode();
void finish_mode();
void sync_ams_mapping_result(std::vector<FilamentInfo>& result);
@ -443,6 +444,8 @@ public:
void update_print_error_info(int code, std::string msg, std::string extra);
void set_flow_calibration_state(bool state);
bool is_show_timelapse();
bool has_timelapse_warning();
void update_timelapse_enable_status();
bool is_same_printer_model();
bool is_blocking_printing();
bool has_tips(MachineObject* obj);

File diff suppressed because it is too large Load diff

View file

@ -61,12 +61,102 @@ enum PrintingTaskType {
CALIBRATION,
};
struct ScoreData
{
int rating_id;
int design_id;
std::string model_id;
int profile_id;
int star_count;
bool success_printed;
wxString comment_text;
std::vector<std::string> image_url_paths;
std::set<wxString> need_upload_images;
std::vector<std::pair<wxString, std::string>> local_to_url_image;
};
typedef std::function<void(BBLModelTask* subtask)> OnGetSubTaskFn;
class ScoreDialog : public GUI::DPIDialog
{
public:
ScoreDialog(wxWindow *parent, int design_id, std::string model_id, int profile_id, int rating_id, bool success_printed, int star_count = 0);
ScoreDialog(wxWindow *parent, ScoreData *score_data);
~ScoreDialog();
int get_rating_id() { return m_rating_id; }
ScoreData get_score_data();
void set_comment(std::string comment);
void set_cloud_bitmap(std::vector<std::string> cloud_bitmaps);
protected:
enum StatusCode {
UPLOAD_PROGRESS = 0,
UPLOAD_EXIST_ISSUE,
UPLOAD_IMG_FAILED,
CODE_NUMBER
};
std::shared_ptr<int> m_tocken;
const int m_photo_nums = 16;
int m_rating_id;
int m_design_id;
std::string m_model_id;
int m_profile_id;
int m_star_count;
bool m_success_printed;
std::vector<std::string> m_image_url_paths;
StatusCode m_upload_status_code;
struct ImageMsg
{
wxString local_image_url; //local image path
std::string img_url_paths; // oss url path
vector<wxPanel *> image_broad;
bool is_selected;
bool is_uploaded; // load
wxBoxSizer * image_tb_broad = nullptr;
};
std::vector<ScalableButton *> m_score_star;
wxTextCtrl * m_comment_text = nullptr;
Button * m_button_ok = nullptr;
Button * m_button_cancel = nullptr;
Label * m_add_photo = nullptr;
Label * m_delete_photo = nullptr;
wxGridSizer * m_image_sizer = nullptr;
wxStaticText * warning_text = nullptr;
std::unordered_map<wxStaticBitmap *, ImageMsg> m_image;
std::unordered_set<wxStaticBitmap *> m_selected_image_list;
void init();
void update_static_bitmap(wxStaticBitmap *static_bitmap, wxImage image);
void create_comment_text(const wxString &comment = "");
void load_photo(const std::vector<std::pair<wxString, std::string>> &filePaths);
void on_dpi_changed(const wxRect &suggested_rect) override;
void OnBitmapClicked(wxMouseEvent &event);
wxBoxSizer * create_broad_sizer(wxStaticBitmap *bitmap, ImageMsg &cur_image_msg);
wxBoxSizer * get_score_sizer();
wxBoxSizer * get_star_sizer();
wxBoxSizer * get_comment_text_sizer();
wxBoxSizer * get_photo_btn_sizer();
wxBoxSizer * get_button_sizer();
wxBoxSizer * get_main_sizer(const std::vector<std::pair<wxString, std::string>> &images = std::vector<std::pair<wxString, std::string>>(), const wxString &comment = "");
std::set<std::pair<wxStaticBitmap *, wxString>> add_need_upload_imgs();
std::pair<wxStaticBitmap *, ImageMsg> create_local_thumbnail(wxString &local_path);
std::pair<wxStaticBitmap *, ImageMsg> create_oss_thumbnail(std::string &oss_path);
};
class PrintingTaskPanel : public wxPanel
{
public:
PrintingTaskPanel(wxWindow* parent, PrintingTaskType type);
~PrintingTaskPanel();
void create_panel(wxWindow* parent);
private:
MachineObject* m_obj;
@ -91,6 +181,7 @@ private:
// Orca: show print end time
wxStaticText * m_staticText_progress_end;
wxStaticText* m_staticText_layers;
wxStaticText * m_has_rated_prompt;
wxStaticBitmap* m_bitmap_thumbnail;
wxStaticBitmap* m_bitmap_static_use_time;
wxStaticBitmap* m_bitmap_static_use_weight;
@ -98,6 +189,12 @@ private:
ScalableButton* m_button_abort;
Button* m_button_market_scoring;
Button* m_button_clean;
wxPanel * m_score_subtask_info;
wxPanel * m_score_staticline;
// score page
int m_star_count;
std::vector<ScalableButton *> m_score_star;
bool m_star_count_dirty = false;
ProgressBar* m_gauge_progress;
Label* m_error_text;
@ -122,6 +219,8 @@ public:
void update_layers_num(bool show, wxString num = wxEmptyString);
void show_priting_use_info(bool show, wxString time = wxEmptyString, wxString weight = wxEmptyString);
void show_profile_info(bool show, wxString profile = wxEmptyString);
void market_scoring_show();
void market_scoring_hide();
public:
ScalableButton* get_abort_button() {return m_button_abort;};
@ -129,6 +228,13 @@ public:
Button* get_market_scoring_button() {return m_button_market_scoring;};
Button* get_clean_button() {return m_button_clean;};
wxStaticBitmap* get_bitmap_thumbnail() {return m_bitmap_thumbnail;};
int get_star_count() { return m_star_count; }
void set_star_count(int star_count);
std::vector<ScalableButton *> &get_score_star() { return m_score_star; }
bool get_star_count_dirty() { return m_star_count_dirty; }
void set_star_count_dirty(bool dirty) { m_star_count_dirty = dirty; }
void set_has_reted_text(bool has_rated);
};
class StatusBasePanel : public wxScrolledWindow
@ -210,7 +316,6 @@ protected:
ScalableButton *m_button_pause_resume;
ScalableButton *m_button_abort;
Button * m_button_clean;
Button * m_button_market_scoring;
wxStaticText * m_text_tasklist_caption;
@ -222,19 +327,22 @@ protected:
/* TempInput */
wxBoxSizer * m_misc_ctrl_sizer;
StaticBox* m_fan_panel;
TempInput * m_tempCtrl_nozzle;
int m_temp_nozzle_timeout {0};
StaticLine * m_line_nozzle;
TempInput* m_tempCtrl_nozzle;
int m_temp_nozzle_timeout{ 0 };
TempInput * m_tempCtrl_bed;
int m_temp_bed_timeout {0};
TempInput * m_tempCtrl_frame;
TempInput * m_tempCtrl_chamber;
int m_temp_chamber_timeout {0};
bool m_current_support_cham_fan{true};
bool m_current_support_aux_fan{true};
FanSwitchButton *m_switch_nozzle_fan;
int m_switch_nozzle_fan_timeout{0};
FanSwitchButton *m_switch_printing_fan;
int m_switch_printing_fan_timeout{0};
FanSwitchButton *m_switch_cham_fan;
int m_switch_cham_fan_timeout{0};
wxPanel* m_switch_block_fan;
float m_fixed_aspect_ratio{1.8};
@ -320,7 +428,7 @@ public:
wxBoxSizer *create_ams_group(wxWindow *parent);
wxBoxSizer *create_settings_group(wxWindow *parent);
void show_ams_group(bool show = true, bool support_virtual_tray = true, bool support_extrustion_cali = true);
void show_ams_group(bool show = true);
};
@ -359,10 +467,14 @@ protected:
int m_last_vcamera = -1;
bool m_is_load_with_temp = false;
bool m_print_finish = false;
json m_rating_result;
json m_last_result;
wxWebRequest web_request;
bool bed_temp_input = false;
bool nozzle_temp_input = false;
bool cham_temp_input = false;
bool request_model_info_flag = false;
int speed_lvl = 1; // 0 - 3
int speed_lvl_timeout {0};
boost::posix_time::ptime speed_dismiss_time;
@ -372,6 +484,8 @@ protected:
std::map<std::string, std::string> m_print_connect_types;
std::vector<Button *> m_buttons;
int last_status;
ScoreData *m_score_data;
void init_scaled_buttons();
void create_tasklist_info();
void show_task_list_info(bool show = true);
@ -384,7 +498,6 @@ protected:
void show_error_message(MachineObject* obj, wxString msg, std::string print_error_str = "");
void error_info_reset();
void show_recenter_dialog();
void market_model_scoring_page(int design_id);
/* axis control */
bool check_axis_z_at_home(MachineObject* obj);
@ -405,9 +518,11 @@ protected:
void on_nozzle_temp_kill_focus(wxFocusEvent &event);
void on_nozzle_temp_set_focus(wxFocusEvent &event);
void on_set_nozzle_temp();
void on_set_chamber_temp();
/* extruder apis */
void on_ams_load(SimpleEvent &event);
void update_filament_step();
void on_ams_load_curr();
void on_ams_unload(SimpleEvent &event);
void on_ams_filament_backup(SimpleEvent& event);
@ -422,6 +537,8 @@ protected:
void on_print_error_func(wxCommandEvent& event);
void on_fan_changed(wxCommandEvent& event);
void on_cham_temp_kill_focus(wxFocusEvent& event);
void on_cham_temp_set_focus(wxFocusEvent& event);
void on_switch_speed(wxCommandEvent& event);
void on_lamp_switch(wxCommandEvent &event);
void on_printing_fan_switch(wxCommandEvent &event);
@ -455,13 +572,16 @@ protected:
void update_misc_ctrl(MachineObject *obj);
void update_ams(MachineObject* obj);
void update_extruder_status(MachineObject* obj);
void update_ams_control_state(bool is_support_virtual_tray, bool is_curr_tray_selected);
void update_ams_control_state(bool is_curr_tray_selected);
void update_cali(MachineObject* obj);
void reset_printing_values();
void on_webrequest_state(wxWebRequestEvent &evt);
bool is_task_changed(MachineObject* obj);
/* model mall score */
bool model_score_is_update();
/* camera */
void update_camera_state(MachineObject* obj);
bool show_vcamera = false;

View file

@ -44,6 +44,7 @@
#include "Widgets/TabCtrl.hpp"
#include "MarkdownTip.hpp"
#include "Search.hpp"
#include "BedShapeDialog.hpp"
#include "BedShapeDialog.hpp"
// #include "BonjourDialog.hpp"
@ -2718,8 +2719,6 @@ void TabFilament::build()
line.append_option(optgroup->get_option("nozzle_temperature_range_high"));
optgroup->append_line(line);
optgroup = page->new_optgroup(L("Recommended temperature range"), L"param_temperature");
optgroup->append_single_option_line("bed_temperature_difference");
optgroup = page->new_optgroup(L("Print temperature"), L"param_temperature");
optgroup->append_single_option_line("chamber_temperature");
@ -2741,7 +2740,7 @@ void TabFilament::build()
line.append_option(optgroup->get_option("eng_plate_temp"));
optgroup->append_line(line);
line = { L("High Temp Plate"), L("Bed temperature when high temperature plate is installed. Value 0 means the filament does not support to print on the High Temp Plate") };
line = {L("Smooth PEI Plate / High Temp Plate"), L("Bed temperature when Smooth PEI Plate/High temperature plate is installed. Value 0 means the filament does not support to print on the Smooth PEI Plate/High Temp Plate") };
line.append_option(optgroup->get_option("hot_plate_temp_initial_layer"));
line.append_option(optgroup->get_option("hot_plate_temp"));
optgroup->append_line(line);
@ -2774,6 +2773,9 @@ void TabFilament::build()
else if (opt_key == "nozzle_temperature_initial_layer") {
m_config_manipulation.check_nozzle_temperature_initial_layer_range(&filament_config);
}
else if (opt_key == "chamber_temperatures") {
m_config_manipulation.check_chamber_temperature(&filament_config);
}
on_value_change(opt_key, value);
};
@ -2824,6 +2826,18 @@ void TabFilament::build()
optgroup = page->new_optgroup(L("Auxiliary part cooling fan"), L"param_cooling_fan");
optgroup->append_single_option_line("additional_cooling_fan_speed");
optgroup = page->new_optgroup(L("Exhaust fan"),L"param_cooling_fan");
optgroup->append_single_option_line("activate_air_filtration");
line = {L("During print"), L("")};
line.append_option(optgroup->get_option("during_print_exhaust_fan_speed"));
optgroup->append_line(line);
line = {L("Complete print"), L("")};
line.append_option(optgroup->get_option("complete_print_exhaust_fan_speed"));
optgroup->append_line(line);
//BBS
add_filament_overrides_page();
const int gcode_field_height = 15; // 150
@ -2985,7 +2999,8 @@ void TabFilament::toggle_options()
toggle_line("cool_plate_temp_initial_layer", is_BBL_printer);
toggle_line("eng_plate_temp_initial_layer", is_BBL_printer);
toggle_line("textured_plate_temp_initial_layer", is_BBL_printer);
toggle_option("chamber_temperature", !is_BBL_printer);
// bool support_chamber_temp_control = this->m_preset_bundle->printers.get_selected_preset().config.opt_bool("support_chamber_temp_control");
// toggle_option("chamber_temperature", !is_BBL_printer || support_chamber_temp_control);
}
if (m_active_page->title() == L("Setting Overrides"))
update_filament_overrides_page();
@ -3098,6 +3113,7 @@ void TabPrinter::build_fff()
// optgroup->append_single_option_line("printable_area");
optgroup->append_single_option_line("printable_height");
optgroup->append_single_option_line("nozzle_volume");
optgroup->append_single_option_line("best_object_pos");
#if 0
//optgroup->append_single_option_line("z_offset");
@ -3116,6 +3132,7 @@ void TabPrinter::build_fff()
// optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
optgroup->append_single_option_line("printer_structure");
optgroup->append_single_option_line("gcode_flavor");
option = optgroup->get_option("thumbnails");
option.opt.full_width = true;
@ -3139,11 +3156,13 @@ void TabPrinter::build_fff()
optgroup->append_single_option_line("extruder_clearance_radius");
optgroup->append_single_option_line("extruder_clearance_height_to_rod");
optgroup->append_single_option_line("extruder_clearance_height_to_lid");
optgroup = page->new_optgroup(L("Accessory") /*, L"param_accessory"*/);
optgroup->append_single_option_line("nozzle_type");
optgroup->append_single_option_line("nozzle_hrc");
optgroup->append_single_option_line("auxiliary_fan");
optgroup->append_single_option_line("support_chamber_temp_control");
optgroup->append_single_option_line("support_air_filtration");
const int gcode_field_height = 15; // 150
const int notes_field_height = 25; // 250
@ -3187,6 +3206,16 @@ void TabPrinter::build_fff()
option.opt.is_code = true;
option.opt.height = gcode_field_height;//150;
optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(L("Time lapse G-code"), L"param_gcode", 0);
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup, opt_key, value);
};
option = optgroup->get_option("time_lapse_gcode");
option.opt.full_width = true;
option.opt.is_code = true;
option.opt.height = gcode_field_height;//150;
optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(L("Change filament G-code"), L"param_gcode", 0);
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
@ -3528,6 +3557,8 @@ void TabPrinter::build_unregular_pages(bool from_initial_build/* = false*/)
optgroup->append_single_option_line("retraction_length", "", extruder_idx);
optgroup->append_single_option_line("retract_restart_extra", "", extruder_idx);
optgroup->append_single_option_line("z_hop", "", extruder_idx);
optgroup->append_single_option_line("retract_lift_above", "", extruder_idx);
optgroup->append_single_option_line("retract_lift_below", "", extruder_idx);
optgroup->append_single_option_line("z_hop_types", "", extruder_idx);
optgroup->append_single_option_line("retraction_speed", "", extruder_idx);
optgroup->append_single_option_line("deretraction_speed", "", extruder_idx);

View file

@ -1349,6 +1349,10 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
opt_key == "sparse_infill_pattern",
opt_idx);
}
case coPoint: {
Vec2d val = config.opt<ConfigOptionPoint>(opt_key)->value;
return from_u8((boost::format("[%1%]") % ConfigOptionPoint(val).serialize()).str());
}
case coPoints: {
//BBS: add bed_exclude_area
if (opt_key == "printable_area" || opt_key == "thumbnails") {
@ -1359,7 +1363,9 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
else if (opt_key == "bed_exclude_area") {
return get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
}
else if (opt_key == "thumbnail_size") {
return get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
}
Vec2d val = config.opt<ConfigOptionPoints>(opt_key)->get_at(opt_idx);
return from_u8((boost::format("[%1%]") % ConfigOptionPoint(val).serialize()).str());
}

View file

@ -29,6 +29,8 @@ MachineInfoPanel::MachineInfoPanel(wxWindow* parent, wxWindowID id, const wxPoin
wxBoxSizer *m_main_left_sizer = new wxBoxSizer(wxVERTICAL);
// ota
wxBoxSizer *m_ota_sizer = new wxBoxSizer(wxHORIZONTAL);
m_printer_img = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(200), FromDIP(200)));
@ -95,11 +97,10 @@ MachineInfoPanel::MachineInfoPanel(wxWindow* parent, wxWindowID id, const wxPoin
m_staticline->Show(false);
m_main_left_sizer->Add(m_staticline, 0, wxEXPAND | wxLEFT, FromDIP(40));
// ams
m_ams_sizer = new wxBoxSizer(wxHORIZONTAL);
m_ams_img = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(200), FromDIP(200)));
m_ams_img->SetBitmap(m_img_monitor_ams.bmp());
m_ams_sizer->Add(m_ams_img, 0, wxALIGN_TOP | wxALL, FromDIP(5));
@ -135,12 +136,31 @@ MachineInfoPanel::MachineInfoPanel(wxWindow* parent, wxWindowID id, const wxPoin
//Hide ams
show_ams(false, true);
//
m_extra_ams_sizer = new wxBoxSizer(wxHORIZONTAL);
m_extra_ams_img = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(200), FromDIP(200)));
m_extra_ams_img->SetBitmap(m_img_extra_ams.bmp());
m_extra_ams_sizer->Add(m_extra_ams_img, 0, wxALIGN_TOP | wxALL, FromDIP(5));
wxBoxSizer* extra_ams_content_sizer = new wxBoxSizer(wxVERTICAL);
extra_ams_content_sizer->Add(0, 40, 0, wxEXPAND, FromDIP(5));
m_extra_ams_panel = new ExtraAmsPanel(this);
m_extra_ams_panel->m_staticText_ams->SetLabel("AMS Lite");
extra_ams_content_sizer->Add(m_extra_ams_panel, 0, wxEXPAND, 0);
m_extra_ams_sizer->Add(extra_ams_content_sizer, 1, wxEXPAND, 0);
m_main_left_sizer->Add(m_extra_ams_sizer, 0, wxEXPAND, 0);
show_extra_ams(false, true);
m_staticline2 = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL);
m_staticline2->SetBackgroundColour(wxColour(206, 206, 206));
//m_staticline2->Show(false);
m_main_left_sizer->Add(m_staticline2, 0, wxEXPAND | wxLEFT, FromDIP(40));
// ext
m_ext_sizer = new wxBoxSizer(wxHORIZONTAL);
m_ext_img = new wxStaticBitmap(this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(FromDIP(200), FromDIP(200)));
@ -158,6 +178,7 @@ MachineInfoPanel::MachineInfoPanel(wxWindow* parent, wxWindowID id, const wxPoin
m_main_left_sizer->Add(m_ext_sizer, 0, wxEXPAND, 0);
m_main_sizer->Add(m_main_left_sizer, 1, wxEXPAND, 0);
wxBoxSizer *m_main_right_sizer = new wxBoxSizer(wxVERTICAL);
@ -288,6 +309,7 @@ void MachineInfoPanel::init_bitmaps()
m_img_printer = ScalableBitmap(this, "printer_thumbnail", 160);
m_img_monitor_ams = ScalableBitmap(this, "monitor_upgrade_ams", 200);
m_img_ext = ScalableBitmap(this, "monitor_upgrade_ext", 200);
m_img_extra_ams = ScalableBitmap(this, "monitor_upgrade_f1", 160);
upgrade_green_icon = ScalableBitmap(this, "monitor_upgrade_online", 5);
upgrade_gray_icon = ScalableBitmap(this, "monitor_upgrade_offline", 5);
upgrade_yellow_icon = ScalableBitmap(this, "monitor_upgrade_busy", 5);
@ -451,7 +473,7 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj)
bool has_hub_model = false;
//hub
if (!obj->online_ahb || obj->module_vers.find("ahb") == obj->module_vers.end())
if (!obj->online_ahb || obj->module_vers.find("ahb") == obj->module_vers.end())
m_ahb_panel->Hide();
else {
has_hub_model = true;
@ -531,105 +553,143 @@ void MachineInfoPanel::update_ams_ext(MachineObject *obj)
//ams
if (obj->ams_exist_bits != 0) {
show_ams(true);
std::map<int, MachineObject::ModuleVersionInfo> ver_list = obj->get_ams_version();
std::string extra_ams_str = (boost::format("ams_f1/%1%") % 0).str();
auto extra_ams_it = obj->module_vers.find(extra_ams_str);
if (extra_ams_it != obj->module_vers.end()) {
wxString sn_text = extra_ams_it->second.sn;
sn_text = sn_text.MakeUpper();
AmsPanelHash::iterator iter = m_amspanel_list.begin();
wxString ver_text = extra_ams_it->second.sw_ver;
for (auto i = 0; i < m_amspanel_list.GetCount(); i++) {
AmsPanel *amspanel = m_amspanel_list[i];
amspanel->Hide();
bool has_new_version = false;
auto new_extra_ams_ver = obj->new_ver_list.find(extra_ams_str);
if (new_extra_ams_ver != obj->new_ver_list.end())
has_new_version = true;
extra_ams_it->second.sw_new_ver;
if (has_new_version) {
m_extra_ams_panel->m_ams_new_version_img->Show();
ver_text = wxString::Format("%s->%s", new_extra_ams_ver->second.sw_ver, new_extra_ams_ver->second.sw_new_ver);
}
else {
m_extra_ams_panel->m_ams_new_version_img->Hide();
ver_text = wxString::Format("%s(%s)", extra_ams_it->second.sw_ver, _L("Latest version"));
}
m_extra_ams_panel->m_staticText_ams_sn_val->SetLabelText(sn_text);
m_extra_ams_panel->m_staticText_ams_ver_val->SetLabelText(ver_text);
show_ams(false);
show_extra_ams(true);
}
else {
show_extra_ams(false);
show_ams(true);
std::map<int, MachineObject::ModuleVersionInfo> ver_list = obj->get_ams_version();
AmsPanelHash::iterator iter = m_amspanel_list.begin();
for (auto i = 0; i < m_amspanel_list.GetCount(); i++) {
AmsPanel* amspanel = m_amspanel_list[i];
amspanel->Hide();
}
auto ams_index = 0;
for (std::map<std::string, Ams *>::iterator iter = obj->amsList.begin(); iter != obj->amsList.end(); iter++) {
wxString ams_name;
wxString ams_sn;
wxString ams_ver;
auto ams_index = 0;
for (std::map<std::string, Ams*>::iterator iter = obj->amsList.begin(); iter != obj->amsList.end(); iter++) {
wxString ams_name;
wxString ams_sn;
wxString ams_ver;
AmsPanel *amspanel = m_amspanel_list[ams_index];
amspanel->Show();
AmsPanel* amspanel = m_amspanel_list[ams_index];
amspanel->Show();
auto it = ver_list.find(atoi(iter->first.c_str()));
auto ams_id = std::stoi(iter->second->id);
auto it = ver_list.find(atoi(iter->first.c_str()));
auto ams_id = std::stoi(iter->second->id);
wxString ams_text = wxString::Format("AMS%s", std::to_string(ams_id + 1));
ams_name = ams_text;
wxString ams_text = wxString::Format("AMS%s", std::to_string(ams_id + 1));
ams_name = ams_text;
if (it == ver_list.end()) {
// hide this ams
ams_sn = "-";
ams_ver = "-";
} else {
// update ams img
if (m_obj->upgrade_display_state == (int)MachineObject::UpgradingDisplayState::UpgradingInProgress) {
if (it == ver_list.end()) {
// hide this ams
ams_sn = "-";
ams_ver = "-";
amspanel->m_ams_new_version_img->Hide();
}
else {
if (obj->new_ver_list.empty() && !obj->m_new_ver_list_exist) {
if (obj->upgrade_new_version
&& obj->ams_new_version_number.compare(it->second.sw_ver) != 0) {
amspanel->m_ams_new_version_img->Show();
// update ams img
if (m_obj->upgrade_display_state == (int)MachineObject::UpgradingDisplayState::UpgradingInProgress) {
ams_ver = "-";
amspanel->m_ams_new_version_img->Hide();
}
else {
if (obj->new_ver_list.empty() && !obj->m_new_ver_list_exist) {
if (obj->upgrade_new_version
&& obj->ams_new_version_number.compare(it->second.sw_ver) != 0) {
amspanel->m_ams_new_version_img->Show();
if (obj->ams_new_version_number.empty()) {
ams_ver = wxString::Format("%s", it->second.sw_ver);
} else {
ams_ver = wxString::Format("%s->%s", it->second.sw_ver, obj->ams_new_version_number);
if (obj->ams_new_version_number.empty()) {
ams_ver = wxString::Format("%s", it->second.sw_ver);
}
else {
ams_ver = wxString::Format("%s->%s", it->second.sw_ver, obj->ams_new_version_number);
}
}
} else {
amspanel->m_ams_new_version_img->Hide();
if (obj->ams_new_version_number.empty()) {
wxString ver_text = wxString::Format("%s", it->second.sw_ver);
ams_ver = ver_text;
} else {
wxString ver_text = wxString::Format("%s(%s)", it->second.sw_ver, _L("Latest version"));
ams_ver = ver_text;
else {
amspanel->m_ams_new_version_img->Hide();
if (obj->ams_new_version_number.empty()) {
wxString ver_text = wxString::Format("%s", it->second.sw_ver);
ams_ver = ver_text;
}
else {
wxString ver_text = wxString::Format("%s(%s)", it->second.sw_ver, _L("Latest version"));
ams_ver = ver_text;
}
}
}
} else {
std::string ams_idx = (boost::format("ams/%1%") % ams_id).str();
auto ver_item = obj->new_ver_list.find(ams_idx);
else {
std::string ams_idx = (boost::format("ams/%1%") % ams_id).str();
auto ver_item = obj->new_ver_list.find(ams_idx);
if (ver_item == obj->new_ver_list.end()) {
amspanel->m_ams_new_version_img->Hide();
wxString ver_text = wxString::Format("%s(%s)", it->second.sw_ver, _L("Latest version"));
ams_ver = ver_text;
} else {
if (ver_item->second.sw_new_ver != ver_item->second.sw_ver) {
amspanel->m_ams_new_version_img->Show();
wxString ver_text = wxString::Format("%s->%s", ver_item->second.sw_ver, ver_item->second.sw_new_ver);
ams_ver = ver_text;
} else {
if (ver_item == obj->new_ver_list.end()) {
amspanel->m_ams_new_version_img->Hide();
wxString ver_text = wxString::Format("%s(%s)", ver_item->second.sw_ver, _L("Latest version"));
ams_ver = ver_text;
wxString ver_text = wxString::Format("%s(%s)", it->second.sw_ver, _L("Latest version"));
ams_ver = ver_text;
}
else {
if (ver_item->second.sw_new_ver != ver_item->second.sw_ver) {
amspanel->m_ams_new_version_img->Show();
wxString ver_text = wxString::Format("%s->%s", ver_item->second.sw_ver, ver_item->second.sw_new_ver);
ams_ver = ver_text;
}
else {
amspanel->m_ams_new_version_img->Hide();
wxString ver_text = wxString::Format("%s(%s)", ver_item->second.sw_ver, _L("Latest version"));
ams_ver = ver_text;
}
}
}
}
// update ams sn
if (it->second.sn.empty()) {
ams_sn = "-";
}
else {
wxString sn_text = it->second.sn;
ams_sn = sn_text.MakeUpper();
}
}
// update ams sn
if (it->second.sn.empty()) {
ams_sn = "-";
} else {
wxString sn_text = it->second.sn;
ams_sn = sn_text.MakeUpper();
}
amspanel->m_staticText_ams->SetLabelText(ams_name);
amspanel->m_staticText_ams_sn_val->SetLabelText(ams_sn);
amspanel->m_staticText_ams_ver_val->SetLabelText(ams_ver);
ams_index++;
}
amspanel->m_staticText_ams->SetLabelText(ams_name);
amspanel->m_staticText_ams_sn_val->SetLabelText(ams_sn);
amspanel->m_staticText_ams_ver_val->SetLabelText(ams_ver);
ams_index++;
}
} else {
if (!has_hub_model) { show_ams(false); }
show_extra_ams(false);
}
//ext
auto ext_module = obj->module_vers.find("ext");
if (ext_module == obj->module_vers.end())
@ -749,6 +809,16 @@ void MachineInfoPanel::show_ext(bool show, bool force_update)
m_last_ext_show = show;
}
void MachineInfoPanel::show_extra_ams(bool show, bool force_update) {
if (m_last_extra_ams_show != show || force_update) {
m_extra_ams_img->Show(show);
m_extra_ams_sizer->Show(show);
m_staticline->Show(show);
BOOST_LOG_TRIVIAL(trace) << "upgrade: show_extra_ams = " << show;
}
m_last_extra_ams_show = show;
}
void MachineInfoPanel::on_sys_color_changed()
{
if (m_obj) {
@ -1154,5 +1224,16 @@ bool UpgradePanel::Show(bool show)
m_ext_new_version_img->SetBitmap(upgrade_green_icon.bmp());
}
ExtraAmsPanel::ExtraAmsPanel(wxWindow* parent,
wxWindowID id /*= wxID_ANY*/,
const wxPoint& pos /*= wxDefaultPosition*/,
const wxSize& size /*= wxDefaultSize*/,
long style /*= wxTAB_TRAVERSAL*/,
const wxString& name /*= wxEmptyString*/)
: AmsPanel(parent, id, pos, size, style)
{
}
}
}

View file

@ -52,6 +52,16 @@ public:
void msw_rescale();
};
class ExtraAmsPanel : public AmsPanel
{
public:
ExtraAmsPanel(wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL,
const wxString& name = wxEmptyString);
};
WX_DEFINE_ARRAY(AmsPanel*, AmsPanelHash);
@ -74,6 +84,8 @@ protected:
wxStaticBitmap *m_ams_img;
AmsPanel* m_ahb_panel;
wxStaticLine* m_staticline2;
ExtraAmsPanel* m_extra_ams_panel;
wxStaticBitmap* m_extra_ams_img;
wxStaticBitmap* m_ext_img;
ExtensionPanel* m_ext_panel;
@ -87,6 +99,10 @@ protected:
bool m_last_ext_show = true;
wxBoxSizer* m_ext_sizer;
/* extra_ams info */
bool m_last_extra_ams_show = true;
wxBoxSizer* m_extra_ams_sizer;
/* upgrade widgets */
wxBoxSizer* m_upgrading_sizer;
wxStaticText * m_staticText_upgrading_info;
@ -97,10 +113,12 @@ protected:
Button * m_button_upgrade_firmware;
wxPanel* create_caption_panel(wxWindow *parent);
AmsPanelHash m_amspanel_list;
AmsPanelHash m_amspanel_list;
std::vector<ExtraAmsPanel*> m_extra_ams_panel_list;
ScalableBitmap m_img_ext;
ScalableBitmap m_img_monitor_ams;
ScalableBitmap m_img_extra_ams;
ScalableBitmap m_img_printer;
ScalableBitmap upgrade_gray_icon;
ScalableBitmap upgrade_green_icon;
@ -134,6 +152,7 @@ public:
void show_status(int status, std::string upgrade_status_str = "");
void show_ams(bool show = false, bool force_update = false);
void show_ext(bool show = false, bool force_update = false);
void show_extra_ams(bool show = false, bool force_update = false);
void on_upgrade_firmware(wxCommandEvent &event);
void on_consisitency_upgrade_firmware(wxCommandEvent &event);
@ -152,12 +171,12 @@ public:
}panel_type;
};
enum UpgradeMode {
umPushUpgrading,
umSelectOtaVerUpgrading,
umSelectAmsVerUpgrading,
};
static UpgradeMode upgrade_mode;
//enum UpgradeMode {
// umPushUpgrading,
// umSelectOtaVerUpgrading,
// umSelectAmsVerUpgrading,
//};
//static UpgradeMode upgrade_mode;
class UpgradePanel : public wxPanel
{

Some files were not shown because too many files have changed in this diff Show more