diff --git a/resources/profiles/BBL.json b/resources/profiles/BBL.json index 3f60611a4..423e42176 100644 --- a/resources/profiles/BBL.json +++ b/resources/profiles/BBL.json @@ -1,7 +1,7 @@ { "name": "Bambulab", "url": "http://www.bambulab.com/Parameters/vendor/BBL.json", - "version": "02.00.00.12", + "version": "02.00.00.15", "force_update": "0", "description": "the initial version of BBL configurations", "machine_model_list": [ diff --git a/resources/profiles/BBL/machine/Bambu Lab H2D 0.4 nozzle.json b/resources/profiles/BBL/machine/Bambu Lab H2D 0.4 nozzle.json index 955ad456f..1b8715c6f 100644 --- a/resources/profiles/BBL/machine/Bambu Lab H2D 0.4 nozzle.json +++ b/resources/profiles/BBL/machine/Bambu Lab H2D 0.4 nozzle.json @@ -28,6 +28,10 @@ "25x0,350x0,350x320,25x320" ], "machine_load_filament_time": "24", + "unprintable_filament_types" : [ + "TPU", + "PPS-CF,PPA-CF" + ], "machine_max_acceleration_x": [ "16000", "16000", diff --git a/resources/profiles/BBL/machine/fdm_bbl_3dp_001_common.json b/resources/profiles/BBL/machine/fdm_bbl_3dp_001_common.json index 2ecd86418..114a18c66 100644 --- a/resources/profiles/BBL/machine/fdm_bbl_3dp_001_common.json +++ b/resources/profiles/BBL/machine/fdm_bbl_3dp_001_common.json @@ -39,6 +39,7 @@ ], "extruder_printable_area": [], "extruder_printable_height": [], + "unprintable_filament_types" : [""], "extruder_type": [ "Direct Drive" ], diff --git a/resources/profiles/BBL/machine/fdm_bbl_3dp_002_common.json b/resources/profiles/BBL/machine/fdm_bbl_3dp_002_common.json index f04af9bdd..7c215c892 100644 --- a/resources/profiles/BBL/machine/fdm_bbl_3dp_002_common.json +++ b/resources/profiles/BBL/machine/fdm_bbl_3dp_002_common.json @@ -48,6 +48,10 @@ "320", "325" ], + "unprintable_filament_types" : [ + "", + "" + ], "extruder_type": [ "Direct Drive", "Direct Drive" diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index 6c7584ff9..c9e073c24 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -54,6 +54,26 @@ bool LayerTools::is_extruder_order(unsigned int a, unsigned int b) const return false; } +bool check_filament_printable_after_group(const std::vector &used_filaments, const std::vector &filament_maps, const PrintConfig *print_config) +{ + for (unsigned int filament_id : used_filaments) { + std::string filament_type = print_config->filament_type.get_at(filament_id); + for (size_t idx = 0; idx < print_config->unprintable_filament_types.values.size(); ++idx) { + if (filament_maps[filament_id] == idx) { + std::vector limit_types = split_string(print_config->unprintable_filament_types.get_at(idx), ','); + auto iter = std::find(limit_types.begin(), limit_types.end(), filament_type); + if (iter != limit_types.end()) { + std::string error_msg; + std::string extruder_name = idx == 0 ? "left" : "right"; + error_msg = "Grouping error: " + filament_type + " can not be placed in the " + extruder_name + " extruder"; + throw Slic3r::RuntimeError(error_msg); + } + } + } + } + return true; +} + // Return a zero based extruder from the region, or extruder_override if overriden. unsigned int LayerTools::wall_filament(const PrintRegion ®ion) const { @@ -1024,6 +1044,14 @@ std::vector ToolOrdering::get_recommended_filament_maps(const std::vector s_Preset_printer_options { "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", "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", "unprintable_filament_types", "default_print_profile", "inherits", "silent_mode", // BBS diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 3c3548329..54e4815a6 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -565,6 +565,12 @@ void PrintConfigDef::init_common_params() def->mode = comSimple; def->set_default_value(new ConfigOptionFloatsNullable{}); + def = this->add("unprintable_filament_types", coStrings); + def->label = L("Unprintable filament type"); + def->tooltip = L("Unprintable filament type"); + def->mode = comDevelop; + def->set_default_value(new ConfigOptionStrings{""}); + // Options used by physical printers def = this->add("preset_names", coStrings); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 454712e56..664b58232 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1113,6 +1113,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionPoints, bed_exclude_area)) ((ConfigOptionPoints, head_wrap_detect_zone)) // BBS + ((ConfigOptionStrings, unprintable_filament_types)) ((ConfigOptionString, bed_custom_texture)) ((ConfigOptionString, bed_custom_model)) ((ConfigOptionEnum, curr_bed_type)) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 55794aad3..5e64c843d 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -172,6 +172,7 @@ typedef std::string local_encoded_string; extern local_encoded_string encode_path(const char *src); extern std::string decode_path(const char *src); extern std::string normalize_utf8_nfc(const char *src); +extern std::vector split_string(const std::string &str, char delimiter); // Safely rename a file even if the target exists. // On Windows, the file explorer (or anti-virus or whatever else) often locks the file diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index 226b01e7b..27188923f 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -1089,6 +1089,18 @@ std::string normalize_utf8_nfc(const char *src) return boost::locale::normalize(src, boost::locale::norm_nfc, locale_utf8); } +std::vector split_string(const std::string &str, char delimiter) +{ + std::vector result; + std::stringstream ss(str); + std::string substr; + + while (std::getline(ss, substr, delimiter)) { + result.push_back(substr); + } + return result; +} + namespace PerlUtils { // Get a file name including the extension. std::string path_to_filename(const char *src) { return boost::filesystem::path(src).filename().string(); } diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index ce5740a2b..93d9e3e2e 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -327,9 +327,23 @@ PrinterArch get_printer_arch_by_str(std::string arch_str) void check_filaments_for_vt_slot(const std::string &tag_vendor, const std::string &tag_type, int ams_id, bool &in_blacklist, std::string &ac, std::string &info) { + DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) + return; + + MachineObject *obj = dev->get_selected_machine(); + if (obj == nullptr) + return; + if (tag_type == "TPU" && ams_id != VIRTUAL_TRAY_MAIN_ID) { + wxString extruder_name = _L("left"); + if (obj->is_main_extruder_on_left()) { + extruder_name = _L("right"); + } + wxString info_str = wxString::Format(_L("TPU is not supported by %s extruder for this printer."), extruder_name); + ac = "prohibition"; - info = wxString(_L("TPU is not supported by deputy extruder.")).ToUTF8().data(); + info = info_str.ToUTF8().data(); in_blacklist = true; } } @@ -7012,7 +7026,6 @@ void DeviceManager::load_last_machine() json DeviceManager::filaments_blacklist = json::object(); - std::string DeviceManager::parse_printer_type(std::string type_str) { return get_value_from_config(type_str, "printer_type"); @@ -7173,8 +7186,54 @@ bool DeviceManager::is_virtual_slot(int ams_id) return false; } +bool DeviceManager::check_filaments_printable(const std::string &tag_vendor, const std::string &tag_type, int ams_id, bool &in_blacklist, std::string &ac, std::string &info) +{ + DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager(); + if (!dev) { + return true; + } + + MachineObject *obj = dev->get_selected_machine(); + if (obj == nullptr || !obj->is_multi_extruders()) { + return true; + } + + Preset *printer_preset = GUI::get_printer_preset(obj); + if (!printer_preset) + return true; + + ConfigOptionStrings *unprintable_filament_types_op = dynamic_cast(printer_preset->config.option("unprintable_filament_types")); + if (!unprintable_filament_types_op) + return true; + + ConfigOptionInts *physical_extruder_map_op = dynamic_cast(printer_preset->config.option("physical_extruder_map")); + if (!physical_extruder_map_op) + return true; + + std::vector physical_extruder_maps = physical_extruder_map_op->values; + for (size_t idx = 0; idx < unprintable_filament_types_op->values.size(); ++idx) { + if (physical_extruder_maps[idx] == obj->get_extruder_id_by_ams_id(std::to_string(ams_id))) { + std::vector filament_types = split_string(unprintable_filament_types_op->values.at(idx), ','); + auto iter = std::find(filament_types.begin(), filament_types.end(), tag_type); + if (iter != filament_types.end()) { + wxString extruder_name = idx == 0 ? _L("left") : _L("right"); + ac = "prohibition"; + info = (wxString::Format(_L("%s is not supported by %s extruder."), tag_type, extruder_name)).ToUTF8().data(); + in_blacklist = true; + return false; + } + } + } + + return true; +} + void DeviceManager::check_filaments_in_blacklist(std::string tag_vendor, std::string tag_type, int ams_id, bool& in_blacklist, std::string& ac, std::string& info) { + if (!check_filaments_printable(tag_vendor, tag_type, ams_id, in_blacklist, ac, info)) { + return; + } + if (DeviceManager::is_virtual_slot(ams_id)) { check_filaments_for_vt_slot(tag_vendor, tag_type, ams_id, in_blacklist, ac, info); return; diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index f709ccc4b..d07879e10 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -1294,6 +1294,7 @@ public: static bool key_field_only; static json function_table; static json filaments_blacklist; + static json filaments_printable_blacklist; template static T get_value_from_config(std::string type_str, std::string item){ @@ -1329,6 +1330,7 @@ public: static std::vector get_resolution_supported(std::string type_str); static std::vector get_compatible_machine(std::string type_str); static void check_filaments_in_blacklist(std::string tag_vendor, std::string tag_type, int ams_id, bool &in_blacklist, std::string &ac, std::string &info); + static bool check_filaments_printable(const std::string &tag_vendor, const std::string &tag_type, int ams_id, bool &in_blacklist, std::string &ac, std::string &info); static boost::bimaps::bimap get_all_model_id_with_name(); static std::string load_gcode(std::string type_str, std::string gcode_file); static bool is_virtual_slot(int ams_id); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index e4fd540c8..15deb9b0e 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -130,6 +130,8 @@ std::string object_limited_text = _u8L("An object is laid on the left/right extr std::string object_clashed_text = _u8L("An object is laid over the boundary of plate or exceeds the height limit.\n" "Please solve the problem by moving it totally on or off the plate, and confirming that the height is within the build volume."); +wxString filament_printable_error_msg; + GLCanvas3D::LayersEditing::~LayersEditing() { if (m_z_texture_id != 0) { @@ -2958,6 +2960,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re bool tpu_valid = cur_plate->check_tpu_printable_status(wxGetApp().preset_bundle->full_config(), wxGetApp().preset_bundle->get_used_tpu_filaments(cur_plate->get_extruders(true))); _set_warning_notification(EWarning::TPUPrintableError, !tpu_valid); + bool filament_printable = cur_plate->check_filament_printable(wxGetApp().preset_bundle->full_config(), filament_printable_error_msg); + _set_warning_notification(EWarning::FilamentPrintableError, !filament_printable); + bool model_fits = contained_min_one && !m_model->objects.empty() && !partlyOut && object_results.filaments.empty() && tpu_valid; post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, model_fits)); ppl.get_curr_plate()->update_slice_ready_status(model_fits); @@ -2968,6 +2973,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re _set_warning_notification(EWarning::ObjectLimited, false); //_set_warning_notification(EWarning::SlaSupportsOutside, false); _set_warning_notification(EWarning::TPUPrintableError, false); + _set_warning_notification(EWarning::FilamentPrintableError, false); post_event(Event(EVT_GLCANVAS_ENABLE_ACTION_BUTTONS, false)); } } @@ -9977,6 +9983,11 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) error = ErrorType::SLICING_ERROR; break; } + case EWarning::FilamentPrintableError: { + text = filament_printable_error_msg.ToUTF8(); + error = ErrorType::SLICING_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()) { @@ -10141,6 +10152,12 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) notification_manager.bbl_close_bed_filament_incompatible_notification(); } } + if (warning == EWarning::FilamentPrintableError) { + if (state) + notification_manager.push_slicing_customize_error_notification(NotificationType::BBLFilamentPrintableError, NotificationManager::NotificationLevel::ErrorNotificationLevel, text); + else + notification_manager.close_slicing_customize_error_notification(NotificationType::BBLFilamentPrintableError, NotificationManager::NotificationLevel::ErrorNotificationLevel); + } else { if (state) notification_manager.push_slicing_error_notification(text, conflictObj ? std::vector{conflictObj} : std::vector{}); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d36178105..579b5238a 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -382,6 +382,7 @@ class GLCanvas3D GCodeConflict, ToolHeightOutside, TPUPrintableError, + FilamentPrintableError, MultiExtruderPrintableError, // after slice MultiExtruderHeightOutside, // after slice FilamentUnPrintableOnFirstLayer diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index ae1a94c64..750b6c5f9 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -147,6 +147,7 @@ enum class NotificationType BBLPreviewOnlyMode, BBLPrinterConfigUpdateAvailable, BBLUserPresetExceedLimit, + BBLFilamentPrintableError, BBLSliceLimitError, BBLBedFilamentIncompatible, NotificationTypeCount diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index d4699d300..0a6b839f1 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -1307,6 +1307,29 @@ std::vector PartPlate::get_used_filaments() return std::vector(used_extruders_set.begin(), used_extruders_set.end()); } +bool PartPlate::check_filament_printable(const DynamicPrintConfig &config, wxString& error_message) +{ + error_message.clear(); + std::vector used_filaments = get_extruders(true); // 1 base + if (!used_filaments.empty()) { + for (auto filament_idx : used_filaments) { + int filament_id = filament_idx - 1; + std::string filament_type = config.option("filament_type")->values.at(filament_id); + std::vector filament_map = get_real_filament_maps(config); + int extruder_idx = filament_map[filament_id] - 1; + std::string filament_types_str = config.option("unprintable_filament_types")->values.at(extruder_idx); + std::vector filament_types = split_string(filament_types_str, ','); + auto iter = std::find(filament_types.begin(), filament_types.end(), filament_type); + if (iter != filament_types.end()) { + wxString extruder_name = extruder_idx == 0 ? _L("left") : _L("right"); + error_message = wxString::Format(_L("Filament %s cannot be placed in the %s extruder for printing."), filament_type, extruder_name); + return false; + } + } + } + return true; +} + bool PartPlate::check_tpu_printable_status(const DynamicPrintConfig & config, const std::vector &tpu_filaments) { bool tpu_valid = true; diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 93e09d0a1..7f6162b03 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -314,6 +314,7 @@ public: // get used filaments from gcode result, 1 based idx std::vector get_used_filaments(); int get_physical_extruder_by_filament_id(const DynamicConfig& g_config, int idx) const; + bool check_filament_printable(const DynamicPrintConfig & config, wxString& error_message); bool check_tpu_printable_status(const DynamicPrintConfig & config, const std::vector &tpu_filaments); /* instance related operations*/