ENH: jump to filament map dialog in error tip

1. Remove error tip for unprintable areas if no longer needed
2. Add link for filament map dialog in error tip

jira:STUDIO-10073

Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: Ic3235038de73a85964c6dbcb9b4f435e7aa47d34
This commit is contained in:
xun.zhang 2025-01-22 19:55:05 +08:00 committed by lane.wei
parent 492033182c
commit 1793060e96
6 changed files with 72 additions and 22 deletions

View File

@ -306,7 +306,7 @@ void FilamentGroupPopup::OnRadioBtn(int idx)
if (m_mode != mode_list.at(idx)) { if (m_mode != mode_list.at(idx)) {
m_mode = mode_list.at(idx); m_mode = mode_list.at(idx);
SetFilamentMapMode(m_mode); SetFilamentMapMode(m_mode);
plater_ref->schedule_background_process(); plater_ref->update();
UpdateButtonStatus(m_mode); UpdateButtonStatus(m_mode);
} }
} }

View File

@ -33,6 +33,9 @@ static std::vector<int> get_applied_map(DynamicConfig& proj_config, const Plater
return plater_ref->get_global_filament_map(); return plater_ref->get_global_filament_map();
} }
extern std::string& get_left_extruder_unprintable_text();
extern std::string& get_right_extruder_unprintable_text();
bool try_pop_up_before_slice(bool skip_plate_sync, Plater* plater_ref, PartPlate* partplate_ref) bool try_pop_up_before_slice(bool skip_plate_sync, Plater* plater_ref, PartPlate* partplate_ref)
{ {
@ -85,6 +88,11 @@ bool try_pop_up_before_slice(bool skip_plate_sync, Plater* plater_ref, PartPlate
if (new_mode == fmmManual) if (new_mode == fmmManual)
plater_ref->set_global_filament_map(new_maps); plater_ref->set_global_filament_map(new_maps);
} }
plater_ref->update();
// check whether able to slice, if not, return false
if (!get_left_extruder_unprintable_text().empty() || !get_right_extruder_unprintable_text().empty()){
return false;
}
return true; return true;
} }
return false; return false;

View File

@ -1440,7 +1440,7 @@ static std::pair<bool, bool> construct_extruder_unprintable_error(ObjectFilament
if (object_result.filaments.empty()) if (object_result.filaments.empty())
return {false,false}; return {false,false};
static const std::vector<std::string> nozzle_name_list = { _u8L("left nozzle"), _u8L("right nozzle") }; const std::vector<std::string> nozzle_name_list = { _u8L("left nozzle"), _u8L("right nozzle") };
std::vector<ObjectFilamentInfo> left_unprintable_objects; std::vector<ObjectFilamentInfo> left_unprintable_objects;
std::vector<ObjectFilamentInfo> right_unprintable_objects; std::vector<ObjectFilamentInfo> right_unprintable_objects;
@ -2997,6 +2997,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
if (m_canvas_type != ECanvasType::CanvasAssembleView) { if (m_canvas_type != ECanvasType::CanvasAssembleView) {
_set_warning_notification_if_needed(EWarning::GCodeConflict); _set_warning_notification_if_needed(EWarning::GCodeConflict);
_set_warning_notification(EWarning::FilamentUnPrintableOnFirstLayer, false); _set_warning_notification(EWarning::FilamentUnPrintableOnFirstLayer, false);
_set_warning_notification_if_needed(EWarning::MultiExtruderPrintableError);
_set_warning_notification_if_needed(EWarning::MultiExtruderHeightOutside);
// checks for geometry outside the print volume to render it accordingly // checks for geometry outside the print volume to render it accordingly
if (!m_volumes.empty()) { if (!m_volumes.empty()) {
ModelInstanceEPrintVolumeState state; ModelInstanceEPrintVolumeState state;
@ -3042,6 +3044,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
_set_warning_notification(EWarning::TPUPrintableError, false); _set_warning_notification(EWarning::TPUPrintableError, false);
_set_warning_notification(EWarning::FilamentPrintableError, false); _set_warning_notification(EWarning::FilamentPrintableError, false);
_set_warning_notification(EWarning::MixUsePLAAndPETG, false); _set_warning_notification(EWarning::MixUsePLAAndPETG, false);
_set_warning_notification(EWarning::MultiExtruderPrintableError,false);
_set_warning_notification(EWarning::MultiExtruderHeightOutside,false);
post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false)); post_event(Event<bool>(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false));
} }
} }
@ -10108,10 +10112,6 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
text += (boost::format(_u8L("Filaments %d is placed in the %s, but the generated G-code path exceeds the printable range of the %s.")) %filaments %extruder_name %extruder_name).str(); text += (boost::format(_u8L("Filaments %d is placed in the %s, but the generated G-code path exceeds the printable range 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; error = ErrorType::SLICING_LIMIT_ERROR;
break; break;
} }
@ -10213,20 +10213,20 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state)
case PLATER_ERROR: case PLATER_ERROR:
if (warning == EWarning::LeftExtruderPrintableError) { if (warning == EWarning::LeftExtruderPrintableError) {
if (state) { if (state) {
if (auto left_str = get_left_extruder_unprintable_text();!left_str.empty()) 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); notification_manager.bbl_show_filament_map_invalid_notification_before_slice(NotificationType::LeftExtruderUnprintableError, left_str);
} }
else { else {
notification_manager.close_slicing_customize_error_notification(NotificationType::LeftExtruderUnprintableError, NotificationLevel::ErrorNotificationLevel); notification_manager.bbl_close_filament_map_invalid_notification_before_slice(NotificationType::LeftExtruderUnprintableError);
} }
} }
else if (warning == EWarning::RightExtruderPrintableError) { else if (warning == EWarning::RightExtruderPrintableError) {
if (state) { if (state) {
if (auto right_str = get_right_extruder_unprintable_text(); !right_str.empty()) 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); notification_manager.bbl_show_filament_map_invalid_notification_before_slice(NotificationType::RightExtruderUnprintableError, right_str);
} }
else { else {
notification_manager.close_slicing_customize_error_notification(NotificationType::RightExtruderUnprintableError, NotificationLevel::ErrorNotificationLevel); notification_manager.bbl_close_filament_map_invalid_notification_before_slice(NotificationType::RightExtruderUnprintableError);
} }
} }
else if (warning == EWarning::ObjectClashed) { else if (warning == EWarning::ObjectClashed) {
@ -10276,9 +10276,9 @@ 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_customize_error_notification(NotificationType::BBLSliceLimitError, NotificationLevel::ErrorNotificationLevel, text); notification_manager.bbl_show_filament_map_invalid_notification_after_slice(NotificationType::BBLSliceLimitError, text);
else else
notification_manager.close_slicing_customize_error_notification(NotificationType::BBLSliceLimitError, NotificationLevel::ErrorNotificationLevel); notification_manager.bbl_close_filament_map_invalid_notification_after_slice(NotificationType::BBLSliceLimitError);
break; break;
case SLICING_HEIGHT_OUTSIDE: case SLICING_HEIGHT_OUTSIDE:
if (state) if (state)

View File

@ -22,6 +22,7 @@
#include <wx/glcanvas.h> #include <wx/glcanvas.h>
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "FilamentMapDialog.hpp"
#ifndef IMGUI_DEFINE_MATH_OPERATORS #ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS
@ -2799,6 +2800,46 @@ void NotificationManager::bbl_close_bed_filament_incompatible_notification()
close_notification_of_type(NotificationType::BBLBedFilamentIncompatible); close_notification_of_type(NotificationType::BBLBedFilamentIncompatible);
} }
void NotificationManager::bbl_show_filament_map_invalid_notification_before_slice(const NotificationType type,const std::string& text)
{
auto callback = [](wxEvtHandler*) {
auto plater = wxGetApp().plater();
auto partplate = plater->get_partplate_list().get_curr_plate();
try_pop_up_before_slice(false, plater, partplate); // ignore the return value
return false;
};
push_notification_data({ type,NotificationLevel::ErrorNotificationLevel,0,_u8L("Error:") + "\n" + text,_u8L("Click here to regroup"),callback }, 0);
}
void NotificationManager::bbl_close_filament_map_invalid_notification_before_slice(const NotificationType type)
{
close_notification_of_type(type);
}
void NotificationManager::bbl_show_filament_map_invalid_notification_after_slice(const NotificationType type, const std::string& text)
{
auto callback = [](wxEvtHandler*) {
auto plater = wxGetApp().plater();
wxCommandEvent evt(EVT_OPEN_FILAMENT_MAP_SETTINGS_DIALOG);
evt.SetEventObject(plater);
auto canvas_type = plater->canvas3D()->get_canvas_type();
if (canvas_type == GLCanvas3D::ECanvasType::CanvasPreview)
evt.SetInt(1); // 1 means from gcode viewer, should do slice right now
else
evt.SetInt(0);
wxPostEvent(plater, evt);
return false;
};
push_notification_data({ type,NotificationLevel::ErrorNotificationLevel,0,_u8L("Error:") + "\n" + text,_u8L("Click here to regroup"),callback }, 0);
}
void NotificationManager::bbl_close_filament_map_invalid_notification_after_slice(const NotificationType type)
{
close_notification_of_type(type);
}
void NotificationManager::bbl_show_sole_text_notification(NotificationType sType, const std::string &text, bool bOverride, int level, bool autohide) { void NotificationManager::bbl_show_sole_text_notification(NotificationType sType, const std::string &text, bool bOverride, int level, bool autohide) {
NotificationLevel nlevel; NotificationLevel nlevel;

View File

@ -352,6 +352,12 @@ public:
void bbl_show_bed_filament_incompatible_notification(const std::string& text); void bbl_show_bed_filament_incompatible_notification(const std::string& text);
void bbl_close_bed_filament_incompatible_notification(); void bbl_close_bed_filament_incompatible_notification();
void bbl_show_filament_map_invalid_notification_before_slice(const NotificationType type, const std::string& text);
void bbl_close_filament_map_invalid_notification_before_slice(const NotificationType type);
void bbl_show_filament_map_invalid_notification_after_slice(const NotificationType type, const std::string& text);
void bbl_close_filament_map_invalid_notification_after_slice(const NotificationType type);
//BBS--sole notification //BBS--sole notification
void bbl_show_sole_text_notification(NotificationType sType,const std::string &text, bool bOverride, int level, bool autohide); void bbl_show_sole_text_notification(NotificationType sType,const std::string &text, bool bOverride, int level, bool autohide);
void bbl_chose_sole_text_notification(NotificationType sType); void bbl_chose_sole_text_notification(NotificationType sType);

View File

@ -15758,22 +15758,18 @@ void Plater::validate_current_plate(bool& model_fits, bool& validate_error)
std::string left_unprintable_text = get_left_extruder_unprintable_text(), right_unprintable_text = get_right_extruder_unprintable_text(); std::string left_unprintable_text = get_left_extruder_unprintable_text(), right_unprintable_text = get_right_extruder_unprintable_text();
if (!left_unprintable_text.empty()) if (!left_unprintable_text.empty())
{ {
p->notification_manager->push_slicing_customize_error_notification(NotificationType::LeftExtruderUnprintableError, p->notification_manager->bbl_show_filament_map_invalid_notification_before_slice(NotificationType::LeftExtruderUnprintableError, left_unprintable_text);
NotificationManager::NotificationLevel::ErrorNotificationLevel, left_unprintable_text);
} }
else { else {
p->notification_manager->close_slicing_customize_error_notification(NotificationType::LeftExtruderUnprintableError, p->notification_manager->bbl_close_filament_map_invalid_notification_before_slice(NotificationType::LeftExtruderUnprintableError);
NotificationManager::NotificationLevel::ErrorNotificationLevel);
} }
if (!right_unprintable_text.empty()) if (!right_unprintable_text.empty())
{ {
p->notification_manager->push_slicing_customize_error_notification(NotificationType::RightExtruderUnprintableError, p->notification_manager->bbl_show_filament_map_invalid_notification_before_slice(NotificationType::RightExtruderUnprintableError,right_unprintable_text);
NotificationManager::NotificationLevel::ErrorNotificationLevel, right_unprintable_text);
} }
else { else {
p->notification_manager->close_slicing_customize_error_notification(NotificationType::RightExtruderUnprintableError, p->notification_manager->bbl_close_filament_map_invalid_notification_before_slice(NotificationType::RightExtruderUnprintableError);
NotificationManager::NotificationLevel::ErrorNotificationLevel);
} }
/*if (state == ModelInstancePVS_Limited) { /*if (state == ModelInstancePVS_Limited) {
@ -15871,7 +15867,6 @@ void Plater::open_filament_map_setting_dialog(wxCommandEvent &evt)
{ {
PartPlate* curr_plate = p->partplate_list.get_curr_plate(); PartPlate* curr_plate = p->partplate_list.get_curr_plate();
int value = evt.GetInt(); //1 means from gcode view int value = evt.GetInt(); //1 means from gcode view
bool force_manual = value == 1; // If from gcode view, should display manual page
bool need_slice = value ==1; // If from gcode view, should slice bool need_slice = value ==1; // If from gcode view, should slice
const auto& project_config = wxGetApp().preset_bundle->project_config; const auto& project_config = wxGetApp().preset_bundle->project_config;