diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 1c6778311..013daa8f2 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -139,6 +139,17 @@ std::string& get_object_clashed_text() { return object_clashed_text; } +std::string& get_left_extruder_unprintable_text() { + static std::string left_unprintable_text; + return left_unprintable_text; +} + +std::string& get_right_extruder_unprintable_text() { + static std::string right_unprintable_text; + return right_unprintable_text; +} + + wxString filament_printable_error_msg; GLCanvas3D::LayersEditing::~LayersEditing() @@ -1419,69 +1430,74 @@ void GLCanvas3D::construct_error_string(ObjectFilamentResults& object_result, st error_string += _u8L("Please solve the problem by moving it totally on or off the plate, and confirming that the height is within the build volume.\n"); } - if (!object_result.filaments.empty()) { - std::vector left_unprintable_objects; - std::vector right_unprintable_objects; +} - std::vector conflicted_filaments = object_result.filaments; +static std::pair construct_extruder_unprintable_error(ObjectFilamentResults& object_result, std::string& left_extruder_unprintable_text, std::string& right_extruder_unprintable_text) +{ + if (object_result.filaments.empty()) + return {false,false}; - auto mode = object_result.mode; + static const std::vector nozzle_name_list = { _u8L("left nozzle"), _u8L("right nozzle") }; - for (auto& obj_filament : object_result.object_filaments) { - if (mode == FilamentMapMode::fmmManual) { - for (auto& elem : obj_filament.manual_filaments) { - bool found_left = false, found_right = false; - int filamnet_id = elem.first; - int extruder_id = elem.second; - if (extruder_id == 1 && !found_left) { - found_left = true; - left_unprintable_objects.emplace_back(obj_filament); - } - if (extruder_id == 2 && !found_right) { - found_right = true; - right_unprintable_objects.emplace_back(obj_filament); - } - } - } - else { - if (!obj_filament.auto_filaments.empty()) { + std::vector left_unprintable_objects; + std::vector right_unprintable_objects; + + std::vector conflicted_filaments = object_result.filaments; + + auto mode = object_result.mode; + + for (auto& obj_filament : object_result.object_filaments) { + if (mode == FilamentMapMode::fmmManual) { + for (auto& elem : obj_filament.manual_filaments) { + bool found_left = false, found_right = false; + int filamnet_id = elem.first; + int extruder_id = elem.second; + if (extruder_id == 1 && !found_left) { + found_left = true; left_unprintable_objects.emplace_back(obj_filament); + } + if (extruder_id == 2 && !found_right) { + found_right = true; right_unprintable_objects.emplace_back(obj_filament); } } } - - std::vector tips(2); - for (size_t idx = 0; idx < tips.size(); ++idx) { - const auto& unprintable_objs = idx == 0 ? left_unprintable_objects : right_unprintable_objects; - if (unprintable_objs.empty()) - continue; - std::string nozzle_name = idx == 0 ? _u8L("left nozzle") : _u8L("right nozzle"); - std::string opposite_nozzle_name = idx == 0 ? _u8L("right nozzle") : _u8L("left nozzle"); - std::string model_prefix; - if (object_result.object_filaments.size() > 1) - model_prefix = _u8L("Some models are"); - else - model_prefix = (boost::format(_u8L("The model %s is"))%object_result.object_filaments.front().object->name).str(); - tips[idx] += model_prefix; - tips[idx] += (boost::format(_u8L(" located within the %s only area, making it impossible to print with the filaments assigned to %s.\n" - "Please move the model out of the %s only area or adjust the filament assignment\n")) % opposite_nozzle_name% nozzle_name % opposite_nozzle_name).str(); - - if (object_result.object_filaments.size() > 1) { - for (ObjectFilamentInfo& object_filament : left_unprintable_objects) - { - tips[idx] += object_filament.object->name; - tips[idx] += "\n"; - } - } - } - - for (size_t idx = 0; idx < tips.size(); ++idx) { - if (!tips[idx].empty()) { - error_string = tips[idx]; + else { + if (!obj_filament.auto_filaments.empty()) { + left_unprintable_objects.emplace_back(obj_filament); + right_unprintable_objects.emplace_back(obj_filament); } } } + + std::vector tips(2); + for (size_t idx = 0; idx < tips.size(); ++idx) { + const auto& unprintable_objs = idx == 0 ? left_unprintable_objects : right_unprintable_objects; + auto& output_text = idx == 0 ? left_extruder_unprintable_text : right_extruder_unprintable_text; + if (unprintable_objs.empty()) + continue; + std::string nozzle_name = nozzle_name_list[0]; + std::string opposite_nozzle_name = idx == 0 ? nozzle_name_list[1] : nozzle_name_list[0]; + std::string model_prefix; + if (object_result.object_filaments.size() > 1) + model_prefix = _u8L("Some models are"); + else + model_prefix = (boost::format(_u8L("The model %s is")) % object_result.object_filaments.front().object->name).str(); + tips[idx] += model_prefix; + tips[idx] += (boost::format(_u8L(" located within the %s only area, making it impossible to print with the filaments assigned to %s.\n" + "Please move the model out of the %s only area or adjust the filament assignment\n")) % opposite_nozzle_name % nozzle_name % opposite_nozzle_name).str(); + + if (object_result.object_filaments.size() > 1) { + for (ObjectFilamentInfo& object_filament : left_unprintable_objects) + { + tips[idx] += object_filament.object->name; + tips[idx] += "\n"; + } + } + output_text = tips[idx]; + } + + return { !left_unprintable_objects.empty(),!right_unprintable_objects.empty() }; } ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state(ObjectFilamentResults* object_results) const @@ -1496,6 +1512,7 @@ ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state(ObjectFil m_volumes.check_outside_state(m_bed.build_volume(), &state, object_results); construct_error_string(*object_results, get_object_clashed_text()); + construct_extruder_unprintable_error(*object_results, get_left_extruder_unprintable_text(), get_right_extruder_unprintable_text()); return state; } @@ -2992,8 +3009,11 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re const bool objectLimited = (state == ModelInstanceEPrintVolumeState::ModelInstancePVS_Limited); construct_error_string(object_results, get_object_clashed_text()); + auto unprintable_flag= construct_extruder_unprintable_error(object_results, get_left_extruder_unprintable_text(), get_right_extruder_unprintable_text()); - _set_warning_notification(EWarning::ObjectClashed, partlyOut || !object_results.filaments.empty()); + _set_warning_notification(EWarning::ObjectClashed, partlyOut); + _set_warning_notification(EWarning::LeftExtruderPrintableError, unprintable_flag.first); + _set_warning_notification(EWarning::RightExtruderPrintableError, unprintable_flag.second); _set_warning_notification(EWarning::ObjectLimited, objectLimited); //BBS: turn off the warning when fully outside //_set_warning_notification(EWarning::ObjectOutside, fullyOut); @@ -3017,6 +3037,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re else { _set_warning_notification(EWarning::ObjectOutside, false); _set_warning_notification(EWarning::ObjectClashed, false); + _set_warning_notification(EWarning::LeftExtruderPrintableError, false); + _set_warning_notification(EWarning::RightExtruderPrintableError, false); _set_warning_notification(EWarning::ObjectLimited, false); //_set_warning_notification(EWarning::SlaSupportsOutside, false); _set_warning_notification(EWarning::TPUPrintableError, false); @@ -9990,6 +10012,7 @@ void GLCanvas3D::_render_silhouette_effect() void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) { + using NotificationLevel = NotificationManager::NotificationLevel; enum ErrorType{ PLATER_WARNING, PLATER_ERROR, @@ -10037,6 +10060,11 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) error = ErrorType::SLICING_ERROR; break; } + case EWarning::LeftExtruderPrintableError: + case EWarning::RightExtruderPrintableError: { + error = ErrorType::PLATER_ERROR; + break; + } case EWarning::MultiExtruderPrintableError: { 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.print_area_error_infos.begin()) { @@ -10184,10 +10212,30 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) notification_manager.close_plater_warning_notification(text); break; case PLATER_ERROR: - if (state) - notification_manager.push_plater_error_notification(text); - else - notification_manager.close_plater_error_notification(text); + if (warning == EWarning::LeftExtruderPrintableError) { + if (state) { + if (auto left_str = get_left_extruder_unprintable_text();!left_str.empty()) + notification_manager.push_slicing_customize_error_notification(NotificationType::LeftExtruderUnprintableError, NotificationLevel::ErrorNotificationLevel, left_str); + } + else { + notification_manager.close_slicing_customize_error_notification(NotificationType::LeftExtruderUnprintableError, NotificationLevel::ErrorNotificationLevel); + } + } + else if (warning == EWarning::RightExtruderPrintableError) { + if (state) { + if (auto right_str = get_right_extruder_unprintable_text(); !right_str.empty()) + notification_manager.push_slicing_customize_error_notification(NotificationType::RightExtruderUnprintableError, NotificationLevel::ErrorNotificationLevel, right_str); + } + else { + notification_manager.close_slicing_customize_error_notification(NotificationType::RightExtruderUnprintableError, NotificationLevel::ErrorNotificationLevel); + } + } + else { + if (state) + notification_manager.push_plater_error_notification(text); + else + notification_manager.close_plater_error_notification(text); + } break; case SLICING_SERIOUS_WARNING: if (state) @@ -10206,9 +10254,9 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) } if (warning == EWarning::FilamentPrintableError) { if (state) - notification_manager.push_slicing_customize_error_notification(NotificationType::BBLFilamentPrintableError, NotificationManager::NotificationLevel::ErrorNotificationLevel, text); + notification_manager.push_slicing_customize_error_notification(NotificationType::BBLFilamentPrintableError, NotificationLevel::ErrorNotificationLevel, text); else - notification_manager.close_slicing_customize_error_notification(NotificationType::BBLFilamentPrintableError, NotificationManager::NotificationLevel::ErrorNotificationLevel); + notification_manager.close_slicing_customize_error_notification(NotificationType::BBLFilamentPrintableError, NotificationLevel::ErrorNotificationLevel); } else { if (state) @@ -10219,15 +10267,15 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) break; case SLICING_LIMIT_ERROR: if (state) - notification_manager.push_slicing_customize_error_notification(NotificationType::BBLSliceLimitError, NotificationManager::NotificationLevel::ErrorNotificationLevel, text); + notification_manager.push_slicing_customize_error_notification(NotificationType::BBLSliceLimitError, NotificationLevel::ErrorNotificationLevel, text); else - notification_manager.close_slicing_customize_error_notification(NotificationType::BBLSliceLimitError, NotificationManager::NotificationLevel::ErrorNotificationLevel); + notification_manager.close_slicing_customize_error_notification(NotificationType::BBLSliceLimitError, NotificationLevel::ErrorNotificationLevel); break; case SLICING_HEIGHT_OUTSIDE: if (state) - notification_manager.push_slicing_customize_error_notification(NotificationType::BBLSliceMultiExtruderHeightOutside, NotificationManager::NotificationLevel::ErrorNotificationLevel, text); + notification_manager.push_slicing_customize_error_notification(NotificationType::BBLSliceMultiExtruderHeightOutside, NotificationLevel::ErrorNotificationLevel, text); else - notification_manager.close_slicing_customize_error_notification(NotificationType::BBLSliceMultiExtruderHeightOutside, NotificationManager::NotificationLevel::ErrorNotificationLevel); + notification_manager.close_slicing_customize_error_notification(NotificationType::BBLSliceMultiExtruderHeightOutside, NotificationLevel::ErrorNotificationLevel); break; default: break; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index bf5ffc0fb..a8422caf4 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -383,6 +383,8 @@ class GLCanvas3D ToolHeightOutside, TPUPrintableError, FilamentPrintableError, + LeftExtruderPrintableError, // before slice + RightExtruderPrintableError, // before slice MultiExtruderPrintableError, // after slice MultiExtruderHeightOutside, // after slice FilamentUnPrintableOnFirstLayer, diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index dcb109647..a735d8efd 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1789,6 +1789,8 @@ void NotificationManager::close_plater_warning_notification(const std::string& t } } } + + void NotificationManager::set_all_slicing_errors_gray(bool g) { for (std::unique_ptr ¬ification : m_pop_notifications) { diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 750b6c5f9..16f321d29 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -84,6 +84,8 @@ enum class NotificationType BBLGeneralError, // Object partially outside the print volume. Cannot slice. PlaterError, + LeftExtruderUnprintableError, + RightExtruderUnprintableError, // Object fully outside the print volume, or extrusion outside the print volume. Slicing is not disabled. PlaterWarning, // Progress bar instead of text. @@ -233,7 +235,6 @@ public: // Closes error or warning of the same text void close_plater_error_notification(const std::string& text); void close_plater_warning_notification(const std::string& text); - // GCode exceeds the printing range of the extruder void push_slicing_customize_error_notification(NotificationType type, NotificationLevel level, const std::string &text); void close_slicing_customize_error_notification(NotificationType type, NotificationLevel level);