ENH: Add extruder_printable_height

to support different printable height of multi_extruder
jira:none

Change-Id: I265c65e15fc8f598c3456556557bb6977b5de820
This commit is contained in:
zhimin.zeng 2024-11-16 19:48:31 +08:00 committed by lane.wei
parent 482af1849b
commit 933adbaaf0
13 changed files with 162 additions and 39 deletions

View File

@ -1338,7 +1338,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu
Polygons ploys = diff(printable_poly, Polygon::new_scale(e_printable_area)); Polygons ploys = diff(printable_poly, Polygon::new_scale(e_printable_area));
extruder_unprintable_polys.emplace_back(ploys); extruder_unprintable_polys.emplace_back(ploys);
} }
m_processor.check_multi_extruder_gcode_valid(extruder_unprintable_polys, m_print->get_filament_maps());
m_processor.check_multi_extruder_gcode_valid(extruder_unprintable_polys, m_print->get_extruder_printable_height(), m_print->get_filament_maps());
} }
m_processor.finalize(true); m_processor.finalize(true);

View File

@ -152,6 +152,18 @@ static int get_object_label_id(const std::string_view comment_1)
return id; return id;
} }
static float get_z_height(const std::string_view comment_1)
{
std::string comment(comment_1);
auto pos = comment.find(":");
std::string num_str = comment.substr(pos + 1);
float print_z = 0.0f;
try {
print_z = stof(num_str);
} catch (const std::exception &) {}
return print_z;
}
void GCodeProcessor::CachedPosition::reset() void GCodeProcessor::CachedPosition::reset()
{ {
std::fill(position.begin(), position.end(), FLT_MAX); std::fill(position.begin(), position.end(), FLT_MAX);
@ -1358,7 +1370,7 @@ GCodeProcessor::GCodeProcessor()
m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_stop_mask = "M73 D%s\n"; m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_stop_mask = "M73 D%s\n";
} }
bool GCodeProcessor::check_multi_extruder_gcode_valid(const std::vector<Polygons> &unprintable_areas, const std::vector<int> &filament_map) bool GCodeProcessor::check_multi_extruder_gcode_valid(const std::vector<Polygons> &unprintable_areas, const std::vector<double>& printable_heights, const std::vector<int> &filament_map)
{ {
m_result.limit_filament_maps.clear(); m_result.limit_filament_maps.clear();
m_result.gcode_check_result.reset(); m_result.gcode_check_result.reset();
@ -1370,18 +1382,23 @@ bool GCodeProcessor::check_multi_extruder_gcode_valid(const std::vector<Polygons
return ps; return ps;
}; };
struct GCodePosInfo
std::map<int, std::map<int, Points>> gcode_path_pos; // object_id, filament_id, pos {
Points pos;
float max_print_z;
};
std::map<int, std::map<int, GCodePosInfo>> gcode_path_pos; // object_id, filament_id, pos
for (const GCodeProcessorResult::MoveVertex &move : m_result.moves) { for (const GCodeProcessorResult::MoveVertex &move : m_result.moves) {
if (move.type == EMoveType::Extrude/* || move.type == EMoveType::Travel*/) { if (move.type == EMoveType::Extrude/* || move.type == EMoveType::Travel*/) {
if (move.is_arc_move_with_interpolation_points()) { if (move.is_arc_move_with_interpolation_points()) {
for (int i = 0; i < move.interpolation_points.size(); i++) { for (int i = 0; i < move.interpolation_points.size(); i++) {
gcode_path_pos[move.object_label_id][int(move.extruder_id)].emplace_back(to_2d(move.interpolation_points[i].cast<double>())); gcode_path_pos[move.object_label_id][int(move.extruder_id)].pos.emplace_back(to_2d(move.interpolation_points[i].cast<double>()));
} }
} }
else { else {
gcode_path_pos[move.object_label_id][int(move.extruder_id)].emplace_back(to_2d(move.position.cast<double>())); gcode_path_pos[move.object_label_id][int(move.extruder_id)].pos.emplace_back(to_2d(move.position.cast<double>()));
} }
gcode_path_pos[move.object_label_id][int(move.extruder_id)].max_print_z = std::max(gcode_path_pos[move.object_label_id][int(move.extruder_id)].max_print_z, move.print_z);
} }
} }
@ -1389,12 +1406,13 @@ bool GCodeProcessor::check_multi_extruder_gcode_valid(const std::vector<Polygons
Point plate_offset = Point(scale_(m_x_offset), scale_(m_y_offset)); Point plate_offset = Point(scale_(m_x_offset), scale_(m_y_offset));
for (auto obj_iter = gcode_path_pos.begin(); obj_iter != gcode_path_pos.end(); ++obj_iter) { for (auto obj_iter = gcode_path_pos.begin(); obj_iter != gcode_path_pos.end(); ++obj_iter) {
int object_label_id = obj_iter->first; int object_label_id = obj_iter->first;
const std::map<int, Points>& path_pos = obj_iter->second; const std::map<int, GCodePosInfo> &path_pos = obj_iter->second;
for (auto iter = path_pos.begin(); iter != path_pos.end(); ++iter) { for (auto iter = path_pos.begin(); iter != path_pos.end(); ++iter) {
int extruder_id = filament_map[iter->first] - 1; int extruder_id = filament_map[iter->first] - 1;
Polygon path_poly(iter->second); Polygon path_poly(iter->second.pos);
BoundingBox bbox = path_poly.bounding_box(); BoundingBox bbox = path_poly.bounding_box();
// check printable area
// Simplified use bounding_box, Accurate calculation is not efficient // Simplified use bounding_box, Accurate calculation is not efficient
for (Polygon poly : unprintable_areas[extruder_id]) { for (Polygon poly : unprintable_areas[extruder_id]) {
poly.translate(plate_offset); poly.translate(plate_offset);
@ -1403,11 +1421,22 @@ bool GCodeProcessor::check_multi_extruder_gcode_valid(const std::vector<Polygons
std::pair<int, int> filament_to_object_id; std::pair<int, int> filament_to_object_id;
filament_to_object_id.first = iter->first; filament_to_object_id.first = iter->first;
filament_to_object_id.second = object_label_id; filament_to_object_id.second = object_label_id;
m_result.gcode_check_result.error_infos[extruder_id].push_back(filament_to_object_id); m_result.gcode_check_result.print_area_error_infos[extruder_id].push_back(filament_to_object_id);
valid = false; valid = false;
} }
} }
// check printable height
if (iter->second.max_print_z > printable_heights[extruder_id]) {
m_result.gcode_check_result.error_code |= (1 << 1);
std::pair<int, int> filament_to_object_id;
filament_to_object_id.first = iter->first;
filament_to_object_id.second = object_label_id;
m_result.gcode_check_result.print_height_error_infos[extruder_id].push_back(filament_to_object_id);
m_result.limit_filament_maps[iter->first] |= (1 << extruder_id);
valid = false;
}
for (int i = 0; i < unprintable_areas.size(); ++i) { for (int i = 0; i < unprintable_areas.size(); ++i) {
for (Polygon poly : unprintable_areas[i]) { for (Polygon poly : unprintable_areas[i]) {
poly.translate(plate_offset); poly.translate(plate_offset);
@ -2714,6 +2743,12 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
return; return;
} }
// ; Z_HEIGHT:
if (boost::starts_with(comment, " Z_HEIGHT:")) {
m_print_z = get_z_height(comment);
return;
}
// wipe start tag // wipe start tag
if (boost::starts_with(comment, reserved_tag(ETags::Wipe_Start))) { if (boost::starts_with(comment, reserved_tag(ETags::Wipe_Start))) {
m_wiping = true; m_wiping = true;
@ -5226,7 +5261,8 @@ void GCodeProcessor::store_move_vertex(EMoveType type, EMovePathType path_type)
Vec3f(m_end_position[X] + m_x_offset, m_end_position[Y] + m_y_offset, m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z]) + m_extruder_offsets[filament_id], Vec3f(m_end_position[X] + m_x_offset, m_end_position[Y] + m_y_offset, m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z]) + m_extruder_offsets[filament_id],
Vec3f(m_arc_center(0, 0) + m_x_offset, m_arc_center(1, 0) + m_y_offset, m_arc_center(2, 0)) + m_extruder_offsets[filament_id], Vec3f(m_arc_center(0, 0) + m_x_offset, m_arc_center(1, 0) + m_y_offset, m_arc_center(2, 0)) + m_extruder_offsets[filament_id],
m_interpolation_points, m_interpolation_points,
m_object_label_id m_object_label_id,
m_print_z
}); });
if (type == EMoveType::Seam) { if (type == EMoveType::Seam) {

View File

@ -121,6 +121,18 @@ namespace Slic3r {
using ConflictResultOpt = std::optional<ConflictResult>; using ConflictResultOpt = std::optional<ConflictResult>;
struct GCodeCheckResult
{
int error_code = 0; // 0 means succeed, 0001 printable area error, 0010 printable height error
std::map<int, std::vector<std::pair<int, int>>> print_area_error_infos; // printable_area extruder_id to <filament_id - object_label_id> which cannot printed in this extruder
std::map<int, std::vector<std::pair<int, int>>> print_height_error_infos; // printable_height extruder_id to <filament_id - object_label_id> which cannot printed in this extruder
void reset() {
error_code = 0;
print_area_error_infos.clear();
print_height_error_infos.clear();
}
};
struct FilamentPrintableResult struct FilamentPrintableResult
{ {
std::vector<int> conflict_filament; std::vector<int> conflict_filament;
@ -132,18 +144,6 @@ namespace Slic3r {
}; };
}; };
using ConflictResultOpt = std::optional<ConflictResult>;
struct GCodeCheckResult
{
int error_code = 0; // 0 means succeed
std::map<int, std::vector<std::pair<int, int>>> error_infos; // extruder_id to <filament_id - object_label_id> which cannot printed in this extruder
void reset() {
error_code = 0;
error_infos.clear();
}
};
struct GCodeProcessorResult struct GCodeProcessorResult
{ {
struct FilamentSequenceHash struct FilamentSequenceHash
@ -197,6 +197,7 @@ namespace Slic3r {
Vec3f arc_center_position{ Vec3f::Zero() }; // mm Vec3f arc_center_position{ Vec3f::Zero() }; // mm
std::vector<Vec3f> interpolation_points; // interpolation points of arc for drawing std::vector<Vec3f> interpolation_points; // interpolation points of arc for drawing
int object_label_id{-1}; int object_label_id{-1};
float print_z{0.0f};
float volumetric_rate() const { return feedrate * mm3_per_mm; } float volumetric_rate() const { return feedrate * mm3_per_mm; }
//BBS: new function to support arc move //BBS: new function to support arc move
@ -763,6 +764,7 @@ namespace Slic3r {
bool m_virtual_flushing; // mark a section with virtual flush, only for statistics bool m_virtual_flushing; // mark a section with virtual flush, only for statistics
bool m_wipe_tower; bool m_wipe_tower;
int m_object_label_id{-1}; int m_object_label_id{-1};
float m_print_z{0.0f};
std::vector<float> m_remaining_volume; std::vector<float> m_remaining_volume;
std::vector<Extruder> m_filament_lists; std::vector<Extruder> m_filament_lists;
std::vector<float> m_filament_nozzle_temp; std::vector<float> m_filament_nozzle_temp;
@ -845,7 +847,7 @@ namespace Slic3r {
GCodeProcessor(); GCodeProcessor();
// check whether the gcode path meets the filament_map grouping requirements // check whether the gcode path meets the filament_map grouping requirements
bool check_multi_extruder_gcode_valid(const std::vector<Polygons> &unprintable_areas, const std::vector<int>& filament_map); bool check_multi_extruder_gcode_valid(const std::vector<Polygons> &unprintable_areas, const std::vector<double>& printable_heights, const std::vector<int>& filament_map);
void apply_config(const PrintConfig& config); void apply_config(const PrintConfig& config);
void set_filaments(const std::vector<Extruder>&filament_lists) { m_filament_lists=filament_lists;} void set_filaments(const std::vector<Extruder>&filament_lists) { m_filament_lists=filament_lists;}

View File

@ -945,7 +945,7 @@ static std::vector<std::string> s_Preset_printer_options {
"printable_area", "extruder_printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor", "printable_area", "extruder_printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
"single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode","printing_by_object_gcode","before_layer_change_gcode", "layer_change_gcode", "time_lapse_gcode", "change_filament_gcode", "single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode","printing_by_object_gcode","before_layer_change_gcode", "layer_change_gcode", "time_lapse_gcode", "change_filament_gcode",
"printer_model", "printer_variant", "printer_extruder_id", "printer_extruder_variant", "extruder_variant_list", "default_nozzle_volume_type", "printer_model", "printer_variant", "printer_extruder_id", "printer_extruder_variant", "extruder_variant_list", "default_nozzle_volume_type",
"printable_height", "extruder_clearance_radius", "extruder_clearance_max_radius","extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "printable_height", "extruder_printable_height", "extruder_clearance_dist_to_rod", "extruder_clearance_max_radius","extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
"nozzle_height", "nozzle_height",
"default_print_profile", "inherits", "default_print_profile", "inherits",
"silent_mode", "silent_mode",

View File

@ -2399,6 +2399,11 @@ std::vector<std::vector<Vec2d>> Print::get_extruder_printable_area()
return m_config.extruder_printable_area.values; return m_config.extruder_printable_area.values;
} }
std::vector<double> Print::get_extruder_printable_height()
{
return m_config.extruder_printable_height.values;
}
size_t Print::get_extruder_id(unsigned int filament_id) const size_t Print::get_extruder_id(unsigned int filament_id) const
{ {
std::vector<int> filament_map = get_filament_maps(); std::vector<int> filament_map = get_filament_maps();

View File

@ -836,6 +836,7 @@ public:
std::vector<Vec2d> get_printable_area(); std::vector<Vec2d> get_printable_area();
std::vector<std::vector<Vec2d>> get_extruder_printable_area(); std::vector<std::vector<Vec2d>> get_extruder_printable_area();
std::vector<double> get_extruder_printable_height();
bool enable_timelapse_print() const; bool enable_timelapse_print() const;

View File

@ -542,6 +542,15 @@ void PrintConfigDef::init_common_params()
def->mode = comSimple; def->mode = comSimple;
def->set_default_value(new ConfigOptionFloat(100.0)); def->set_default_value(new ConfigOptionFloat(100.0));
def = this->add("extruder_printable_height", coFloats);
def->label = L("Printable height");
def->tooltip = L("Maximum printable height which is limited by mechanism of printer");
def->sidetext = L("mm");
def->min = 0;
def->max = 1000;
def->mode = comSimple;
def->set_default_value(new ConfigOptionFloatsNullable{100.0, 200.0});
// Options used by physical printers // Options used by physical printers
def = this->add("preset_names", coStrings); def = this->add("preset_names", coStrings);
@ -5278,6 +5287,7 @@ std::set<std::string> printer_extruder_options = {
"nozzle_diameter", "nozzle_diameter",
"default_nozzle_volume_type", "default_nozzle_volume_type",
"extruder_printable_area", "extruder_printable_area",
"extruder_printable_height",
"min_layer_height", "min_layer_height",
"max_layer_height" "max_layer_height"
}; };

View File

@ -1140,6 +1140,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloatsNullable, min_layer_height)) ((ConfigOptionFloatsNullable, min_layer_height))
((ConfigOptionString, printer_notes)) ((ConfigOptionString, printer_notes))
((ConfigOptionFloat, printable_height)) ((ConfigOptionFloat, printable_height))
((ConfigOptionFloatsNullable, extruder_printable_height))
((ConfigOptionPoint, best_object_pos)) ((ConfigOptionPoint, best_object_pos))
((ConfigOptionFloats, slow_down_min_speed)) ((ConfigOptionFloats, slow_down_min_speed))
((ConfigOptionFloatsNullable, nozzle_diameter)) ((ConfigOptionFloatsNullable, nozzle_diameter))

View File

@ -2959,6 +2959,7 @@ void GLCanvas3D::load_gcode_preview(const GCodeProcessorResult& gcode_result, co
_set_warning_notification_if_needed(EWarning::ToolpathOutside); _set_warning_notification_if_needed(EWarning::ToolpathOutside);
_set_warning_notification_if_needed(EWarning::GCodeConflict); _set_warning_notification_if_needed(EWarning::GCodeConflict);
_set_warning_notification_if_needed(EWarning::MultiExtruderPrintableError); _set_warning_notification_if_needed(EWarning::MultiExtruderPrintableError);
_set_warning_notification_if_needed(EWarning::MultiExtruderHeightOutside);
_set_warning_notification_if_needed(EWarning::FilamentUnPrintableOnFirstLayer); _set_warning_notification_if_needed(EWarning::FilamentUnPrintableOnFirstLayer);
} }
@ -9607,7 +9608,9 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning)
} else if (warning == EWarning::GCodeConflict) } else if (warning == EWarning::GCodeConflict)
show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.m_conflict_result.has_value(); show = m_gcode_viewer.has_data() && m_gcode_viewer.is_contained_in_bed() && m_gcode_viewer.m_conflict_result.has_value();
else if (warning == EWarning::MultiExtruderPrintableError) else if (warning == EWarning::MultiExtruderPrintableError)
show = m_gcode_viewer.has_data() && m_gcode_viewer.m_gcode_check_result.error_code != 0; show = m_gcode_viewer.has_data() && (m_gcode_viewer.m_gcode_check_result.error_code & 1);
else if (warning == EWarning::MultiExtruderHeightOutside)
show = m_gcode_viewer.has_data() && (m_gcode_viewer.m_gcode_check_result.error_code & (1 << 1));
else if (warning == EWarning::FilamentUnPrintableOnFirstLayer) else if (warning == EWarning::FilamentUnPrintableOnFirstLayer)
show = m_gcode_viewer.has_data() && m_gcode_viewer.filament_printable_reuslt.has_value(); show = m_gcode_viewer.has_data() && m_gcode_viewer.filament_printable_reuslt.has_value();
} }
@ -9646,7 +9649,8 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
PLATER_ERROR, PLATER_ERROR,
SLICING_SERIOUS_WARNING, SLICING_SERIOUS_WARNING,
SLICING_ERROR, SLICING_ERROR,
SLICING_LIMIT_ERROR SLICING_LIMIT_ERROR,
SLICING_HEIGHT_OUTSIDE
}; };
std::string text; std::string text;
ErrorType error = ErrorType::PLATER_WARNING; ErrorType error = ErrorType::PLATER_WARNING;
@ -9682,8 +9686,8 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
break; break;
} }
case EWarning::MultiExtruderPrintableError: { case EWarning::MultiExtruderPrintableError: {
for (auto error_iter = m_gcode_viewer.m_gcode_check_result.error_infos.begin(); error_iter != m_gcode_viewer.m_gcode_check_result.error_infos.end(); ++error_iter) { for (auto error_iter = m_gcode_viewer.m_gcode_check_result.print_area_error_infos.begin(); error_iter != m_gcode_viewer.m_gcode_check_result.print_area_error_infos.end(); ++error_iter) {
if (error_iter != m_gcode_viewer.m_gcode_check_result.error_infos.begin()) { if (error_iter != m_gcode_viewer.m_gcode_check_result.print_area_error_infos.begin()) {
text += "\n"; text += "\n";
} }
int extruder_id = error_iter->first + 1; // change extruder id to 1 based int extruder_id = error_iter->first + 1; // change extruder id to 1 based
@ -9696,7 +9700,6 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
int filament_id = error_iter->second[i].first + 1; // change filament id to 1 based int filament_id = error_iter->second[i].first + 1; // change filament id to 1 based
int object_label_id = error_iter->second[i].second; int object_label_id = error_iter->second[i].second;
//ModelObject* object->instances[0]->get_labeled_id();
filaments += std::to_string(filament_id); filaments += std::to_string(filament_id);
for (int object_idx = 0; object_idx < (int) m_model->objects.size(); ++object_idx) { for (int object_idx = 0; object_idx < (int) m_model->objects.size(); ++object_idx) {
const ModelObject *model_object = m_model->objects[object_idx]; const ModelObject *model_object = m_model->objects[object_idx];
@ -9732,6 +9735,63 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
error = ErrorType::SLICING_LIMIT_ERROR; error = ErrorType::SLICING_LIMIT_ERROR;
break; break;
} }
case EWarning::MultiExtruderHeightOutside: {
for (auto error_iter = m_gcode_viewer.m_gcode_check_result.print_height_error_infos.begin(); error_iter != m_gcode_viewer.m_gcode_check_result.print_height_error_infos.end(); ++error_iter) {
if (error_iter != m_gcode_viewer.m_gcode_check_result.print_height_error_infos.begin()) {
text += "\n";
}
int extruder_id = error_iter->first + 1; // change extruder id to 1 based
std::set<int> filament_ids;
std::vector<int> slice_error_object_idxs;
for (size_t i = 0; i < error_iter->second.size(); ++i) {
int filament_id = error_iter->second[i].first + 1; // change filament id to 1 based
int object_label_id = error_iter->second[i].second;
filament_ids.insert(filament_id);
for (int object_idx = 0; object_idx < (int) m_model->objects.size(); ++object_idx) {
const ModelObject *model_object = m_model->objects[object_idx];
for (int instance_idx = 0; instance_idx < (int) model_object->instances.size(); ++instance_idx) {
const ModelInstance *model_instance = model_object->instances[instance_idx];
auto expect_id = model_instance->get_labeled_id();
if (object_label_id == expect_id) {
slice_error_object_idxs.emplace_back(object_idx);
}
}
}
}
std::string filaments;
int index = 0;
for (auto filament_id : filament_ids) {
if (index == 0) {
filaments += ", ";
}
filaments += std::to_string(filament_id);
++index;
}
for (GLVolume *volume : m_gcode_viewer.m_shells.volumes.volumes) {
for (auto obj_idx : slice_error_object_idxs) {
if (volume->object_idx() == obj_idx) {
volume->slice_error = true;
volume->selected = true;
}
}
}
std::string extruder_name = extruder_id == 1 ? "Left extruder" : "Right extruder";
if (error_iter->second.size() == 1) {
text += (boost::format(_u8L("Filament %d is placed in the %s, but the generated G-code path exceeds the printable height of the %s.")) % filaments % extruder_name % extruder_name).str();
} else {
text += (boost::format(_u8L("Filaments %d is placed in the %s, but the generated G-code path exceeds the printable height of the %s.")) % filaments % extruder_name % extruder_name).str();
}
}
if (!text.empty()) {
text += "\n";
text += _u8L("Open wiki for more information.");
}
error = ErrorType::SLICING_LIMIT_ERROR;
break;
}
// BBS: remove _u8L() for SLA // BBS: remove _u8L() for SLA
case EWarning::SlaSupportsOutside: text = ("SLA supports outside the print area were detected."); error = ErrorType::PLATER_ERROR; break; case EWarning::SlaSupportsOutside: text = ("SLA supports outside the print area were detected."); error = ErrorType::PLATER_ERROR; break;
case EWarning::SomethingNotShown: text = _u8L("Only the object being edited is visible."); break; case EWarning::SomethingNotShown: text = _u8L("Only the object being edited is visible."); break;
@ -9798,9 +9858,15 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
break; break;
case SLICING_LIMIT_ERROR: case SLICING_LIMIT_ERROR:
if (state) if (state)
notification_manager.push_slicing_limit_error_notification(text); notification_manager.push_slicing_customize_error_notification(NotificationType::BBLSliceLimitError, NotificationManager::NotificationLevel::ErrorNotificationLevel, text);
else else
notification_manager.close_slicing_limit_error_notification(text); notification_manager.close_slicing_customize_error_notification(NotificationType::BBLSliceLimitError, NotificationManager::NotificationLevel::ErrorNotificationLevel);
break;
case SLICING_HEIGHT_OUTSIDE:
if (state)
notification_manager.push_slicing_customize_error_notification(NotificationType::BBLSliceMultiExtruderHeightOutside, NotificationManager::NotificationLevel::ErrorNotificationLevel, text);
else
notification_manager.close_slicing_customize_error_notification(NotificationType::BBLSliceMultiExtruderHeightOutside, NotificationManager::NotificationLevel::ErrorNotificationLevel);
break; break;
default: default:
break; break;

View File

@ -381,6 +381,7 @@ class GLCanvas3D
ToolHeightOutside, ToolHeightOutside,
TPUPrintableError, TPUPrintableError,
MultiExtruderPrintableError, // after slice MultiExtruderPrintableError, // after slice
MultiExtruderHeightOutside, // after slice
FilamentUnPrintableOnFirstLayer FilamentUnPrintableOnFirstLayer
}; };

View File

@ -1745,17 +1745,17 @@ void NotificationManager::close_general_error_notification(const std::string& te
} }
} }
void NotificationManager::push_slicing_limit_error_notification(const std::string &text) void NotificationManager::push_slicing_customize_error_notification(NotificationType type, NotificationLevel level, const std::string &text)
{ {
set_all_slicing_errors_gray(false); set_all_slicing_errors_gray(false);
push_notification_data({NotificationType::BBLSliceLimitError, NotificationLevel::ErrorNotificationLevel, 0, _u8L("Error:") + "\n" + text}, 0); push_notification_data({type, level, 0, _u8L("Error:") + "\n" + text}, 0);
set_slicing_progress_hidden(); set_slicing_progress_hidden();
} }
void NotificationManager::close_slicing_limit_error_notification(const std::string &text) void NotificationManager::close_slicing_customize_error_notification(NotificationType type, NotificationLevel level)
{ {
for (std::unique_ptr<PopNotification> &notification : m_pop_notifications) { for (std::unique_ptr<PopNotification> &notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::BBLSliceLimitError) { if (notification->get_type() == type && notification->get_data().level == level) {
notification->close(); notification->close();
} }
} }

View File

@ -234,8 +234,8 @@ public:
void close_plater_warning_notification(const std::string& text); void close_plater_warning_notification(const std::string& text);
// GCode exceeds the printing range of the extruder // GCode exceeds the printing range of the extruder
void push_slicing_limit_error_notification(const std::string &text); void push_slicing_customize_error_notification(NotificationType type, NotificationLevel level, const std::string &text);
void close_slicing_limit_error_notification(const std::string &text); void close_slicing_customize_error_notification(NotificationType type, NotificationLevel level);
// Object warning with ObjectID, closes when object is deleted. ID used is of object not print like in slicing warning. // Object warning with ObjectID, closes when object is deleted. ID used is of object not print like in slicing warning.
void push_simplify_suggestion_notification(const std::string& text, ObjectID object_id, const std::string& hypertext = "", void push_simplify_suggestion_notification(const std::string& text, ObjectID object_id, const std::string& hypertext = "",

View File

@ -3151,7 +3151,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
"nozzle_height", "skirt_loops", "skirt_distance", "nozzle_height", "skirt_loops", "skirt_distance",
"brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material", "brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material",
"enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_volume", "enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_volume",
"extruder_colour", "filament_colour", "material_colour", "printable_height", "printer_model", "printer_technology", "extruder_colour", "filament_colour", "material_colour", "printable_height", "extruder_printable_height", "printer_model", "printer_technology",
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor. // These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.
"layer_height", "initial_layer_print_height", "min_layer_height", "max_layer_height", "layer_height", "initial_layer_print_height", "min_layer_height", "max_layer_height",
"brim_width", "wall_loops", "wall_filament", "sparse_infill_density", "sparse_infill_filament", "top_shell_layers", "brim_width", "wall_loops", "wall_filament", "sparse_infill_density", "sparse_infill_filament", "top_shell_layers",