From 756a76a77318cc25ea6c4fe532d003fd5c7fda3a Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 23 Jul 2024 16:21:29 +0200 Subject: [PATCH 01/16] repo_prefix parameter and removing prefix before send to connect. Change printer_model in full config before applying to print printer_model prefix handling when showing online printers in sidebar Select printer from connect by nozzle diameter (instead of pritner_variant) and by additional config options. + Moved standalone functions to UserAccountUtils Set as current without repo prefix when selecting preset with prefix, mind visible presets. prefer visible printers for selecting fix of selecting SLA printer Added prusalink for prefixed printer_model --- src/libslic3r/Preset.cpp | 7 + src/libslic3r/Preset.hpp | 1 + src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/GUI_App.cpp | 104 +++++++++- src/slic3r/GUI/PhysicalPrinterDialog.cpp | 18 +- src/slic3r/GUI/Plater.cpp | 28 ++- src/slic3r/GUI/PresetComboBoxes.cpp | 35 +++- src/slic3r/GUI/UserAccount.cpp | 235 +---------------------- src/slic3r/GUI/UserAccount.hpp | 7 - src/slic3r/GUI/UserAccountUtils.cpp | 222 +++++++++++++++++++++ src/slic3r/GUI/UserAccountUtils.hpp | 27 +++ src/slic3r/GUI/WebViewDialog.cpp | 61 ++++-- 12 files changed, 476 insertions(+), 271 deletions(-) create mode 100644 src/slic3r/GUI/UserAccountUtils.cpp create mode 100644 src/slic3r/GUI/UserAccountUtils.hpp diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 96a5572435..0f1b6cef61 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -165,6 +165,13 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem res.repo_id = ""; } + const auto repo_prefix = vendor_section.find("repo_prefix"); + if (repo_prefix != vendor_section.not_found()) { + res.repo_prefix = repo_prefix->second.data(); + } else { + res.repo_prefix = ""; + } + if (! load_all) { return res; } diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index a2985ac4ec..5b430442f4 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -40,6 +40,7 @@ public: std::string config_update_url; std::string changelog_url; std::string repo_id; + std::string repo_prefix; bool templates_profile { false }; struct PrinterVariant { diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index d2b2459a5a..e09515f08c 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -23,6 +23,8 @@ set(SLIC3R_GUI_SOURCES GUI/UserAccountCommunication.hpp GUI/UserAccountSession.cpp GUI/UserAccountSession.hpp + GUI/UserAccountUtils.cpp + GUI/UserAccountUtils.hpp GUI/UserAccount.cpp GUI/UserAccount.hpp GUI/WebViewDialog.cpp diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 805d012a43..eca27a09b6 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -101,6 +101,7 @@ #include "PhysicalPrinterDialog.hpp" #include "WifiConfigDialog.hpp" #include "UserAccount.hpp" +#include "UserAccountUtils.hpp" #include "WebViewDialog.hpp" #include "LoginDialog.hpp" // IWYU pragma: keep #include "PresetArchiveDatabase.hpp" @@ -3823,14 +3824,98 @@ bool GUI_App::select_printer_preset(const Preset* preset) return is_installed; } +namespace { +const Preset* find_preset_by_nozzle_and_options( + const PrinterPresetCollection& collection + , const std::string& model_id + , const std::string& nozzle + , const std::map& options) +{ + // find all matching presets when repo prefix is ommited + std::vector results; + for (const Preset &preset : collection) { + // trim repo prefix + std::string printer_model = preset.config.opt_string("printer_model"); + std::string vendor_repo_prefix; + if (preset.vendor) { + vendor_repo_prefix = preset.vendor->repo_prefix; + } else if (std::string inherits = preset.inherits(); !inherits.empty()) { + const Preset *parent = wxGetApp().preset_bundle->printers.find_preset(inherits); + if (parent && parent->vendor) { + vendor_repo_prefix = parent->vendor->repo_prefix; + } + } + if (printer_model.find(vendor_repo_prefix) == 0) { + printer_model = printer_model.substr(vendor_repo_prefix.size() + ); + boost::trim_left(printer_model); + } + + if (!preset.is_system || printer_model != model_id) + continue; + // nozzle diameter + if (!nozzle.empty() && preset.config.has("nozzle_diameter")) { + double nozzle_diameter = static_cast(preset.config.option("nozzle_diameter"))->values[0]; + std::string nozzle_diameter_serialized = into_u8(double_to_string(nozzle_diameter)); + if (size_t pos = nozzle_diameter_serialized.find(",") != std::string::npos) { + nozzle_diameter_serialized.replace(pos, 1, 1, '.'); + } + if (nozzle != nozzle_diameter_serialized) { + continue; + } + } + // other options + bool failed = false; + for (const auto& opt : options) { + if (!preset.config.has(opt.first)) { + failed = true; + break; + } + if (preset.config.option(opt.first)->serialize() != opt.second) { + failed = true; + break; + } + } + if (failed) { + continue; + } + results.push_back(&preset); + } + // find visible without prefix + for (const Preset *preset : results) { + if (preset->is_visible && preset->config.opt_string("printer_model") == model_id) { + return preset; + } + } + // find one visible + for (const Preset *preset : results) { + if (preset->is_visible) { + return preset; + } + } + // find one without prefix + for (const Preset* preset : results) { + if (preset->config.opt_string("printer_model") == model_id) { + return preset; + } + } + if (results.size() != 0) { + return results.front(); + } + return nullptr; +} +} + bool GUI_App::select_printer_from_connect(const std::string& msg) { - // parse message - std::string model_name = plater()->get_user_account()->get_keyword_from_json(msg, "printer_model"); - std::string uuid = plater()->get_user_account()->get_keyword_from_json(msg, "uuid"); + // parse message "binary_gcode" + boost::property_tree::ptree ptree; + std::string model_name = UserAccountUtils::get_keyword_from_json(ptree, msg, "printer_model"); + std::string uuid = UserAccountUtils::get_keyword_from_json(ptree, msg, "uuid"); if (model_name.empty()) { std::vector compatible_printers; - plater()->get_user_account()->fill_supported_printer_models_from_json(msg, compatible_printers); + UserAccountUtils::fill_supported_printer_models_from_json(ptree, compatible_printers); if (!compatible_printers.empty()) { model_name = compatible_printers.front(); } @@ -3839,10 +3924,12 @@ bool GUI_App::select_printer_from_connect(const std::string& msg) BOOST_LOG_TRIVIAL(error) << "Failed to select printer from Connect. Printer_model is empty."; return false; } - std::string nozzle = plater()->get_user_account()->get_nozzle_from_json(msg); + std::string nozzle = UserAccountUtils::get_nozzle_from_json(ptree); + std::map config_options_to_match; + //UserAccountUtils::fill_config_options_from_json(ptree, config_options_to_match); BOOST_LOG_TRIVIAL(info) << "Select printer from Connect. Model: " << model_name << "nozzle: " << nozzle; // select printer - const Preset* printer_preset = preset_bundle->printers.find_system_preset_by_model_and_variant(model_name, nozzle); + const Preset* printer_preset = find_preset_by_nozzle_and_options(preset_bundle->printers, model_name, nozzle, config_options_to_match); bool is_installed = printer_preset && select_printer_preset(printer_preset); // notification std::string out = printer_preset ? @@ -3935,7 +4022,7 @@ void GUI_App::select_filament_from_connect(const std::string& msg) { // parse message std::vector materials; - plater()->get_user_account()->fill_material_from_json(msg, materials); + UserAccountUtils::fill_material_from_json(msg, materials); if (materials.empty()) { BOOST_LOG_TRIVIAL(error) << "Failed to select filament from Connect. No material data."; return; @@ -3969,7 +4056,8 @@ void GUI_App::handle_connect_request_printer_select(const std::string& msg) // Here comes code from ConnectWebViewPanel // It only contains uuid of a printer to be selected // Lets queue it and wait on result. The result is send via event to plater, where it is send to handle_connect_request_printer_select_inner - std::string uuid = plater()->get_user_account()->get_keyword_from_json(msg, "uuid"); + boost::property_tree::ptree ptree; + std::string uuid = UserAccountUtils::get_keyword_from_json(ptree, msg, "uuid"); plater()->get_user_account()->enqueue_printer_data_action(uuid); } void GUI_App::handle_connect_request_printer_select_inner(const std::string & msg) diff --git a/src/slic3r/GUI/PhysicalPrinterDialog.cpp b/src/slic3r/GUI/PhysicalPrinterDialog.cpp index 4cae18c133..10b05d62c2 100644 --- a/src/slic3r/GUI/PhysicalPrinterDialog.cpp +++ b/src/slic3r/GUI/PhysicalPrinterDialog.cpp @@ -728,9 +728,10 @@ void PhysicalPrinterDialog::update_host_type(bool printer_change) for (PresetForPrinter* prstft : m_presets) { std::string preset_name = prstft->get_preset_name(); if (Preset* preset = wxGetApp().preset_bundle->printers.find_preset(preset_name)) { - std::string model_id = preset->config.opt_string("printer_model"); + std::string model_id = preset->config.opt_string("printer_model"); if (preset->vendor) { - if (preset->vendor->name == "Prusa Research") { + // No need to remove prefix from printer_model, family is not prefixed + if (preset->vendor->name.find("Prusa Research") != std::string::npos) { const std::vector& models = preset->vendor->models; auto it = std::find_if(models.begin(), models.end(), [model_id](const VendorProfile::PrinterModel& model) { return model.id == model_id; }); @@ -754,11 +755,16 @@ void PhysicalPrinterDialog::update_host_type(bool printer_change) break; } std::string model_id = preset->config.opt_string("printer_model"); - if (preset->vendor && preset->vendor->name != "Prusa Research") { - connect.supported = false; - break; + // remove prefix from printer_model + if (preset->vendor) { + std::string vendor_repo_prefix; + vendor_repo_prefix = preset->vendor->repo_prefix; + if (model_id.find(vendor_repo_prefix) == 0) { + model_id = model_id.substr(vendor_repo_prefix.size()); + boost::trim_left(model_id); + } } - if (preset->vendor && preset->vendor->name != "Prusa Research") { + if (preset->vendor && preset->vendor->name.find("Prusa Research") == std::string::npos) { connect.supported = false; break; } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 162c8b09bf..9c70d60074 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -123,6 +123,7 @@ #include "Gizmos/GLGizmoCut.hpp" #include "FileArchiveDialog.hpp" #include "UserAccount.hpp" +#include "UserAccountUtils.hpp" #include "DesktopIntegrationDialog.hpp" #include "WebViewDialog.hpp" #include "PresetArchiveDatabase.hpp" @@ -2059,6 +2060,22 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool if (full_config.has("binary_gcode")) // needed for SLA full_config.set("binary_gcode", bool(full_config.opt_bool("binary_gcode") & wxGetApp().app_config->get_bool("use_binary_gcode_when_supported"))); + const Preset &selected_printer = wxGetApp().preset_bundle->printers.get_selected_preset(); + std::string printer_model_serialized = full_config.option("printer_model")->serialize(); + std::string vendor_repo_prefix; + if (selected_printer.vendor) { + vendor_repo_prefix = selected_printer.vendor->repo_prefix; + } else if (std::string inherits = selected_printer.inherits(); !inherits.empty()) { + const Preset *parent = wxGetApp().preset_bundle->printers.find_preset(inherits); + if (parent && parent->vendor) { + vendor_repo_prefix = parent->vendor->repo_prefix; + } + } + if (printer_model_serialized.find(vendor_repo_prefix) == 0) { + printer_model_serialized = printer_model_serialized.substr(vendor_repo_prefix.size()); + boost::trim_left(printer_model_serialized); + full_config.set("printer_model", printer_model_serialized); + } // If the update_background_process() was not called by the timer, kill the timer, // so the update_restart_background_process() will not be called again in vain. background_process_timer.Stop(); @@ -3648,7 +3665,9 @@ bool Plater::priv::can_show_upload_to_connect() const vendor_id = parent->vendor->id; } } - return vendor_id.compare(0, 5, "Prusa") == 0; + // Upload to Connect should show only for prusa printers + // Some vendors might have prefixed name due to repository id. + return vendor_id.find("Prusa") != std::string::npos; } void Plater::priv::show_action_buttons(const bool ready_to_slice_) const @@ -6022,10 +6041,11 @@ void Plater::connect_gcode() */ const Preset* selected_printer_preset = &wxGetApp().preset_bundle->printers.get_selected_preset(); - const std::string filename = p->user_account->get_keyword_from_json(dialog_msg, "filename"); - const std::string team_id = p->user_account->get_keyword_from_json(dialog_msg, "team_id"); + boost::property_tree::ptree ptree; + const std::string filename = UserAccountUtils::get_keyword_from_json(ptree, dialog_msg, "filename"); + const std::string team_id = UserAccountUtils::get_keyword_from_json(ptree, dialog_msg, "team_id"); - std::string data_subtree = p->user_account->get_print_data_from_json(dialog_msg, "data"); + std::string data_subtree = UserAccountUtils::get_print_data_from_json(dialog_msg, "data"); if (filename.empty() || team_id.empty() || data_subtree.empty()) { std::string msg = _u8L("Failed to read response from Prusa Connect server. Upload is cancelled."); BOOST_LOG_TRIVIAL(error) << msg; diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 6b3aea7f6d..ff7815a18e 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -970,7 +970,22 @@ static std::string get_connect_state_suffix_for_printer(const Preset& printer_pr !printer_state_map.empty()) { for (const auto& [printer_model_nozzle_pair, states] : printer_state_map) { - if (printer_model_nozzle_pair.first == printer_preset.config.opt_string("printer_model") + std::string printer_model = printer_preset.config.opt_string("printer_model"); + std::string vendor_repo_prefix; + if (printer_preset.vendor) { + vendor_repo_prefix = printer_preset.vendor->repo_prefix; + } else if (std::string inherits = printer_preset.inherits(); !inherits.empty()) { + const Preset *parent = wxGetApp().preset_bundle->printers.find_preset(inherits); + if (parent && parent->vendor) { + vendor_repo_prefix = parent->vendor->repo_prefix; + } + } + if (printer_model.find(vendor_repo_prefix) == 0) { + printer_model = printer_model.substr(vendor_repo_prefix.size()); + boost::trim_left(printer_model); + } + + if (printer_model_nozzle_pair.first == printer_model && printer_model_nozzle_pair.second == printer_preset.config.opt_string("printer_variant")) { PrinterStatesCount states_cnt = get_printe_states_count(states); @@ -1002,7 +1017,23 @@ static bool fill_data_to_connect_info_line( const Preset& printer_preset, !printer_state_map.empty()) { for (const auto& [printer_model_nozzle_pair, states] : printer_state_map) { - if (printer_model_nozzle_pair.first == printer_preset.config.opt_string("printer_model") + // get printer_model without repo prefix + std::string printer_model = printer_preset.config.opt_string("printer_model"); + std::string vendor_repo_prefix; + if (printer_preset.vendor) { + vendor_repo_prefix = printer_preset.vendor->repo_prefix; + } else if (std::string inherits = printer_preset.inherits(); !inherits.empty()) { + const Preset *parent = wxGetApp().preset_bundle->printers.find_preset(inherits); + if (parent && parent->vendor) { + vendor_repo_prefix = parent->vendor->repo_prefix; + } + } + if (printer_model.find(vendor_repo_prefix) == 0) { + printer_model = printer_model.substr(vendor_repo_prefix.size()); + boost::trim_left(printer_model); + } + + if (printer_model_nozzle_pair.first == printer_model && printer_model_nozzle_pair.second == printer_preset.config.opt_string("printer_variant")) { PrinterStatesCount states_cnt = get_printe_states_count(states); diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 265c89cc3c..b7bc79a59f 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -1,5 +1,6 @@ #include "UserAccount.hpp" +#include "UserAccountUtils.hpp" #include "format.hpp" #include "GUI.hpp" @@ -160,64 +161,7 @@ void UserAccount::on_communication_fail() } } -namespace { - std::string parse_tree_for_param(const pt::ptree& tree, const std::string& param) - { - for (const auto& section : tree) { - if (section.first == param) { - return section.second.data(); - } - if (std::string res = parse_tree_for_param(section.second, param); !res.empty()) { - return res; - } - } - return {}; - } - void parse_tree_for_param_vector(const pt::ptree& tree, const std::string& param, std::vector& results) - { - for (const auto& section : tree) { - if (section.first == param) { - results.emplace_back(section.second.data()); - } else { - parse_tree_for_param_vector(section.second, param, results); - } - } - } - - pt::ptree parse_tree_for_subtree(const pt::ptree& tree, const std::string& param) - { - for (const auto& section : tree) { - if (section.first == param) { - return section.second; - } - else { - if (pt::ptree res = parse_tree_for_subtree(section.second, param); !res.empty()) - return res; - } - - } - return pt::ptree(); - } - - void fill_supported_printer_models_from_json_inner(const pt::ptree& ptree, std::vector& result) { - std::string printer_model = parse_tree_for_param(ptree, "printer_model"); - if (!printer_model.empty()) { - result.emplace_back(printer_model); - } - pt::ptree out = parse_tree_for_subtree(ptree, "supported_printer_models"); - if (out.empty()) { - BOOST_LOG_TRIVIAL(error) << "Failed to find supported_printer_models in printer detail."; - return; - } - for (const auto& sub : out) { - if (printer_model != sub.second.data()) { - result.emplace_back(sub.second.data()); - } - - } - } -} bool UserAccount::on_connect_printers_success(const std::string& data, AppConfig* app_config, bool& out_printers_changed) { @@ -327,8 +271,8 @@ bool UserAccount::on_connect_uiid_map_success(const std::string& data, AppConfig return on_connect_printers_success(data, app_config, out_printers_changed); } -std::string UserAccount::get_current_printer_uuid_from_connect(const std::string& selected_printer_id) const -{ +std::string UserAccount::get_current_printer_uuid_from_connect(const std::string &selected_printer_id +) const { if (m_current_printer_data_json_from_connect.empty() || m_current_printer_uuid_from_connect.empty()) { return {}; } @@ -343,12 +287,12 @@ std::string UserAccount::get_current_printer_uuid_from_connect(const std::string return {}; } - std::string data_uuid = parse_tree_for_param(ptree, "uuid"); + std::string data_uuid = UserAccountUtils::get_keyword_from_json(ptree, "", "uuid"); assert(data_uuid == m_current_printer_uuid_from_connect); //std::string model_name = parse_tree_for_param(ptree, "printer_model"); std::vector compatible_printers; - fill_supported_printer_models_from_json_inner(ptree, compatible_printers); + UserAccountUtils::fill_supported_printer_models_from_json(ptree, compatible_printers); if (compatible_printers.empty()) { return {}; } @@ -356,173 +300,4 @@ std::string UserAccount::get_current_printer_uuid_from_connect(const std::string return std::find(compatible_printers.begin(), compatible_printers.end(), selected_printer_id) == compatible_printers.end() ? "" : m_current_printer_uuid_from_connect; } - -std::string UserAccount::get_nozzle_from_json(const std::string& message) const -{ - std::string out; - try { - std::stringstream ss(message); - pt::ptree ptree; - pt::read_json(ss, ptree); - - out = parse_tree_for_param(ptree, "nozzle_diameter"); - //assert(!out.empty()); - } - catch (const std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); - } - - // Get rid of trailing zeros. - // This is because somtimes we get "nozzle_diameter":0.40000000000000002 - // This will return wrong result for f.e. 0.05. But we dont have such profiles right now. - if (size_t fist_dot = out.find('.'); fist_dot != std::string::npos) { - if (size_t first_zero = out.find('0', fist_dot); first_zero != std::string::npos) { - return out.substr(0, first_zero); - } - } - return out; -} - -std::string UserAccount::get_keyword_from_json(const std::string& json, const std::string& keyword) const -{ - std::string out; - try { - std::stringstream ss(json); - pt::ptree ptree; - pt::read_json(ss, ptree); - - out = parse_tree_for_param(ptree, keyword); - //assert(!out.empty()); - } - catch (const std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); - } - return out; -} - -std::string UserAccount::get_print_data_from_json(const std::string &json, const std::string &keyword) const -{ - // copy subtree string f.e. - // { "": {"param1": "something", "filename":"abcd.gcode", "param3":true}, "something_else" : 0 } - // into: {"param1": "something", "filename":"%1%", "param3":true, "size":%2%} - // yes there will be 2 placeholders for later format - - // this will fail if not flat subtree - size_t start_of_keyword = json.find("\""+keyword+"\""); - if (start_of_keyword == std::string::npos) - return {}; - size_t start_of_sub = json.find('{', start_of_keyword); - if (start_of_sub == std::string::npos) - return {}; - size_t end_of_sub = json.find('}', start_of_sub); - if (end_of_sub == std::string::npos) - return {}; - size_t start_of_filename = json.find("\"filename\"", start_of_sub); - if (start_of_filename == std::string::npos) - return {}; - size_t filename_doubledot = json.find(':', start_of_filename); - if (filename_doubledot == std::string::npos) - return {}; - size_t start_of_filename_data = json.find('\"', filename_doubledot); - if (start_of_filename_data == std::string::npos) - return {}; - size_t end_of_filename_data = json.find('\"', start_of_filename_data + 1); - if (end_of_filename_data == std::string::npos) - return {}; - size_t size = json.size(); - std::string result = json.substr(start_of_sub, start_of_filename_data - start_of_sub + 1); - result += "%1%"; - result += json.substr(end_of_filename_data, end_of_sub - end_of_filename_data); - result += ",\"size\":%2%}"; - return result; -} - -void UserAccount::fill_supported_printer_models_from_json(const std::string& json, std::vector& result) const -{ - try { - std::stringstream ss(json); - pt::ptree ptree; - pt::read_json(ss, ptree); - - fill_supported_printer_models_from_json_inner(ptree, result); - } - catch (const std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); - } -} - -void UserAccount::fill_material_from_json(const std::string& json, std::vector& result) const -{ - - /* option 1: - "slot": { - "active": 2, - "slots": { - "1": { - "material": "PLA", - "temp": 170, - "fan_hotend": 7689, - "fan_print": 0 - }, - "2": { - "material": "PLA", - "temp": 225, - "fan_hotend": 7798, - "fan_print": 6503 - }, - "3": { - "material": "PLA", - "temp": 36, - "fan_hotend": 6636, - "fan_print": 0 - }, - "4": { - "material": "PLA", - "temp": 35, - "fan_hotend": 0, - "fan_print": 0 - }, - "5": { - "material": "PETG", - "temp": 136, - "fan_hotend": 8132, - "fan_print": 0 - } - } - } - */ - /* option 2 - "filament": { - "material": "PLA", - "bed_temperature": 60, - "nozzle_temperature": 210 - } - */ - // try finding "slot" subtree a use it to - // if not found, find "filament" subtree - try { - std::stringstream ss(json); - pt::ptree ptree; - pt::read_json(ss, ptree); - // find "slot" subtree - pt::ptree slot_subtree = parse_tree_for_subtree(ptree, "slot"); - if (slot_subtree.empty()) { - // if not found, find "filament" subtree - pt::ptree filament_subtree = parse_tree_for_subtree(ptree, "filament"); - if (!filament_subtree.empty()) { - std::string material = parse_tree_for_param(filament_subtree, "material"); - if (!material.empty()) { - result.emplace_back(std::move(material)); - } - } - return; - } - // search "slot" subtree for all "material"s - parse_tree_for_param_vector(slot_subtree, "material", result); - } - catch (const std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); - } -} - }} // namespace slic3r::GUI \ No newline at end of file diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index d241f778be..e38efdd02c 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -67,13 +67,6 @@ public: const ConnectPrinterStateMap& get_printer_state_map() const { return m_printer_map; } boost::filesystem::path get_avatar_path(bool logged) const; - // standalone utility methods - std::string get_nozzle_from_json(const std::string& message) const; - std::string get_keyword_from_json(const std::string& json, const std::string& keyword) const; - std::string get_print_data_from_json(const std::string &json, const std::string &keyword) const; - void fill_supported_printer_models_from_json(const std::string& json, std::vector& result) const; - void fill_material_from_json(const std::string& json, std::vector& result) const; - const std::map& get_printer_state_table() const { return printer_state_table; } void set_current_printer_uuid_from_connect(const std::string& uuid) { m_current_printer_uuid_from_connect = uuid; } diff --git a/src/slic3r/GUI/UserAccountUtils.cpp b/src/slic3r/GUI/UserAccountUtils.cpp new file mode 100644 index 0000000000..07c56065e8 --- /dev/null +++ b/src/slic3r/GUI/UserAccountUtils.cpp @@ -0,0 +1,222 @@ +#include "UserAccountUtils.hpp" + +#include "format.hpp" + +#include +#include +#include + +namespace pt = boost::property_tree; + +namespace Slic3r { namespace GUI { namespace UserAccountUtils { + +namespace { +std::string parse_tree_for_param(const pt::ptree &tree, const std::string ¶m) { + for (const auto §ion : tree) { + if (section.first == param) { + return section.second.data(); + } + if (std::string res = parse_tree_for_param(section.second, param); !res.empty()) { + return res; + } + } + return {}; +} + +void parse_tree_for_param_vector( + const pt::ptree &tree, const std::string ¶m, std::vector &results +) { + for (const auto §ion : tree) { + if (section.first == param) { + results.emplace_back(section.second.data()); + } else { + parse_tree_for_param_vector(section.second, param, results); + } + } +} + +pt::ptree parse_tree_for_subtree(const pt::ptree &tree, const std::string ¶m) { + for (const auto §ion : tree) { + if (section.first == param) { + return section.second; + } else { + if (pt::ptree res = parse_tree_for_subtree(section.second, param); !res.empty()) + return res; + } + } + return pt::ptree(); +} + +void json_to_ptree(boost::property_tree::ptree &ptree, const std::string &json) { + try { + std::stringstream ss(json); + pt::read_json(ss, ptree); + } catch (const std::exception &e) { + BOOST_LOG_TRIVIAL(error) << "Failed to parse json to ptree. " << e.what(); + BOOST_LOG_TRIVIAL(error) << "json: " << json; + } +} + +} // namespace + +std::string get_nozzle_from_json(boost::property_tree::ptree &ptree) { + assert(!ptree.empty()); + + std::string out = parse_tree_for_param(ptree, "nozzle_diameter"); + // Get rid of trailing zeros. + // This is because somtimes we get "nozzle_diameter":0.40000000000000002 + // This will return wrong result for f.e. 0.05. But we dont have such profiles right now. + if (size_t fist_dot = out.find('.'); fist_dot != std::string::npos) { + if (size_t first_zero = out.find('0', fist_dot); first_zero != std::string::npos) { + return out.substr(0, first_zero); + } + } + return out; +} + +std::string get_keyword_from_json(boost::property_tree::ptree &ptree, const std::string &json, const std::string &keyword ) +{ + if (ptree.empty()) { + json_to_ptree(ptree, json); + } + assert(!ptree.empty()); + return parse_tree_for_param(ptree, keyword); +} + +void fill_supported_printer_models_from_json(boost::property_tree::ptree &ptree, std::vector &result) +{ + assert(!ptree.empty()); + std::string printer_model = parse_tree_for_param(ptree, "printer_model"); + if (!printer_model.empty()) { + result.emplace_back(printer_model); + } + pt::ptree out = parse_tree_for_subtree(ptree, "supported_printer_models"); + if (out.empty()) { + BOOST_LOG_TRIVIAL(error) << "Failed to find supported_printer_models in printer detail."; + return; + } + for (const auto &sub : out) { + if (printer_model != sub.second.data()) { + result.emplace_back(sub.second.data()); + } + } +} + +void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map& result) +{ + assert(!ptree.empty()); + pt::ptree subtree = parse_tree_for_subtree(ptree, "config_options"); + for (const auto &item : subtree) { + result[item.first] = item.second.data(); + } +} + +void fill_material_from_json(const std::string &json, std::vector &result) +{ + pt::ptree ptree; + json_to_ptree(ptree, json); + assert(!ptree.empty()); + + /* option 1: + "slot": { + "active": 2, + "slots": { + "1": { + "material": "PLA", + "temp": 170, + "fan_hotend": 7689, + "fan_print": 0 + }, + "2": { + "material": "PLA", + "temp": 225, + "fan_hotend": 7798, + "fan_print": 6503 + }, + "3": { + "material": "PLA", + "temp": 36, + "fan_hotend": 6636, + "fan_print": 0 + }, + "4": { + "material": "PLA", + "temp": 35, + "fan_hotend": 0, + "fan_print": 0 + }, + "5": { + "material": "PETG", + "temp": 136, + "fan_hotend": 8132, + "fan_print": 0 + } + } + } + */ + /* option 2 + "filament": { + "material": "PLA", + "bed_temperature": 60, + "nozzle_temperature": 210 + } + */ + // try finding "slot" subtree a use it to + // if not found, find "filament" subtree + + // find "slot" subtree + pt::ptree slot_subtree = parse_tree_for_subtree(ptree, "slot"); + if (slot_subtree.empty()) { + // if not found, find "filament" subtree + pt::ptree filament_subtree = parse_tree_for_subtree(ptree, "filament"); + if (!filament_subtree.empty()) { + std::string material = parse_tree_for_param(filament_subtree, "material"); + if (!material.empty()) { + result.emplace_back(std::move(material)); + } + } + return; + } + // search "slot" subtree for all "material"s + parse_tree_for_param_vector(slot_subtree, "material", result); +} + +std::string get_print_data_from_json(const std::string &json, const std::string &keyword) { + // copy subtree string f.e. + // { "": {"param1": "something", "filename":"abcd.gcode", "param3":true}, + // "something_else" : 0 } into: {"param1": "something", "filename":"%1%", "param3":true, + // "size":%2%} yes there will be 2 placeholders for later format + + // this will fail if not flat subtree + size_t start_of_keyword = json.find("\"" + keyword + "\""); + if (start_of_keyword == std::string::npos) + return {}; + size_t start_of_sub = json.find('{', start_of_keyword); + if (start_of_sub == std::string::npos) + return {}; + size_t end_of_sub = json.find('}', start_of_sub); + if (end_of_sub == std::string::npos) + return {}; + size_t start_of_filename = json.find("\"filename\"", start_of_sub); + if (start_of_filename == std::string::npos) + return {}; + size_t filename_doubledot = json.find(':', start_of_filename); + if (filename_doubledot == std::string::npos) + return {}; + size_t start_of_filename_data = json.find('\"', filename_doubledot); + if (start_of_filename_data == std::string::npos) + return {}; + size_t end_of_filename_data = json.find('\"', start_of_filename_data + 1); + if (end_of_filename_data == std::string::npos) + return {}; + size_t size = json.size(); + std::string result = json.substr(start_of_sub, start_of_filename_data - start_of_sub + 1); + result += "%1%"; + result += json.substr(end_of_filename_data, end_of_sub - end_of_filename_data); + result += ",\"size\":%2%}"; + return result; +} + +}}} // Slic3r::GUI::UserAccountUtils + + diff --git a/src/slic3r/GUI/UserAccountUtils.hpp b/src/slic3r/GUI/UserAccountUtils.hpp new file mode 100644 index 0000000000..cfecaaa2f6 --- /dev/null +++ b/src/slic3r/GUI/UserAccountUtils.hpp @@ -0,0 +1,27 @@ +#ifndef slic3r_UserAccountUtils_hpp_ +#define slic3r_UserAccountUtils_hpp_ + +#include +#include + +#include + +namespace Slic3r { namespace GUI { +namespace UserAccountUtils { + +// If ptree parameter is empty, json parameter needs to contain data and ptree is filled. +// If ptree is non-epty, json parameter is not used. +std::string get_keyword_from_json(boost::property_tree::ptree& ptree, const std::string& json, const std::string& keyword); +// Only ptree is passed since these functions are called on places that already has the ptree from get_keyword_from_json call +std::string get_nozzle_from_json(boost::property_tree::ptree &ptree); +void fill_supported_printer_models_from_json(boost::property_tree::ptree& ptree, std::vector& result); +void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map& result); + +// Since fill_material_from_json is called only from one place where ptree doesnt need to be shared, it is not always read from json. +void fill_material_from_json(const std::string& json, std::vector& result); + +std::string get_print_data_from_json(const std::string &json, const std::string &keyword); + +}}} // Slic3r::GUI::UserAccountUtils + +#endif // slic3r_UserAccountUtils_hpp_ \ No newline at end of file diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index cc2fe608b2..a0114a2474 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -1274,22 +1274,41 @@ void PrinterPickWebViewDialog::on_connect_action_webapp_ready(const std::string& } } -void PrinterPickWebViewDialog::request_compatible_printers_FFF() -{ - //PrinterParams: { - //material: Material; - //nozzleDiameter: number; - //printerType: string; - //filename: string; - //} - const Preset& selected_printer = wxGetApp().preset_bundle->printers.get_selected_preset(); - const Preset& selected_filament = wxGetApp().preset_bundle->filaments.get_selected_preset(); - double nozzle_diameter = static_cast(selected_printer.config.option("nozzle_diameter"))->values[0]; +void PrinterPickWebViewDialog::request_compatible_printers_FFF() { + // PrinterParams: { + // material: Material; + // nozzleDiameter: number; + // printerType: string; + // filename: string; + // } + const Preset &selected_printer = wxGetApp().preset_bundle->printers.get_selected_preset(); + const Preset &selected_filament = wxGetApp().preset_bundle->filaments.get_selected_preset(); + double nozzle_diameter = static_cast( + selected_printer.config.option("nozzle_diameter") + ) + ->values[0]; wxString nozzle_diameter_serialized = double_to_string(nozzle_diameter); nozzle_diameter_serialized.Replace(L",", L"."); // Sending only first filament type for now. This should change to array of values - const std::string filament_type_serialized = selected_filament.config.option("filament_type")->serialize(); - const std::string printer_model_serialized = selected_printer.config.option("printer_model")->serialize(); + const std::string filament_type_serialized = selected_filament.config.option("filament_type") + ->serialize(); + std::string printer_model_serialized = selected_printer.config.option("printer_model") + ->serialize(); + + std::string vendor_repo_prefix; + if (selected_printer.vendor) { + vendor_repo_prefix = selected_printer.vendor->repo_prefix; + } else if (std::string inherits = selected_printer.inherits(); !inherits.empty()) { + const Preset *parent = wxGetApp().preset_bundle->printers.find_preset(inherits); + if (parent && parent->vendor) { + vendor_repo_prefix = parent->vendor->repo_prefix; + } + } + if (printer_model_serialized.find(vendor_repo_prefix) == 0) { + printer_model_serialized = printer_model_serialized.substr(vendor_repo_prefix.size()); + boost::trim_left(printer_model_serialized); + } + const std::string uuid = wxGetApp().plater()->get_user_account()->get_current_printer_uuid_from_connect(printer_model_serialized); const std::string filename = wxGetApp().plater()->get_upload_filename(); const std::string request = GUI::format( @@ -1307,7 +1326,21 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() void PrinterPickWebViewDialog::request_compatible_printers_SLA() { const Preset& selected_printer = wxGetApp().preset_bundle->printers.get_selected_preset(); - const std::string printer_model_serialized = selected_printer.config.option("printer_model")->serialize(); + std::string printer_model_serialized = selected_printer.config.option("printer_model")->serialize(); + + std::string vendor_repo_prefix; + if (selected_printer.vendor) { + vendor_repo_prefix = selected_printer.vendor->repo_prefix; + } else if (std::string inherits = selected_printer.inherits(); !inherits.empty()) { + const Preset *parent = wxGetApp().preset_bundle->printers.find_preset(inherits); + if (parent && parent->vendor) { + vendor_repo_prefix = parent->vendor->repo_prefix; + } + } + if (printer_model_serialized.find(vendor_repo_prefix) == 0) { + printer_model_serialized = printer_model_serialized.substr(vendor_repo_prefix.size()); + boost::trim_left(printer_model_serialized); + } const Preset& selected_material = wxGetApp().preset_bundle->sla_materials.get_selected_preset(); const std::string material_type_serialized = selected_material.config.option("material_type")->serialize(); const std::string uuid = wxGetApp().plater()->get_user_account()->get_current_printer_uuid_from_connect(printer_model_serialized); From ef3d323102728e6ceb7b395de8a1dccadf1e8c8c Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 17 Jul 2024 16:08:35 +0200 Subject: [PATCH 02/16] Select printer from connect by nozzle diameter (instead of pritner_variant) and by additional config options. + Moved standalone functions to UserAccountUtils --- src/slic3r/GUI/GUI_App.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index eca27a09b6..046f1c2f42 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3926,7 +3926,7 @@ bool GUI_App::select_printer_from_connect(const std::string& msg) } std::string nozzle = UserAccountUtils::get_nozzle_from_json(ptree); std::map config_options_to_match; - //UserAccountUtils::fill_config_options_from_json(ptree, config_options_to_match); + UserAccountUtils::fill_config_options_from_json(ptree, config_options_to_match); BOOST_LOG_TRIVIAL(info) << "Select printer from Connect. Model: " << model_name << "nozzle: " << nozzle; // select printer const Preset* printer_preset = find_preset_by_nozzle_and_options(preset_bundle->printers, model_name, nozzle, config_options_to_match); From d384c5a13ffd21349645b6bffbc70effb84538fc Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 17 Jul 2024 17:01:54 +0200 Subject: [PATCH 03/16] Copy all printer config options to outcoming json for selecting printer. --- src/slic3r/GUI/WebViewDialog.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index a0114a2474..f0ba87d935 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -1311,14 +1311,27 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() { const std::string uuid = wxGetApp().plater()->get_user_account()->get_current_printer_uuid_from_connect(printer_model_serialized); const std::string filename = wxGetApp().plater()->get_upload_filename(); - const std::string request = GUI::format( + std::string request = GUI::format( "{" "\"printerUuid\": \"%4%\", " "\"printerModel\": \"%3%\", " "\"nozzleDiameter\": %2%, " "\"material\": \"%1%\", " - "\"filename\": \"%5%\" " - "}", filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized, uuid, filename); + "\"filename\": \"%5%\", " + "\"config_options\": {" + , filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized, uuid, filename); + + // std::map>::const_iterator + for (auto it = selected_printer.config.cbegin(); it != selected_printer.config.cend(); ++it) { + std::string value = selected_printer.config.option(it->first)->serialize(); + if (value.find('\"') != std::string::npos) { + continue; + } + request += it == selected_printer.config.cbegin() ? "" : ","; + request += GUI::format("\"%1%\": \"%2%\"", it->first, value); + } + + request += "}}"; wxString script = GUI::format_wxstr("window._prusaConnect_v1.requestCompatiblePrinter(%1%)", request); run_script(script); From 66b8144f3f05a5d24ee0d03d3cf9d5fc0bf62a36 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 18 Jul 2024 15:33:16 +0200 Subject: [PATCH 04/16] Added nozzle_high_flow, nozzle_high_temperature, filament_abrasive. Updated version of libbgcode. --- deps/+LibBGCode/LibBGCode.cmake | 4 ++-- src/libslic3r/GCode.cpp | 4 ++-- src/libslic3r/Preset.cpp | 5 +++-- src/libslic3r/Print.cpp | 3 +++ src/libslic3r/PrintConfig.cpp | 20 +++++++++++++++++++- src/libslic3r/PrintConfig.hpp | 3 +++ src/slic3r/GUI/Tab.cpp | 7 ++++++- 7 files changed, 38 insertions(+), 8 deletions(-) diff --git a/deps/+LibBGCode/LibBGCode.cmake b/deps/+LibBGCode/LibBGCode.cmake index 484c0748fa..2a43a8ea06 100644 --- a/deps/+LibBGCode/LibBGCode.cmake +++ b/deps/+LibBGCode/LibBGCode.cmake @@ -1,8 +1,8 @@ set(LibBGCode_SOURCE_DIR "" CACHE PATH "Optionally specify local LibBGCode source directory") set(_source_dir_line - URL https://github.com/prusa3d/libbgcode/archive/8ae75bd0eea622f0e34cae311b3bd065b55eae9b.zip - URL_HASH SHA256=141a8cea3baea6066527389fda734057181414c4fa296d34501ef8f69ea412e9) + URL https://github.com/prusa3d/libbgcode/archive/a21254e7043b9a9e8f1c89a1d702912b36ad3d4c.zip + URL_HASH SHA256=4ce42e5b3129e3cb976d19c7c14ec8c708758297b27908b62657a57ac07e7fb5) if (LibBGCode_SOURCE_DIR) set(_source_dir_line "SOURCE_DIR;${LibBGCode_SOURCE_DIR};BUILD_ALWAYS;ON") diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index c310d419fd..8d42f03db2 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -957,8 +957,8 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail // printer data - this section contains duplicates from the slicer metadata // that we just created. Find and copy the entries that we want to duplicate. const auto& slicer_metadata = binary_data.slicer_metadata.raw_data; - const std::vector keys_to_duplicate = { "printer_model", "filament_type", "nozzle_diameter", "bed_temperature", - "brim_width", "fill_density", "layer_height", "temperature", "ironing", "support_material", "extruder_colour" }; + const std::vector keys_to_duplicate = { "printer_model", "filament_type", "filament_abrasive", "nozzle_diameter", "nozzle_high_flow", "nozzle_high_temperature", "bed_temperature", + "brim_width", "fill_density", "layer_height", "temperature", "ironing", "support_material", "extruder_colour"}; assert(std::is_sorted(slicer_metadata.begin(), slicer_metadata.end(), [](const auto& a, const auto& b) { return a.first < b.first; })); for (const std::string& key : keys_to_duplicate) { diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 0f1b6cef61..54285ff25b 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -493,7 +493,7 @@ static std::vector s_Preset_print_options { }; static std::vector s_Preset_filament_options { - "filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_notes", "filament_max_volumetric_speed", "filament_infill_max_speed", "filament_infill_max_crossing_speed", + "filament_colour", "filament_diameter", "filament_type", "filament_soluble", "filament_abrasive", "filament_notes", "filament_max_volumetric_speed", "filament_infill_max_speed", "filament_infill_max_crossing_speed", "extrusion_multiplier", "filament_density", "filament_cost", "filament_spool_weight", "filament_loading_speed", "filament_loading_speed_start", "filament_load_time", "filament_unloading_speed", "filament_unloading_speed_start", "filament_unload_time", "filament_toolchange_delay", "filament_cooling_moves", "filament_stamping_loading_speed", "filament_stamping_distance", "filament_cooling_initial_speed", "filament_purge_multiplier", "filament_cooling_final_speed", "filament_ramming_parameters", "filament_minimal_purge_on_wipe_tower", @@ -532,7 +532,8 @@ static std::vector s_Preset_printer_options { "cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "multimaterial_purging", "max_print_height", "default_print_profile", "inherits", "remaining_times", "silent_mode", - "machine_limits_usage", "thumbnails", "thumbnails_format" + "machine_limits_usage", "thumbnails", "thumbnails_format", + "nozzle_high_flow", "nozzle_high_temperature", }; static std::vector s_Preset_sla_print_options { diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index cd358951b7..7bba2ea5ee 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -114,6 +114,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "fan_always_on", "fan_below_layer_time", "full_fan_speed_layer", + "filament_abrasive", "filament_colour", "filament_diameter", "filament_density", @@ -126,6 +127,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "first_layer_speed_over_raft", "gcode_comments", "gcode_label_objects", + "nozzle_high_flow", + "nozzle_high_temperature", "infill_acceleration", "layer_gcode", "min_fan_speed", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index a22656ae46..58d8e722a3 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1370,6 +1370,12 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionBools { false }); + def = this->add("filament_abrasive", coBools); + def->label = L("Abrasive material"); + def->tooltip = L("TODO"); + def->mode = comExpert; + def->set_default_value(new ConfigOptionBools { false }); + def = this->add("filament_cost", coFloats); def->label = L("Cost"); def->tooltip = L("Enter your filament cost per kg here. This is only for statistical information."); @@ -2550,6 +2556,18 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionBools{false}); + def = this->add("nozzle_high_flow", coBools); + def->label = L("High flow nozzle"); + def->tooltip = L("TODO"); + def->mode = comExpert; + def->set_default_value(new ConfigOptionBools{false}); + + def = this->add("nozzle_high_temperature", coBools); + def->label = L("High temperature nozzle"); + def->tooltip = L("TODO"); + def->mode = comExpert; + def->set_default_value(new ConfigOptionBools{false}); + def = this->add("retract_lift", coFloats); def->label = L("Lift height"); def->tooltip = L("Lift height applied before travel."); @@ -3715,7 +3733,7 @@ void PrintConfigDef::init_extruder_option_keys() "retract_before_wipe", "retract_restart_extra", "retract_before_travel", "wipe", "travel_slope", "travel_max_lift", "travel_ramping_lift", "travel_lift_before_obstacle", "retract_layer_change", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour", - "default_filament_profile" + "default_filament_profile", "nozzle_high_flow", "nozzle_high_temperature" }; m_extruder_retract_keys = { diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index e3769e4313..0a82f5e9c2 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -782,6 +782,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloats, filament_density)) ((ConfigOptionStrings, filament_type)) ((ConfigOptionBools, filament_soluble)) + ((ConfigOptionBools, filament_abrasive)) ((ConfigOptionFloats, filament_cost)) ((ConfigOptionFloats, filament_spool_weight)) ((ConfigOptionFloats, filament_max_volumetric_speed)) @@ -825,6 +826,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloats, travel_max_lift)) ((ConfigOptionFloats, travel_slope)) ((ConfigOptionBools, travel_lift_before_obstacle)) + ((ConfigOptionBools, nozzle_high_flow)) + ((ConfigOptionBools, nozzle_high_temperature)) ((ConfigOptionPercents, retract_before_wipe)) ((ConfigOptionFloats, retract_length)) ((ConfigOptionFloats, retract_length_toolchange)) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index c68c7128fc..aa35aa9590 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2227,6 +2227,7 @@ void TabFilament::build() option.opt.width = Field::def_width(); optgroup->append_single_option_line(option); optgroup->append_single_option_line("filament_soluble"); + optgroup->append_single_option_line("filament_abrasive"); optgroup = page->new_optgroup(L("Print speed override")); optgroup->append_single_option_line("filament_max_volumetric_speed", "max-volumetric-speed_127176"); @@ -3132,7 +3133,7 @@ const std::vector extruder_options = { "retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", "retract_restart_extra", "retract_before_travel", "retract_layer_change", "wipe", "retract_before_wipe", "travel_ramping_lift", - "travel_slope", "travel_max_lift", "travel_lift_before_obstacle", + "travel_slope", "travel_max_lift", "travel_lift_before_obstacle", "nozzle_high_flow", "nozzle_high_temperature", "retract_length_toolchange", "retract_restart_extra_toolchange", }; @@ -3195,6 +3196,10 @@ void TabPrinter::build_extruder_pages(size_t n_before_extruders) update(); }; + optgroup->append_single_option_line("nozzle_high_flow", "", extruder_idx); + optgroup->append_single_option_line("nozzle_high_temperature", "", extruder_idx); + + optgroup = page->new_optgroup(L("Preview")); auto reset_to_filament_color = [this, extruder_idx](wxWindow*parent) { From 3ff2b179b9e5fdf2a4340b93bc057dc73625fe5b Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 22 Jul 2024 09:27:07 +0200 Subject: [PATCH 05/16] filament abrasive option in outgoing json for upload to connect --- src/slic3r/GUI/WebViewDialog.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index f0ba87d935..0b33acdce5 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -1311,6 +1311,8 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() { const std::string uuid = wxGetApp().plater()->get_user_account()->get_current_printer_uuid_from_connect(printer_model_serialized); const std::string filename = wxGetApp().plater()->get_upload_filename(); + //filament_abrasive + const std::string filament_abrasive = selected_filament.config.option("filament_abrasive")->serialize(); std::string request = GUI::format( "{" "\"printerUuid\": \"%4%\", " @@ -1318,8 +1320,9 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() { "\"nozzleDiameter\": %2%, " "\"material\": \"%1%\", " "\"filename\": \"%5%\", " + "\"filamentAbrasive\": \"%6%\", " "\"config_options\": {" - , filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized, uuid, filename); + , filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized, uuid, filename, filament_abrasive); // std::map>::const_iterator for (auto it = selected_printer.config.cbegin(); it != selected_printer.config.cend(); ++it) { From a30961f59ae5a1bd85359f79f147cdcd9eac0472 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 29 Jul 2024 17:08:26 +0200 Subject: [PATCH 06/16] Rename paramters in jsons and add FilamentConfig. --- src/slic3r/GUI/UserAccountUtils.cpp | 2 +- src/slic3r/GUI/WebViewDialog.cpp | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/UserAccountUtils.cpp b/src/slic3r/GUI/UserAccountUtils.cpp index 07c56065e8..84c6483ed5 100644 --- a/src/slic3r/GUI/UserAccountUtils.cpp +++ b/src/slic3r/GUI/UserAccountUtils.cpp @@ -105,7 +105,7 @@ void fill_supported_printer_models_from_json(boost::property_tree::ptree &ptree, void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map& result) { assert(!ptree.empty()); - pt::ptree subtree = parse_tree_for_subtree(ptree, "config_options"); + pt::ptree subtree = parse_tree_for_subtree(ptree, "printerConfig"); for (const auto &item : subtree) { result[item.first] = item.second.data(); } diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 0b33acdce5..cd2aa66bf9 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -1320,9 +1320,9 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() { "\"nozzleDiameter\": %2%, " "\"material\": \"%1%\", " "\"filename\": \"%5%\", " - "\"filamentAbrasive\": \"%6%\", " - "\"config_options\": {" - , filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized, uuid, filename, filament_abrasive); + //"\"filamentAbrasive\": \"%6%\", " + "\"printerConfig\": {" + , filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized, uuid, filename/*, filament_abrasive*/); // std::map>::const_iterator for (auto it = selected_printer.config.cbegin(); it != selected_printer.config.cend(); ++it) { @@ -1334,6 +1334,16 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() { request += GUI::format("\"%1%\": \"%2%\"", it->first, value); } + request += "}, \"filamentConfig\": {"; + for (auto it = selected_filament.config.cbegin(); it != selected_filament.config.cend(); ++it) { + std::string value = selected_filament.config.option(it->first)->serialize(); + if (value.find('\"') != std::string::npos) { + continue; + } + request += it == selected_filament.config.cbegin() ? "" : ","; + request += GUI::format("\"%1%\": \"%2%\"", it->first, value); + } + request += "}}"; wxString script = GUI::format_wxstr("window._prusaConnect_v1.requestCompatiblePrinter(%1%)", request); From a627c4c64ed5288641ee35bb4f313e2c6ad55bce Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 30 Jul 2024 09:56:38 +0200 Subject: [PATCH 07/16] full config in json for upload --- src/slic3r/GUI/WebViewDialog.cpp | 41 ++++++++------------------------ 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index cd2aa66bf9..30f93c7477 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -1282,18 +1282,13 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() { // filename: string; // } const Preset &selected_printer = wxGetApp().preset_bundle->printers.get_selected_preset(); - const Preset &selected_filament = wxGetApp().preset_bundle->filaments.get_selected_preset(); - double nozzle_diameter = static_cast( - selected_printer.config.option("nozzle_diameter") - ) - ->values[0]; + const DynamicPrintConfig full_config = wxGetApp().preset_bundle->full_config(); + double nozzle_diameter = static_cast(full_config.option("nozzle_diameter"))->values[0]; wxString nozzle_diameter_serialized = double_to_string(nozzle_diameter); nozzle_diameter_serialized.Replace(L",", L"."); // Sending only first filament type for now. This should change to array of values - const std::string filament_type_serialized = selected_filament.config.option("filament_type") - ->serialize(); - std::string printer_model_serialized = selected_printer.config.option("printer_model") - ->serialize(); + const std::string filament_type_serialized = full_config.option("filament_type")->serialize(); + std::string printer_model_serialized = full_config.option("printer_model")->serialize(); std::string vendor_repo_prefix; if (selected_printer.vendor) { @@ -1312,7 +1307,6 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() { const std::string uuid = wxGetApp().plater()->get_user_account()->get_current_printer_uuid_from_connect(printer_model_serialized); const std::string filename = wxGetApp().plater()->get_upload_filename(); //filament_abrasive - const std::string filament_abrasive = selected_filament.config.option("filament_abrasive")->serialize(); std::string request = GUI::format( "{" "\"printerUuid\": \"%4%\", " @@ -1320,30 +1314,15 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() { "\"nozzleDiameter\": %2%, " "\"material\": \"%1%\", " "\"filename\": \"%5%\", " - //"\"filamentAbrasive\": \"%6%\", " - "\"printerConfig\": {" - , filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized, uuid, filename/*, filament_abrasive*/); + "\"fullConfig\": {" + , filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized, uuid, filename); - // std::map>::const_iterator - for (auto it = selected_printer.config.cbegin(); it != selected_printer.config.cend(); ++it) { - std::string value = selected_printer.config.option(it->first)->serialize(); - if (value.find('\"') != std::string::npos) { - continue; - } - request += it == selected_printer.config.cbegin() ? "" : ","; + for (auto it = full_config.cbegin(); it != full_config.cend(); ++it) { + std::string value = full_config.option(it->first)->serialize(); + boost::algorithm::replace_all(value, "\"", "\\\""); + request += it == full_config.cbegin() ? "" : ","; request += GUI::format("\"%1%\": \"%2%\"", it->first, value); } - - request += "}, \"filamentConfig\": {"; - for (auto it = selected_filament.config.cbegin(); it != selected_filament.config.cend(); ++it) { - std::string value = selected_filament.config.option(it->first)->serialize(); - if (value.find('\"') != std::string::npos) { - continue; - } - request += it == selected_filament.config.cbegin() ? "" : ","; - request += GUI::format("\"%1%\": \"%2%\"", it->first, value); - } - request += "}}"; wxString script = GUI::format_wxstr("window._prusaConnect_v1.requestCompatiblePrinter(%1%)", request); From eb7f27c83d54ed5094c45a9595262785c3b311f9 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 8 Aug 2024 10:58:52 +0200 Subject: [PATCH 08/16] Serialize parameters from json var to config opt format improved config options filtering changed outgoing json for upload to connect --- src/slic3r/GUI/GUI_App.cpp | 71 ++++++++++------- src/slic3r/GUI/UserAccountUtils.cpp | 116 ++++++++++++++++++++++++---- src/slic3r/GUI/UserAccountUtils.hpp | 2 +- src/slic3r/GUI/WebViewDialog.cpp | 20 ++--- 4 files changed, 154 insertions(+), 55 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 046f1c2f42..5cf38043a0 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3828,9 +3828,7 @@ namespace { const Preset* find_preset_by_nozzle_and_options( const PrinterPresetCollection& collection , const std::string& model_id - , const std::string& nozzle - , const std::map& options) + , std::map>& options) { // find all matching presets when repo prefix is ommited std::vector results; @@ -3854,33 +3852,39 @@ const Preset* find_preset_by_nozzle_and_options( if (!preset.is_system || printer_model != model_id) continue; - // nozzle diameter - if (!nozzle.empty() && preset.config.has("nozzle_diameter")) { - double nozzle_diameter = static_cast(preset.config.option("nozzle_diameter"))->values[0]; - std::string nozzle_diameter_serialized = into_u8(double_to_string(nozzle_diameter)); - if (size_t pos = nozzle_diameter_serialized.find(",") != std::string::npos) { - nozzle_diameter_serialized.replace(pos, 1, 1, '.'); - } - if (nozzle != nozzle_diameter_serialized) { - continue; - } - } - // other options + // options (including nozzle_diameter) bool failed = false; for (const auto& opt : options) { - if (!preset.config.has(opt.first)) { - failed = true; - break; + assert(preset.config.has(opt.first)); + // We compare only first value now, but options contains data for all (some might be empty tho) + std::string opt_val; + if (preset.config.option(opt.first)->is_scalar()) { + opt_val = preset.config.option(opt.first)->serialize(); + } else { + switch (preset.config.option(opt.first)->type()) { + case coInts: opt_val = std::to_string(static_cast(preset.config.option(opt.first))->values[0]); break; + case coFloats: + opt_val = into_u8(double_to_string(static_cast(preset.config.option(opt.first))->values[0])); + if (size_t pos = opt_val.find(",") != std::string::npos) + opt_val.replace(pos, 1, 1, '.'); + break; + case coStrings: opt_val = static_cast(preset.config.option(opt.first))->values[0]; break; + case coBools: opt_val = static_cast(preset.config.option(opt.first))->values[0] ? "1" : "0"; break; + default: + assert(true); + continue; + } } - if (preset.config.option(opt.first)->serialize() != opt.second) { + + if (opt_val != opt.second[0]) + { failed = true; break; } } - if (failed) { - continue; + if (!failed) { + results.push_back(&preset); } - results.push_back(&preset); } // find visible without prefix for (const Preset *preset : results) { @@ -3924,12 +3928,23 @@ bool GUI_App::select_printer_from_connect(const std::string& msg) BOOST_LOG_TRIVIAL(error) << "Failed to select printer from Connect. Printer_model is empty."; return false; } - std::string nozzle = UserAccountUtils::get_nozzle_from_json(ptree); - std::map config_options_to_match; + std::map> config_options_to_match; UserAccountUtils::fill_config_options_from_json(ptree, config_options_to_match); - BOOST_LOG_TRIVIAL(info) << "Select printer from Connect. Model: " << model_name << "nozzle: " << nozzle; + // prevent not having nozzle diameter + if (config_options_to_match.find("nozzle_diameter") == config_options_to_match.end()) { + std::string diameter = UserAccountUtils::get_keyword_from_json(ptree, msg, "nozzle_diameter"); + if (!diameter.empty()) + config_options_to_match["nozzle_diameter"] = {diameter}; + } + // log + BOOST_LOG_TRIVIAL(info) << "Select printer from Connect. Model: " << model_name; + for(const auto& pair :config_options_to_match) { + std::string out; + for(const std::string& val :pair.second) { out += val + ",";} + BOOST_LOG_TRIVIAL(info) << pair.first << ": " << out; + } // select printer - const Preset* printer_preset = find_preset_by_nozzle_and_options(preset_bundle->printers, model_name, nozzle, config_options_to_match); + const Preset* printer_preset = find_preset_by_nozzle_and_options(preset_bundle->printers, model_name, config_options_to_match); bool is_installed = printer_preset && select_printer_preset(printer_preset); // notification std::string out = printer_preset ? @@ -4031,6 +4046,9 @@ void GUI_App::select_filament_from_connect(const std::string& msg) size_t extruder_count = preset_bundle->extruders_filaments.size(); if (extruder_count != materials.size()) { BOOST_LOG_TRIVIAL(error) << format("Failed to select filament from Connect. Selected printer has %1% extruders while data from Connect contains %2% materials.", extruder_count, materials.size()); + plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); + // TRN: Notification text. + plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, _u8L("Failed to select filament from Connect.")); return; } std::string notification_text; @@ -4065,7 +4083,6 @@ void GUI_App::handle_connect_request_printer_select_inner(const std::string & ms BOOST_LOG_TRIVIAL(debug) << "Handling web request: " << msg; // return to plater this->mainframe->select_tab(size_t(0)); - if (!select_printer_from_connect(msg)) { // If printer was not selected, do not select filament. return; diff --git a/src/slic3r/GUI/UserAccountUtils.cpp b/src/slic3r/GUI/UserAccountUtils.cpp index 84c6483ed5..a4f1778f3a 100644 --- a/src/slic3r/GUI/UserAccountUtils.cpp +++ b/src/slic3r/GUI/UserAccountUtils.cpp @@ -11,7 +11,7 @@ namespace pt = boost::property_tree; namespace Slic3r { namespace GUI { namespace UserAccountUtils { namespace { -std::string parse_tree_for_param(const pt::ptree &tree, const std::string ¶m) { +std::string parse_tree_for_param(const pt::ptree& tree, const std::string& param) { for (const auto §ion : tree) { if (section.first == param) { return section.second.data(); @@ -24,8 +24,7 @@ std::string parse_tree_for_param(const pt::ptree &tree, const std::string ¶m } void parse_tree_for_param_vector( - const pt::ptree &tree, const std::string ¶m, std::vector &results -) { +const pt::ptree &tree, const std::string& param, std::vector& results) { for (const auto §ion : tree) { if (section.first == param) { results.emplace_back(section.second.data()); @@ -35,7 +34,7 @@ void parse_tree_for_param_vector( } } -pt::ptree parse_tree_for_subtree(const pt::ptree &tree, const std::string ¶m) { +pt::ptree parse_tree_for_subtree(const pt::ptree& tree, const std::string& param) { for (const auto §ion : tree) { if (section.first == param) { return section.second; @@ -47,7 +46,7 @@ pt::ptree parse_tree_for_subtree(const pt::ptree &tree, const std::string ¶m return pt::ptree(); } -void json_to_ptree(boost::property_tree::ptree &ptree, const std::string &json) { +void json_to_ptree(boost::property_tree::ptree& ptree, const std::string& json) { try { std::stringstream ss(json); pt::read_json(ss, ptree); @@ -59,7 +58,7 @@ void json_to_ptree(boost::property_tree::ptree &ptree, const std::string &json) } // namespace -std::string get_nozzle_from_json(boost::property_tree::ptree &ptree) { +std::string get_nozzle_from_json(boost::property_tree::ptree& ptree) { assert(!ptree.empty()); std::string out = parse_tree_for_param(ptree, "nozzle_diameter"); @@ -74,7 +73,7 @@ std::string get_nozzle_from_json(boost::property_tree::ptree &ptree) { return out; } -std::string get_keyword_from_json(boost::property_tree::ptree &ptree, const std::string &json, const std::string &keyword ) +std::string get_keyword_from_json(boost::property_tree::ptree& ptree, const std::string& json, const std::string& keyword ) { if (ptree.empty()) { json_to_ptree(ptree, json); @@ -83,7 +82,7 @@ std::string get_keyword_from_json(boost::property_tree::ptree &ptree, const std: return parse_tree_for_param(ptree, keyword); } -void fill_supported_printer_models_from_json(boost::property_tree::ptree &ptree, std::vector &result) +void fill_supported_printer_models_from_json(boost::property_tree::ptree& ptree, std::vector& result) { assert(!ptree.empty()); std::string printer_model = parse_tree_for_param(ptree, "printer_model"); @@ -102,16 +101,87 @@ void fill_supported_printer_models_from_json(boost::property_tree::ptree &ptree, } } -void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map& result) +namespace { +std::string json_var_to_opt_string(const std::string& json_var) +{ + if (json_var == "true") + return "1"; + if (json_var == "false") + return "0"; + return json_var; +} +} + +void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map>& result) { assert(!ptree.empty()); - pt::ptree subtree = parse_tree_for_subtree(ptree, "printerConfig"); - for (const auto &item : subtree) { - result[item.first] = item.second.data(); + /* + "slot": { + "active": 3, + "slots": { + "1": { + "material": "PETG", + "temp": 32.0, + "fan_hotend": 0.0, + "fan_print": 0.0, + "nozzle_diameter": 3.2, // float + "high_flow": true, // boolean + "high_temperature": false, // boolean + "hardened": true, // boolean + }, + "3": { + "material": "ASA", + "temp": 35.0, + "fan_hotend": 0.0, + "fan_print": 0.0, + "nozzle_diameter": 3.2, // float + "high_flow": true, // boolean + "high_temperature": false, // boolean + "hardened": true, // boolean + }, + } + } + */ + const std::map parameters = { + // first name from connect, second config option + {"nozzle_diameter","nozzle_diameter"}, + {"high_flow","nozzle_high_flow"}, + //{"",""} + }; + pt::ptree slots = parse_tree_for_subtree(parse_tree_for_subtree(ptree, "slot"), "slots"); + for (const auto &subtree : slots) { + size_t slot_id; + try { + slot_id = boost::lexical_cast(subtree.first); + } catch (const boost::bad_lexical_cast&) { + continue; + } + for (const auto &item : subtree.second) { + if (parameters.find(item.first) == parameters.end()) { + continue; + } + std::string config_name = parameters.at(item.first); + // resolve value + std::string val; + if (item.second.size() > 0) { + for (const auto &subitem : item.second) { + if (!val.empty()) { + val += ","; + } + val += json_var_to_opt_string(subitem.second.data()); + } + } else { + val = json_var_to_opt_string(item.second.data()); + } + // insert value + while (result[config_name].size() < slot_id) + result[config_name].emplace_back(); + result[config_name][slot_id - 1] = val; + } } } -void fill_material_from_json(const std::string &json, std::vector &result) +void fill_material_from_json(const std::string& json, std::vector& result) { pt::ptree ptree; json_to_ptree(ptree, json); @@ -178,10 +248,26 @@ void fill_material_from_json(const std::string &json, std::vector & return; } // search "slot" subtree for all "material"s - parse_tree_for_param_vector(slot_subtree, "material", result); + // this parses "slots" with respect to numbers of slots and adds empty string to missing numbers + // if only filled should be used. Use: parse_tree_for_param_vector(slot_subtree, "material", result); + pt::ptree slots = parse_tree_for_subtree(slot_subtree, "slots"); + assert(!slots.empty()); + for (const auto &subtree : slots) { + size_t slot_id; + try { + slot_id = boost::lexical_cast(subtree.first); + } catch (const boost::bad_lexical_cast&) { + continue; + } + std::string val = parse_tree_for_param(subtree.second, "material"); + // add empty for missing id + while (result.size() < slot_id) + result.emplace_back(); + result[slot_id - 1] = val; + } } -std::string get_print_data_from_json(const std::string &json, const std::string &keyword) { +std::string get_print_data_from_json(const std::string& json, const std::string& keyword) { // copy subtree string f.e. // { "": {"param1": "something", "filename":"abcd.gcode", "param3":true}, // "something_else" : 0 } into: {"param1": "something", "filename":"%1%", "param3":true, diff --git a/src/slic3r/GUI/UserAccountUtils.hpp b/src/slic3r/GUI/UserAccountUtils.hpp index cfecaaa2f6..e45b385cf5 100644 --- a/src/slic3r/GUI/UserAccountUtils.hpp +++ b/src/slic3r/GUI/UserAccountUtils.hpp @@ -15,7 +15,7 @@ std::string get_keyword_from_json(boost::property_tree::ptree& ptree, const std: // Only ptree is passed since these functions are called on places that already has the ptree from get_keyword_from_json call std::string get_nozzle_from_json(boost::property_tree::ptree &ptree); void fill_supported_printer_models_from_json(boost::property_tree::ptree& ptree, std::vector& result); -void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map& result); +void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map>& result); // Since fill_material_from_json is called only from one place where ptree doesnt need to be shared, it is not always read from json. void fill_material_from_json(const std::string& json, std::vector& result); diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 30f93c7477..9d5ec17a1f 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -1288,8 +1288,10 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() { nozzle_diameter_serialized.Replace(L",", L"."); // Sending only first filament type for now. This should change to array of values const std::string filament_type_serialized = full_config.option("filament_type")->serialize(); - std::string printer_model_serialized = full_config.option("printer_model")->serialize(); + const std::string nozzle_high_flow_serialized = static_cast(full_config.option("nozzle_high_flow"))->values[0] ? "1" : "0"; + const std::string filament_abrasive_serialized = static_cast(full_config.option("filament_abrasive"))->values[0] ? "1" : "0"; + std::string printer_model_serialized = full_config.option("printer_model")->serialize(); std::string vendor_repo_prefix; if (selected_printer.vendor) { vendor_repo_prefix = selected_printer.vendor->repo_prefix; @@ -1311,19 +1313,13 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() { "{" "\"printerUuid\": \"%4%\", " "\"printerModel\": \"%3%\", " - "\"nozzleDiameter\": %2%, " + "\"nozzle_diameter\": %2%, " "\"material\": \"%1%\", " "\"filename\": \"%5%\", " - "\"fullConfig\": {" - , filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized, uuid, filename); - - for (auto it = full_config.cbegin(); it != full_config.cend(); ++it) { - std::string value = full_config.option(it->first)->serialize(); - boost::algorithm::replace_all(value, "\"", "\\\""); - request += it == full_config.cbegin() ? "" : ","; - request += GUI::format("\"%1%\": \"%2%\"", it->first, value); - } - request += "}}"; + "\"filament_abrasive\": \"%6%\"," + "\"nozzle_high_flow\": \"%7%\"" + "}" + , filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized, uuid, filename, nozzle_high_flow_serialized, filament_abrasive_serialized); wxString script = GUI::format_wxstr("window._prusaConnect_v1.requestCompatiblePrinter(%1%)", request); run_script(script); From a361f78067312b16a707a0d7f3774eac9d58353b Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 5 Aug 2024 11:19:55 +0200 Subject: [PATCH 09/16] Fix of faulty upload to Connect, when upload is set before slicing ends. --- src/slic3r/GUI/UserAccountUtils.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/UserAccountUtils.cpp b/src/slic3r/GUI/UserAccountUtils.cpp index a4f1778f3a..fb67f01c59 100644 --- a/src/slic3r/GUI/UserAccountUtils.cpp +++ b/src/slic3r/GUI/UserAccountUtils.cpp @@ -280,9 +280,6 @@ std::string get_print_data_from_json(const std::string& json, const std::string& size_t start_of_sub = json.find('{', start_of_keyword); if (start_of_sub == std::string::npos) return {}; - size_t end_of_sub = json.find('}', start_of_sub); - if (end_of_sub == std::string::npos) - return {}; size_t start_of_filename = json.find("\"filename\"", start_of_sub); if (start_of_filename == std::string::npos) return {}; @@ -295,6 +292,9 @@ std::string get_print_data_from_json(const std::string& json, const std::string& size_t end_of_filename_data = json.find('\"', start_of_filename_data + 1); if (end_of_filename_data == std::string::npos) return {}; + size_t end_of_sub = json.find('}', end_of_filename_data); + if (end_of_sub == std::string::npos) + return {}; size_t size = json.size(); std::string result = json.substr(start_of_sub, start_of_filename_data - start_of_sub + 1); result += "%1%"; From 37583da9e860470bc4432f2269c1519847a4c156 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 26 Aug 2024 16:07:20 +0200 Subject: [PATCH 10/16] Removed nozzle_high_temperature --- deps/+LibBGCode/LibBGCode.cmake | 4 ++-- src/libslic3r/GCode.cpp | 2 +- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/Print.cpp | 1 - src/libslic3r/PrintConfig.cpp | 8 +------- src/libslic3r/PrintConfig.hpp | 1 - src/slic3r/GUI/Tab.cpp | 4 +--- 7 files changed, 6 insertions(+), 16 deletions(-) diff --git a/deps/+LibBGCode/LibBGCode.cmake b/deps/+LibBGCode/LibBGCode.cmake index 2a43a8ea06..8f2ead2585 100644 --- a/deps/+LibBGCode/LibBGCode.cmake +++ b/deps/+LibBGCode/LibBGCode.cmake @@ -1,8 +1,8 @@ set(LibBGCode_SOURCE_DIR "" CACHE PATH "Optionally specify local LibBGCode source directory") set(_source_dir_line - URL https://github.com/prusa3d/libbgcode/archive/a21254e7043b9a9e8f1c89a1d702912b36ad3d4c.zip - URL_HASH SHA256=4ce42e5b3129e3cb976d19c7c14ec8c708758297b27908b62657a57ac07e7fb5) + URL https://github.com/prusa3d/libbgcode/archive/d20e3a3a6d1ee3d8026bf20c5a9ce2ad88f4b433.zip + URL_HASH SHA256=bfcba51262bdda6f0bf06b9508f4386c50145d3e97bba6c76ee1f1520dae3b93) if (LibBGCode_SOURCE_DIR) set(_source_dir_line "SOURCE_DIR;${LibBGCode_SOURCE_DIR};BUILD_ALWAYS;ON") diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 8d42f03db2..d1323c8b31 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -957,7 +957,7 @@ void GCodeGenerator::_do_export(Print& print, GCodeOutputStream &file, Thumbnail // printer data - this section contains duplicates from the slicer metadata // that we just created. Find and copy the entries that we want to duplicate. const auto& slicer_metadata = binary_data.slicer_metadata.raw_data; - const std::vector keys_to_duplicate = { "printer_model", "filament_type", "filament_abrasive", "nozzle_diameter", "nozzle_high_flow", "nozzle_high_temperature", "bed_temperature", + const std::vector keys_to_duplicate = { "printer_model", "filament_type", "filament_abrasive", "nozzle_diameter", "nozzle_high_flow", "bed_temperature", "brim_width", "fill_density", "layer_height", "temperature", "ironing", "support_material", "extruder_colour"}; assert(std::is_sorted(slicer_metadata.begin(), slicer_metadata.end(), [](const auto& a, const auto& b) { return a.first < b.first; })); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 54285ff25b..fe943d8cb8 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -533,7 +533,7 @@ static std::vector s_Preset_printer_options { "max_print_height", "default_print_profile", "inherits", "remaining_times", "silent_mode", "machine_limits_usage", "thumbnails", "thumbnails_format", - "nozzle_high_flow", "nozzle_high_temperature", + "nozzle_high_flow" }; static std::vector s_Preset_sla_print_options { diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 7bba2ea5ee..1bd340d165 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -128,7 +128,6 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "gcode_comments", "gcode_label_objects", "nozzle_high_flow", - "nozzle_high_temperature", "infill_acceleration", "layer_gcode", "min_fan_speed", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 58d8e722a3..ed3c5a74cf 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2562,12 +2562,6 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionBools{false}); - def = this->add("nozzle_high_temperature", coBools); - def->label = L("High temperature nozzle"); - def->tooltip = L("TODO"); - def->mode = comExpert; - def->set_default_value(new ConfigOptionBools{false}); - def = this->add("retract_lift", coFloats); def->label = L("Lift height"); def->tooltip = L("Lift height applied before travel."); @@ -3733,7 +3727,7 @@ void PrintConfigDef::init_extruder_option_keys() "retract_before_wipe", "retract_restart_extra", "retract_before_travel", "wipe", "travel_slope", "travel_max_lift", "travel_ramping_lift", "travel_lift_before_obstacle", "retract_layer_change", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour", - "default_filament_profile", "nozzle_high_flow", "nozzle_high_temperature" + "default_filament_profile", "nozzle_high_flow" }; m_extruder_retract_keys = { diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 0a82f5e9c2..fb89debbd6 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -827,7 +827,6 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloats, travel_slope)) ((ConfigOptionBools, travel_lift_before_obstacle)) ((ConfigOptionBools, nozzle_high_flow)) - ((ConfigOptionBools, nozzle_high_temperature)) ((ConfigOptionPercents, retract_before_wipe)) ((ConfigOptionFloats, retract_length)) ((ConfigOptionFloats, retract_length_toolchange)) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index aa35aa9590..27ada926ff 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3133,7 +3133,7 @@ const std::vector extruder_options = { "retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed", "retract_restart_extra", "retract_before_travel", "retract_layer_change", "wipe", "retract_before_wipe", "travel_ramping_lift", - "travel_slope", "travel_max_lift", "travel_lift_before_obstacle", "nozzle_high_flow", "nozzle_high_temperature", + "travel_slope", "travel_max_lift", "travel_lift_before_obstacle", "nozzle_high_flow", "retract_length_toolchange", "retract_restart_extra_toolchange", }; @@ -3197,8 +3197,6 @@ void TabPrinter::build_extruder_pages(size_t n_before_extruders) }; optgroup->append_single_option_line("nozzle_high_flow", "", extruder_idx); - optgroup->append_single_option_line("nozzle_high_temperature", "", extruder_idx); - optgroup = page->new_optgroup(L("Preview")); From b492368f269dc9bea0db6f1332e92b200435fadc Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 26 Aug 2024 16:08:46 +0200 Subject: [PATCH 11/16] nozzle_high_flow should be synchronized when single_extruder_multi_material --- src/slic3r/GUI/Tab.cpp | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 27ada926ff..157ec0c042 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3151,7 +3151,8 @@ void TabPrinter::build_extruder_pages(size_t n_before_extruders) optgroup->on_change = [this, extruder_idx](const t_config_option_key&opt_key, boost::any value) { const bool is_single_extruder_MM = m_config->opt_bool("single_extruder_multi_material"); - const bool is_nozzle_diameter_changed = opt_key.find_first_of("nozzle_diameter") != std::string::npos; + const bool is_nozzle_diameter_changed = opt_key.find("nozzle_diameter") != std::string::npos; + const bool is_high_flow_changed = opt_key.find("nozzle_high_flow") != std::string::npos; if (is_single_extruder_MM && m_extruders_count > 1 && is_nozzle_diameter_changed) { @@ -3164,7 +3165,6 @@ void TabPrinter::build_extruder_pages(size_t n_before_extruders) { const wxString msg_text = _L("This is a single extruder multimaterial printer, diameters of all extruders " "will be set to the new value. Do you want to proceed?"); - //wxMessageDialog dialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); MessageDialog dialog(parent(), msg_text, _L("Nozzle diameter"), wxICON_WARNING | wxYES_NO); DynamicPrintConfig new_conf = *m_config; @@ -3183,7 +3183,36 @@ void TabPrinter::build_extruder_pages(size_t n_before_extruders) } } - if (is_nozzle_diameter_changed) { + if (is_single_extruder_MM && m_extruders_count > 1 && is_high_flow_changed) + { + SuppressBackgroundProcessingUpdate sbpu; + const unsigned char new_hf = boost::any_cast(value); + std::vector nozzle_high_flow = static_cast(m_config->option("nozzle_high_flow"))->values; + + // if value was changed + if (nozzle_high_flow[extruder_idx == 0 ? 1 : 0] != new_hf) + { + const wxString msg_text = _L("This is a single extruder multimaterial printer, 'high_flow' state of all extruders " + "will be set to the new value. Do you want to proceed?"); + MessageDialog dialog(parent(), msg_text, _L("High flow"), wxICON_WARNING | wxYES_NO); + + DynamicPrintConfig new_conf = *m_config; + if (dialog.ShowModal() == wxID_YES) { + for (size_t i = 0; i < nozzle_high_flow.size(); i++) { + if (i==extruder_idx) + continue; + nozzle_high_flow[i] = new_hf; + } + } + else + nozzle_high_flow[extruder_idx] = nozzle_high_flow[extruder_idx == 0 ? 1 : 0]; + + new_conf.set_key_value("nozzle_high_flow", new ConfigOptionBools(nozzle_high_flow)); + load_config(new_conf); + } + } + + if (is_nozzle_diameter_changed || is_high_flow_changed) { if (extruder_idx == 0) // Mark the print & filament enabled if they are compatible with the currently selected preset. // If saving the preset changes compatibility with other presets, keep the now incompatible dependent presets selected, however with a "red flag" icon showing that they are no more compatible. From 02c63a56b887f649215235d5ae42a9308020b42d Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 26 Aug 2024 17:23:29 +0200 Subject: [PATCH 12/16] avoid abrasive filament on non harden nozzle when selecting printer from connect. --- src/slic3r/GUI/GUI_App.cpp | 10 ++- src/slic3r/GUI/GUI_App.hpp | 2 +- src/slic3r/GUI/UserAccountUtils.cpp | 102 +++++++++++++++++----------- src/slic3r/GUI/UserAccountUtils.hpp | 2 +- 4 files changed, 73 insertions(+), 43 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 5cf38043a0..3957325f65 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3973,7 +3973,7 @@ bool GUI_App::select_filament_preset(const Preset* preset, size_t extruder_index assert(preset->is_visible); return preset_bundle->extruders_filaments[extruder_index].select_filament(preset->name); } -void GUI_App::search_and_select_filaments(const std::string& material, size_t extruder_index, std::string& out_message) +void GUI_App::search_and_select_filaments(const std::string& material, bool avoid_abrasive, size_t extruder_index, std::string& out_message) { const Preset* preset = preset_bundle->extruders_filaments[extruder_index].get_selected_preset(); // selected is ok @@ -3987,6 +3987,7 @@ void GUI_App::search_and_select_filaments(const std::string& material, size_t ex && filament.preset->is_visible && (!filament.preset->vendor || !filament.preset->vendor->templates_profile) && filament.preset->config.has("filament_type") + && (!avoid_abrasive || filament.preset->config.opt_bool("filament_abrasive") == false) && filament.preset->config.option("filament_type")->serialize() == material && filament.preset->name.compare(0, 9, "Prusament") == 0 && select_filament_preset(filament.preset, extruder_index) @@ -4005,6 +4006,7 @@ void GUI_App::search_and_select_filaments(const std::string& material, size_t ex && filament.preset->is_visible && (!filament.preset->vendor || !filament.preset->vendor->templates_profile) && filament.preset->config.has("filament_type") + && (!avoid_abrasive || filament.preset->config.opt_bool("filament_abrasive") == false) && filament.preset->config.option("filament_type")->serialize() == material && select_filament_preset(filament.preset, extruder_index) ) @@ -4022,6 +4024,7 @@ void GUI_App::search_and_select_filaments(const std::string& material, size_t ex && !filament.preset->is_default && (!filament.preset->vendor || !filament.preset->vendor->templates_profile) && filament.preset->config.has("filament_type") + && (!avoid_abrasive || filament.preset->config.opt_bool("filament_abrasive") == false) && filament.preset->config.option("filament_type")->serialize() == material && filament.preset->name.compare(0, 9, "Prusament") == 0 && select_filament_preset(filament.preset, extruder_index)) @@ -4037,7 +4040,8 @@ void GUI_App::select_filament_from_connect(const std::string& msg) { // parse message std::vector materials; - UserAccountUtils::fill_material_from_json(msg, materials); + std::vector avoid_abrasive; + UserAccountUtils::fill_material_from_json(msg, materials, avoid_abrasive); if (materials.empty()) { BOOST_LOG_TRIVIAL(error) << "Failed to select filament from Connect. No material data."; return; @@ -4053,7 +4057,7 @@ void GUI_App::select_filament_from_connect(const std::string& msg) } std::string notification_text; for (size_t i = 0; i < extruder_count; i++) { - search_and_select_filaments(materials[i], i, notification_text); + search_and_select_filaments(materials[i], avoid_abrasive.size() > i ? avoid_abrasive[i] : false, i, notification_text); } // When all filaments are selected/intalled, diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 6d7008f0dd..e915576943 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -416,7 +416,7 @@ public: // return true if preset vas invisible and we have to installed it to make it selectable bool select_printer_preset(const Preset* printer_preset); bool select_filament_preset(const Preset* filament_preset, size_t extruder_index); - void search_and_select_filaments(const std::string& material, size_t extruder_index, std::string& out_message); + void search_and_select_filaments(const std::string& material, bool avoid_abrasive, size_t extruder_index, std::string& out_message); void handle_script_message(std::string msg) {} void request_model_download(std::string import_json) {} void download_project(std::string project_id) {} diff --git a/src/slic3r/GUI/UserAccountUtils.cpp b/src/slic3r/GUI/UserAccountUtils.cpp index fb67f01c59..c82a9731e6 100644 --- a/src/slic3r/GUI/UserAccountUtils.cpp +++ b/src/slic3r/GUI/UserAccountUtils.cpp @@ -110,44 +110,9 @@ std::string json_var_to_opt_string(const std::string& json_var) return "0"; return json_var; } -} -void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map>& result) +void fill_config_options_from_json_inner(boost::property_tree::ptree& ptree, std::map>& result, const std::map& parameters) { - assert(!ptree.empty()); - /* - "slot": { - "active": 3, - "slots": { - "1": { - "material": "PETG", - "temp": 32.0, - "fan_hotend": 0.0, - "fan_print": 0.0, - "nozzle_diameter": 3.2, // float - "high_flow": true, // boolean - "high_temperature": false, // boolean - "hardened": true, // boolean - }, - "3": { - "material": "ASA", - "temp": 35.0, - "fan_hotend": 0.0, - "fan_print": 0.0, - "nozzle_diameter": 3.2, // float - "high_flow": true, // boolean - "high_temperature": false, // boolean - "hardened": true, // boolean - }, - } - } - */ - const std::map parameters = { - // first name from connect, second config option - {"nozzle_diameter","nozzle_diameter"}, - {"high_flow","nozzle_high_flow"}, - //{"",""} - }; pt::ptree slots = parse_tree_for_subtree(parse_tree_for_subtree(ptree, "slot"), "slots"); for (const auto &subtree : slots) { size_t slot_id; @@ -180,8 +145,48 @@ void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map< } } } +} -void fill_material_from_json(const std::string& json, std::vector& result) +void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map>& result) +{ + assert(!ptree.empty()); + /* + "slot": { + "active": 3, + "slots": { + "1": { + "material": "PETG", + "temp": 32.0, + "fan_hotend": 0.0, + "fan_print": 0.0, + "nozzle_diameter": 3.2, // float + "high_flow": true, // boolean + "high_temperature": false, // boolean + "hardened": true, // boolean + }, + "3": { + "material": "ASA", + "temp": 35.0, + "fan_hotend": 0.0, + "fan_print": 0.0, + "nozzle_diameter": 3.2, // float + "high_flow": true, // boolean + "high_temperature": false, // boolean + "hardened": true, // boolean + }, + } + } + */ + const std::map parameters = { + // first name from connect, second config option + {"nozzle_diameter","nozzle_diameter"}, + {"high_flow","nozzle_high_flow"}, + //{"",""} + }; + fill_config_options_from_json_inner(ptree, result, parameters); +} + +void fill_material_from_json(const std::string& json, std::vector& material_result, std::vector& avoid_abrasive_result) { pt::ptree ptree; json_to_ptree(ptree, json); @@ -242,7 +247,8 @@ void fill_material_from_json(const std::string& json, std::vector& if (!filament_subtree.empty()) { std::string material = parse_tree_for_param(filament_subtree, "material"); if (!material.empty()) { - result.emplace_back(std::move(material)); + material_result.emplace_back(std::move(material)); + avoid_abrasive_result.emplace_back(true); } } return; @@ -250,6 +256,7 @@ void fill_material_from_json(const std::string& json, std::vector& // search "slot" subtree for all "material"s // this parses "slots" with respect to numbers of slots and adds empty string to missing numbers // if only filled should be used. Use: parse_tree_for_param_vector(slot_subtree, "material", result); + /* pt::ptree slots = parse_tree_for_subtree(slot_subtree, "slots"); assert(!slots.empty()); for (const auto &subtree : slots) { @@ -265,6 +272,25 @@ void fill_material_from_json(const std::string& json, std::vector& result.emplace_back(); result[slot_id - 1] = val; } + */ + const std::map parameters = { + // first name from connect, second config option + {"material","material"}, + {"hardened","hardened"}, + //{"",""} + }; + std::map> result_map; + fill_config_options_from_json_inner(ptree, result_map, parameters); + if (result_map.find("material") != result_map.end()) { + for (const std::string& val : result_map["material"]) { + material_result.emplace_back(val); + } + } + if (result_map.find("hardened") != result_map.end()) { + for (const std::string& val : result_map["hardened"]) { + avoid_abrasive_result.emplace_back(val == "false" ? 1 : 0); + } + } } std::string get_print_data_from_json(const std::string& json, const std::string& keyword) { diff --git a/src/slic3r/GUI/UserAccountUtils.hpp b/src/slic3r/GUI/UserAccountUtils.hpp index e45b385cf5..d470a93900 100644 --- a/src/slic3r/GUI/UserAccountUtils.hpp +++ b/src/slic3r/GUI/UserAccountUtils.hpp @@ -18,7 +18,7 @@ void fill_supported_printer_models_from_json(boost::property_tree::ptree& ptree, void fill_config_options_from_json(boost::property_tree::ptree& ptree, std::map>& result); // Since fill_material_from_json is called only from one place where ptree doesnt need to be shared, it is not always read from json. -void fill_material_from_json(const std::string& json, std::vector& result); +void fill_material_from_json(const std::string& json, std::vector& material_result, std::vector& avoid_abrasive_result); std::string get_print_data_from_json(const std::string &json, const std::string &keyword); From a54aa25f1b304829d12a8c838182423541531f20 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 27 Aug 2024 12:32:54 +0200 Subject: [PATCH 13/16] Added tooltips for the new parameters --- src/libslic3r/PrintConfig.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index ed3c5a74cf..fbe9fbaa51 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1372,7 +1372,7 @@ void PrintConfigDef::init_fff_params() def = this->add("filament_abrasive", coBools); def->label = L("Abrasive material"); - def->tooltip = L("TODO"); + def->tooltip = L("This flag means that the material is abrasive and requires a hardened nozzle. The value is used by the printer to check it."); def->mode = comExpert; def->set_default_value(new ConfigOptionBools { false }); @@ -2558,7 +2558,7 @@ void PrintConfigDef::init_fff_params() def = this->add("nozzle_high_flow", coBools); def->label = L("High flow nozzle"); - def->tooltip = L("TODO"); + def->tooltip = L("High flow nozzles allow higher print speeds."); def->mode = comExpert; def->set_default_value(new ConfigOptionBools{false}); From 8edc0b796d932eec2a13076f484108edf100a99c Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 27 Aug 2024 15:35:05 +0200 Subject: [PATCH 14/16] followup on 5f4b4da91e0c062153ca24ce4fbc829e5c1e6044 fix of value reading --- src/slic3r/GUI/GUI_App.cpp | 12 ++++++++---- src/slic3r/GUI/UserAccountUtils.cpp | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 3957325f65..8a7ad88365 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3976,8 +3976,12 @@ bool GUI_App::select_filament_preset(const Preset* preset, size_t extruder_index void GUI_App::search_and_select_filaments(const std::string& material, bool avoid_abrasive, size_t extruder_index, std::string& out_message) { const Preset* preset = preset_bundle->extruders_filaments[extruder_index].get_selected_preset(); + bool b = preset->config.option("filament_abrasive")->get_at(0); // selected is ok - if (!preset->is_default && preset->config.has("filament_type") && preset->config.option("filament_type")->serialize() == material) { + if (!preset->is_default && preset->config.has("filament_type") + && (!avoid_abrasive || preset->config.option("filament_abrasive")->get_at(0) == false) + && preset->config.option("filament_type")->serialize() == material) + { return; } // find installed compatible filament that is Prusa with suitable type and select it @@ -3987,7 +3991,7 @@ void GUI_App::search_and_select_filaments(const std::string& material, bool avoi && filament.preset->is_visible && (!filament.preset->vendor || !filament.preset->vendor->templates_profile) && filament.preset->config.has("filament_type") - && (!avoid_abrasive || filament.preset->config.opt_bool("filament_abrasive") == false) + && (!avoid_abrasive || filament.preset->config.option("filament_abrasive")->get_at(0) == false) && filament.preset->config.option("filament_type")->serialize() == material && filament.preset->name.compare(0, 9, "Prusament") == 0 && select_filament_preset(filament.preset, extruder_index) @@ -4006,7 +4010,7 @@ void GUI_App::search_and_select_filaments(const std::string& material, bool avoi && filament.preset->is_visible && (!filament.preset->vendor || !filament.preset->vendor->templates_profile) && filament.preset->config.has("filament_type") - && (!avoid_abrasive || filament.preset->config.opt_bool("filament_abrasive") == false) + && (!avoid_abrasive || filament.preset->config.option("filament_abrasive")->get_at(0) == false) && filament.preset->config.option("filament_type")->serialize() == material && select_filament_preset(filament.preset, extruder_index) ) @@ -4024,7 +4028,7 @@ void GUI_App::search_and_select_filaments(const std::string& material, bool avoi && !filament.preset->is_default && (!filament.preset->vendor || !filament.preset->vendor->templates_profile) && filament.preset->config.has("filament_type") - && (!avoid_abrasive || filament.preset->config.opt_bool("filament_abrasive") == false) + && (!avoid_abrasive || filament.preset->config.option("filament_abrasive")->get_at(0) == false) && filament.preset->config.option("filament_type")->serialize() == material && filament.preset->name.compare(0, 9, "Prusament") == 0 && select_filament_preset(filament.preset, extruder_index)) diff --git a/src/slic3r/GUI/UserAccountUtils.cpp b/src/slic3r/GUI/UserAccountUtils.cpp index c82a9731e6..7cde12db6e 100644 --- a/src/slic3r/GUI/UserAccountUtils.cpp +++ b/src/slic3r/GUI/UserAccountUtils.cpp @@ -288,7 +288,7 @@ void fill_material_from_json(const std::string& json, std::vector& } if (result_map.find("hardened") != result_map.end()) { for (const std::string& val : result_map["hardened"]) { - avoid_abrasive_result.emplace_back(val == "false" ? 1 : 0); + avoid_abrasive_result.emplace_back(val == "0" ? 1 : 0); } } } From c758c74d7f5549c44ca7ca2bd98de970ba1f6d7e Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 27 Aug 2024 16:17:10 +0200 Subject: [PATCH 15/16] Change in comparing nozzle diameter in right panel printer status --- src/slic3r/GUI/GUI_App.cpp | 9 ++-- src/slic3r/GUI/PresetComboBoxes.cpp | 75 +++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 8a7ad88365..1ef8b24ffc 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3976,10 +3976,9 @@ bool GUI_App::select_filament_preset(const Preset* preset, size_t extruder_index void GUI_App::search_and_select_filaments(const std::string& material, bool avoid_abrasive, size_t extruder_index, std::string& out_message) { const Preset* preset = preset_bundle->extruders_filaments[extruder_index].get_selected_preset(); - bool b = preset->config.option("filament_abrasive")->get_at(0); // selected is ok if (!preset->is_default && preset->config.has("filament_type") - && (!avoid_abrasive || preset->config.option("filament_abrasive")->get_at(0) == false) + && (!avoid_abrasive || preset->config.option("filament_abrasive")->values[0] == false) && preset->config.option("filament_type")->serialize() == material) { return; @@ -3991,7 +3990,7 @@ void GUI_App::search_and_select_filaments(const std::string& material, bool avoi && filament.preset->is_visible && (!filament.preset->vendor || !filament.preset->vendor->templates_profile) && filament.preset->config.has("filament_type") - && (!avoid_abrasive || filament.preset->config.option("filament_abrasive")->get_at(0) == false) + && (!avoid_abrasive || filament.preset->config.option("filament_abrasive")->values[0] == false) && filament.preset->config.option("filament_type")->serialize() == material && filament.preset->name.compare(0, 9, "Prusament") == 0 && select_filament_preset(filament.preset, extruder_index) @@ -4010,7 +4009,7 @@ void GUI_App::search_and_select_filaments(const std::string& material, bool avoi && filament.preset->is_visible && (!filament.preset->vendor || !filament.preset->vendor->templates_profile) && filament.preset->config.has("filament_type") - && (!avoid_abrasive || filament.preset->config.option("filament_abrasive")->get_at(0) == false) + && (!avoid_abrasive || filament.preset->config.option("filament_abrasive")->values[0] == false) && filament.preset->config.option("filament_type")->serialize() == material && select_filament_preset(filament.preset, extruder_index) ) @@ -4028,7 +4027,7 @@ void GUI_App::search_and_select_filaments(const std::string& material, bool avoi && !filament.preset->is_default && (!filament.preset->vendor || !filament.preset->vendor->templates_profile) && filament.preset->config.has("filament_type") - && (!avoid_abrasive || filament.preset->config.option("filament_abrasive")->get_at(0) == false) + && (!avoid_abrasive || filament.preset->config.option("filament_abrasive")->values[0] == false) && filament.preset->config.option("filament_type")->serialize() == material && filament.preset->name.compare(0, 9, "Prusament") == 0 && select_filament_preset(filament.preset, extruder_index)) diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index ff7815a18e..733a2c6907 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -985,16 +985,32 @@ static std::string get_connect_state_suffix_for_printer(const Preset& printer_pr boost::trim_left(printer_model); } - if (printer_model_nozzle_pair.first == printer_model - && printer_model_nozzle_pair.second == printer_preset.config.opt_string("printer_variant")) - { - PrinterStatesCount states_cnt = get_printe_states_count(states); + if (printer_preset.config.has("nozzle_diameter")) { + double nozzle_diameter = static_cast(printer_preset.config.option("nozzle_diameter"))->values[0]; + wxString nozzle_diameter_serialized = double_to_string(nozzle_diameter); + nozzle_diameter_serialized.Replace(L",", L"."); - if (states_cnt.available_cnt > 0) - return "_available"; - if (states_cnt.busy_cnt > 0) - return "_busy"; - return "_offline"; + if (printer_model_nozzle_pair.first == printer_model + && printer_model_nozzle_pair.second == GUI::into_u8(nozzle_diameter_serialized)) + { + PrinterStatesCount states_cnt = get_printe_states_count(states); + + if (states_cnt.available_cnt > 0) + return "_available"; + if (states_cnt.busy_cnt > 0) + return "_busy"; + return "_offline"; + } + } else { + if (printer_model_nozzle_pair.first == printer_model) { + PrinterStatesCount states_cnt = get_printe_states_count(states); + + if (states_cnt.available_cnt > 0) + return "_available"; + if (states_cnt.busy_cnt > 0) + return "_busy"; + return "_offline"; + } } } } @@ -1033,21 +1049,40 @@ static bool fill_data_to_connect_info_line( const Preset& printer_preset, boost::trim_left(printer_model); } - if (printer_model_nozzle_pair.first == printer_model - && printer_model_nozzle_pair.second == printer_preset.config.opt_string("printer_variant")) - { - PrinterStatesCount states_cnt = get_printe_states_count(states); + if (printer_preset.config.has("nozzle_diameter")) { + double nozzle_diameter = static_cast(printer_preset.config.option("nozzle_diameter"))->values[0]; + wxString nozzle_diameter_serialized = double_to_string(nozzle_diameter); + nozzle_diameter_serialized.Replace(L",", L"."); + if (printer_model_nozzle_pair.first == printer_model + && printer_model_nozzle_pair.second == GUI::into_u8(nozzle_diameter_serialized)) + { + PrinterStatesCount states_cnt = get_printe_states_count(states); #ifdef _WIN32 - connect_available_info->SetLabelMarkup(format_wxstr("%1% %2%", format("%1%", states_cnt.available_cnt), _L("available"))); - connect_offline_info ->SetLabelMarkup(format_wxstr("%1% %2%", format("%1%", states_cnt.offline_cnt), _L("offline"))); - connect_printing_info ->SetLabelMarkup(format_wxstr("%1% %2%", format("%1%", states_cnt.busy_cnt), _L("printing"))); + connect_available_info->SetLabelMarkup(format_wxstr("%1% %2%", format("%1%", states_cnt.available_cnt), _L("available"))); + connect_offline_info ->SetLabelMarkup(format_wxstr("%1% %2%", format("%1%", states_cnt.offline_cnt), _L("offline"))); + connect_printing_info ->SetLabelMarkup(format_wxstr("%1% %2%", format("%1%", states_cnt.busy_cnt), _L("printing"))); #else - connect_available_info->SetLabel(format_wxstr("%1% ", states_cnt.available_cnt)); - connect_offline_info ->SetLabel(format_wxstr("%1% ", states_cnt.offline_cnt)); - connect_printing_info ->SetLabel(format_wxstr("%1% ", states_cnt.busy_cnt)); + connect_available_info->SetLabel(format_wxstr("%1% ", states_cnt.available_cnt)); + connect_offline_info ->SetLabel(format_wxstr("%1% ", states_cnt.offline_cnt)); + connect_printing_info ->SetLabel(format_wxstr("%1% ", states_cnt.busy_cnt)); #endif - return true; + return true; + } + } else { + if (printer_model_nozzle_pair.first == printer_model) { + PrinterStatesCount states_cnt = get_printe_states_count(states); +#ifdef _WIN32 + connect_available_info->SetLabelMarkup(format_wxstr("%1% %2%", format("%1%", states_cnt.available_cnt), _L("available"))); + connect_offline_info ->SetLabelMarkup(format_wxstr("%1% %2%", format("%1%", states_cnt.offline_cnt), _L("offline"))); + connect_printing_info ->SetLabelMarkup(format_wxstr("%1% %2%", format("%1%", states_cnt.busy_cnt), _L("printing"))); +#else + connect_available_info->SetLabel(format_wxstr("%1% ", states_cnt.available_cnt)); + connect_offline_info ->SetLabel(format_wxstr("%1% ", states_cnt.offline_cnt)); + connect_printing_info ->SetLabel(format_wxstr("%1% ", states_cnt.busy_cnt)); +#endif + return true; + } } } } From a2c964e88222a911f8beb9b70b64b3ea39e39cdd Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 28 Aug 2024 14:51:46 +0200 Subject: [PATCH 16/16] nozzle_high_flow should be synchronized when single_extruder_multi_material (part 2) --- src/slic3r/GUI/Tab.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 157ec0c042..23bf15da15 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2654,22 +2654,26 @@ void TabPrinter::build_fff() if (boost::any_cast(value) && m_extruders_count > 1) { SuppressBackgroundProcessingUpdate sbpu; std::vector nozzle_diameters = static_cast(m_config->option("nozzle_diameter"))->values; - const double frst_diam = nozzle_diameters[0]; + std::vector high_flow_nozzles = static_cast(m_config->option("nozzle_high_flow"))->values; + assert(nozzle_diameters.size() == high_flow_nozzles.size()); - for (auto cur_diam : nozzle_diameters) { + for (size_t i = 1; i < nozzle_diameters.size(); ++i) { // if value is differs from first nozzle diameter value - if (fabs(cur_diam - frst_diam) > EPSILON) { + if (fabs(nozzle_diameters[i] - nozzle_diameters[0]) > EPSILON || high_flow_nozzles[i] != high_flow_nozzles[0]) { const wxString msg_text = _(L("Single Extruder Multi Material is selected, \n" - "and all extruders must have the same diameter.\n" - "Do you want to change the diameter for all extruders to first extruder nozzle diameter value?")); - MessageDialog dialog(parent(), msg_text, _(L("Nozzle diameter")), wxICON_WARNING | wxYES_NO); + "and all extruders must have the same diameter and 'High flow' state.\n" + "Do you want to change these values for all extruders to first extruder values?")); + MessageDialog dialog(parent(), msg_text, _(L("Nozzle settings mismatch")), wxICON_WARNING | wxYES_NO); DynamicPrintConfig new_conf = *m_config; if (dialog.ShowModal() == wxID_YES) { - for (size_t i = 1; i < nozzle_diameters.size(); i++) - nozzle_diameters[i] = frst_diam; + for (size_t i = 1; i < nozzle_diameters.size(); i++) { + nozzle_diameters[i] = nozzle_diameters[0]; + high_flow_nozzles[i] = high_flow_nozzles[0]; + } new_conf.set_key_value("nozzle_diameter", new ConfigOptionFloats(nozzle_diameters)); + new_conf.set_key_value("nozzle_high_flow", new ConfigOptionBools(high_flow_nozzles)); } else new_conf.set_key_value("single_extruder_multi_material", new ConfigOptionBool(false));