diff --git a/resources/images/partskip_retry.svg b/resources/images/partskip_retry.svg new file mode 100644 index 0000000000..ff104e9951 --- /dev/null +++ b/resources/images/partskip_retry.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/images/print_control_partskip_hover.svg b/resources/images/print_control_partskip_hover.svg new file mode 100644 index 0000000000..b41ffcc516 --- /dev/null +++ b/resources/images/print_control_partskip_hover.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/slic3r/GUI/PartSkipDialog.cpp b/src/slic3r/GUI/PartSkipDialog.cpp index bfe98371d2..2b847fd0a0 100644 --- a/src/slic3r/GUI/PartSkipDialog.cpp +++ b/src/slic3r/GUI/PartSkipDialog.cpp @@ -230,11 +230,13 @@ PartSkipDialog::PartSkipDialog(wxWindow* parent): DPIDialog(parent, wxID_ANY, _L m_book_second_sizer = new wxBoxSizer( wxVERTICAL ); m_book_second_btn_sizer = new wxBoxSizer( wxHORIZONTAL ); - m_retry_label = new Label( m_book_second_panel, _L("Load Skipping Objects Information Failed. \nPlease try again.")); + m_retry_bitmap = new wxStaticBitmap(m_book_second_panel, -1, create_scaled_bitmap("partskip_retry", m_book_second_panel, 200), wxDefaultPosition, wxDefaultSize); + m_retry_label = new Label( m_book_second_panel, _L("Load skipping objects information failed. Please try again.")); m_retry_label->Wrap( -1 ); m_retry_label->SetBackgroundColour(*wxWHITE); m_book_second_sizer->Add(0, 0, 1, wxEXPAND, 0); - m_book_second_sizer->Add(m_retry_label, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER_HORIZONTAL, 0); + m_book_second_sizer->Add(m_retry_bitmap, 0, wxALIGN_CENTER_HORIZONTAL, 0); + m_book_second_sizer->Add(m_retry_label, 0, wxALIGN_CENTER_HORIZONTAL, 0); m_book_second_sizer->Add(0, 0, 1, wxEXPAND, 0); m_second_retry_btn = new Button(m_book_second_panel, _L("Retry")); @@ -305,6 +307,7 @@ void PartSkipDialog::on_dpi_changed(const wxRect& suggested_rect) { m_canvas->LoadPickImage(m_local_paths[0]); m_loading_icon->SetMinSize(wxSize(FromDIP(25), FromDIP(25))); + m_retry_bitmap->SetBitmap(create_scaled_bitmap("partskip_retry", m_book_second_panel, 200)); m_percent_label->SetMinSize(wxSize(FromDIP(56), FromDIP(28))); m_percent_label->SetMaxSize(wxSize(FromDIP(56), FromDIP(28))); @@ -426,8 +429,10 @@ void PartSkipDialog::DownloadPartsFile() m_file_sys->Bind(EVT_STATUS_CHANGED, &PartSkipDialog::OnFileSystemEvent, this); m_file_sys->Bind(EVT_RAMDOWNLOAD, &PartSkipDialog::OnFileSystemResult, this); m_file_sys->Start(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <<"part skip: print file system start."; }else{ m_file_sys->Retry(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <<"part skip: print file system retry."; } } else { m_file_sys->SendExistedFile(); @@ -526,8 +531,10 @@ void PartSkipDialog::OnFileSystemEvent(wxCommandEvent &e) if( m_url_state == URL_TCP){ m_url_state = URL_TUTK; m_file_sys->Retry(); + BOOST_LOG_TRIVIAL(info) << "part skip: print file system connnect failed first."; }else{ m_file_sys->SendConnectFail(); + BOOST_LOG_TRIVIAL(info) << "part skip: print file system connnect failed second."; } break; } @@ -538,6 +545,7 @@ void PartSkipDialog::OnFileSystemEvent(wxCommandEvent &e) boost::shared_ptr fs(wfs.lock()); if (!fs) return; fetchUrl(boost::weak_ptr(fs)); + BOOST_LOG_TRIVIAL(info) << "part skip: fetch url, get parts info files from printer."; }); } } @@ -550,10 +558,12 @@ void PartSkipDialog::OnFileSystemResult(wxCommandEvent &event){ InitDialogUI(); SetSimplebookPage(2); m_file_sys->Stop(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <<"part skip: on file system result success."; }else{ m_url_state = URL_TCP; SetSimplebookPage(1); m_file_sys->Stop(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ <<"part skip: on file system result failed."; } } @@ -670,6 +680,7 @@ bool PartSkipDialog::Show(bool show) void PartSkipDialog::InitDialogUI() { m_print_lock = true; + BOOST_LOG_TRIVIAL(info) << "part skip: lock parts info from printer."; m_scroll_sizer->Clear(true); m_all_checkbox->SetValue(false); m_parts_state.clear(); @@ -684,11 +695,15 @@ void PartSkipDialog::InitDialogUI() { m_canvas->SwitchDrag(false); m_canvas->SetZoomPercent(100); m_canvas->SetOffset(wxPoint(0, 0)); + + BOOST_LOG_TRIVIAL(info) << "part skip: load canvas pick image begin."; m_canvas->LoadPickImage(pick_img); + BOOST_LOG_TRIVIAL(info) << "part skip: load canvas pick image end."; ModelSettingHelper helper(slice_info); if (helper.Parse()) { - auto parse_result = helper.GetResults(); + int plate_idx = m_obj ? m_obj->m_plate_index : 0; + auto parse_result = helper.GetPlates()[plate_idx - 1].objects; for (const auto& part : parse_result) { m_parts_state[part.identify_id] = part.state; m_parts_name[part.identify_id] = part.name; @@ -741,31 +756,42 @@ void PartSkipDialog::InitDialogUI() { m_scroll_sizer->Add(line_sizer, 0, wxBOTTOM | wxEXPAND, FromDIP(12)); } m_canvas->UpdatePartsInfo(GetPartsInfo()); + BOOST_LOG_TRIVIAL(info) << "part skip: update canvas parts info."; } m_scroll_sizer->Layout(); UpdateCountLabel(); Refresh(); m_print_lock = false; + BOOST_LOG_TRIVIAL(info) << "part skip: unlock parts info from printer."; } void PartSkipDialog::UpdatePartsStateFromPrinter(MachineObject *obj) { - if (m_print_lock) return; + if (m_print_lock) { + BOOST_LOG_TRIVIAL(info) << "part skip: parts info from printer is locked."; + return; + } m_obj = obj; if (m_obj) { + bool update_flag = false; std::vector partskip_ids = m_obj->m_partskip_ids; for(auto part_id : partskip_ids) { - m_parts_state[part_id] = PartState::psSkipped; + if(m_parts_state[part_id] != PartState::psSkipped){ + m_parts_state[part_id] = PartState::psSkipped; + update_flag = true; + } + } + if(update_flag){ + m_canvas->UpdatePartsInfo(GetPartsInfo()); + UpdateDialogUI(); } - m_canvas->UpdatePartsInfo(GetPartsInfo()); - UpdateDialogUI(); } } void PartSkipDialog::UpdateDialogUI(){ if(m_parts_state.size() != m_scroll_sizer->GetItemCount()){ - BOOST_LOG_TRIVIAL(warning) << "m_parts_state and m_scroll_sizer mismatch."; + BOOST_LOG_TRIVIAL(warning) << "part skip: m_parts_state and m_scroll_sizer mismatch."; return; } @@ -839,30 +865,47 @@ void PartSkipDialog::OnApplyDialog(wxCommandEvent &event) m_partskip_ids.push_back(part_id); } } + + bool all_skipped = true; + for (auto [part_id, part_state] : m_parts_state) { + if (part_state == PartState::psUnCheck) all_skipped = false; + } + PartSkipConfirmDialog confirm_dialog(this); - confirm_dialog.SetMsgLabel(wxString::Format(_L("Skipping %d objects."), m_partskip_ids.size())); + if (all_skipped){ + confirm_dialog.SetMsgLabel(_L("Skipping all objects.")); + confirm_dialog.SetTipLabel(_L("The printing job will be stopped. Continue?")); + }else{ + confirm_dialog.SetMsgLabel(wxString::Format(_L("Skipping %d objects."), m_partskip_ids.size())); + confirm_dialog.SetTipLabel(_L("This action cannot be undone. Continue?")); + } if(confirm_dialog.ShowModal() == wxID_OK){ if (m_obj) { - BOOST_LOG_TRIVIAL(info) << "monitor: skipping "<< m_partskip_ids.size() <<" objects."; - - bool all_skipped = true; - for (auto [part_id, part_state] : m_parts_state) { - if (part_state == PartState::psUnCheck) all_skipped = false; - } + BOOST_LOG_TRIVIAL(info) << "part skip: skipping "<< m_partskip_ids.size() <<" objects."; if (all_skipped) { m_obj->command_task_abort(); + BOOST_LOG_TRIVIAL(info) << "part skip: command skip all parts, abort task."; } else { m_obj->command_task_partskip(m_partskip_ids); + BOOST_LOG_TRIVIAL(info) << "part skip: command skip " << m_partskip_ids.size() << " parts."; } EndModal(wxID_OK); } else { - BOOST_LOG_TRIVIAL(warning) << "machine object is null."; + BOOST_LOG_TRIVIAL(warning) << "part skip: machine object is null."; } } } +int PartSkipDialog::GetAllSkippedPartsNum() { + int skipped_cnt = 0; + for (auto& [part_id, part_state] : m_parts_state) { + if (part_state == PartState::psSkipped || part_state == PartState::psChecked) + skipped_cnt++; + } + return skipped_cnt; +} PartSkipConfirmDialog::PartSkipConfirmDialog(wxWindow *parent) : DPIDialog(parent, wxID_ANY, _L("Skip Objects"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) { @@ -886,9 +929,7 @@ PartSkipConfirmDialog::PartSkipConfirmDialog(wxWindow *parent) : DPIDialog(paren m_msg_label->Wrap( -1 ); m_msg_label->SetBackgroundColour(*wxWHITE); - - - auto m_tip_label = new Label(this, _L("This action cannot be undone. Continue?")); + m_tip_label = new Label(this, _L("This action cannot be undone. Continue?")); m_tip_label->Wrap(-1); m_tip_label->SetBackgroundColour(*wxWHITE); m_tip_label->SetForegroundColour(wxColor(92,92,92)); @@ -965,6 +1006,10 @@ void PartSkipConfirmDialog::SetMsgLabel(wxString msg){ m_msg_label->SetLabel(msg); } +void PartSkipConfirmDialog::SetTipLabel(wxString msg){ + m_tip_label->SetLabel(msg); +} + } } // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/PartSkipDialog.hpp b/src/slic3r/GUI/PartSkipDialog.hpp index 1428f15ee8..ef5cb743af 100644 --- a/src/slic3r/GUI/PartSkipDialog.hpp +++ b/src/slic3r/GUI/PartSkipDialog.hpp @@ -39,6 +39,7 @@ class PartSkipConfirmDialog : public DPIDialog private: protected: Label *m_msg_label; + Label *m_tip_label; Button *m_apply_button; public: @@ -48,6 +49,7 @@ public: void on_dpi_changed(const wxRect &suggested_rect); Button* GetConfirmButton(); void SetMsgLabel(wxString msg); + void SetTipLabel(wxString msg); bool Show(bool show); }; @@ -63,7 +65,7 @@ public: void SetSimplebookPage(int page); void InitSchedule(MachineObject *obj_); void InitDialogUI(); - + int GetAllSkippedPartsNum(); MachineObject *m_obj{nullptr}; @@ -91,6 +93,8 @@ public: Label* m_loading_label; Label* m_retry_label; + ScalableBitmap* m_retry_icon; + wxStaticBitmap* m_retry_bitmap; wxBoxSizer* m_sizer; wxBoxSizer* m_dlg_sizer; diff --git a/src/slic3r/GUI/SkipPartCanvas.cpp b/src/slic3r/GUI/SkipPartCanvas.cpp index 09e6987a7a..85c2cc6c6d 100644 --- a/src/slic3r/GUI/SkipPartCanvas.cpp +++ b/src/slic3r/GUI/SkipPartCanvas.cpp @@ -32,9 +32,47 @@ SkipPartCanvas::SkipPartCanvas(wxWindow *parent, const wxGLAttributes& dispAttrs void SkipPartCanvas::LoadPickImage(const std::string & path) { + auto ParseShapeId = [](cv::Mat image, const std::vector> &contours, const std::vector &hierarchy, int root_idx) -> uint32_t { + cv::Mat mask = cv::Mat::zeros(image.size(), CV_8UC1); + + cv::drawContours(mask, contours, root_idx, 255, cv::FILLED); + + int child = hierarchy[root_idx][2]; + while (child != -1) { + cv::drawContours(mask, contours, child, 0, cv::FILLED); + child = hierarchy[child][0]; + } + std::vector pixels; + for (int y = 0; y < image.rows; ++y) { + for (int x = 0; x < image.cols; ++x) { + if (mask.at(y, x)) { pixels.push_back(image.at(y, x)); } + } + } + + std::map> colorCount( + [](const cv::Vec3b &a, const cv::Vec3b &b) { return std::lexicographical_compare(a.val, a.val + 3, b.val, b.val + 3); }); + + for (auto &c : pixels) colorCount[c]++; + + cv::Vec3b main_color; + int max_count = 0; + int total_count = 0; + for (const auto &kv : colorCount) { + if (kv.second > max_count) { + max_count = kv.second; + main_color = kv.first; + } + total_count += kv.second; + } + + SkipIdHelper helper{main_color[2], main_color[1], main_color[0]}; + helper.reverse(); + return (max_count * 2 > total_count) ? helper.value : 0; + }; + parts_state_.clear(); - pick_parts_.clear(); parts_triangles_.clear(); + pick_parts_.clear(); int preffered_w{FromDIP(400)}, preffered_h{FromDIP(400)}; cv::Mat src_image = cv::imread(path, cv::IMREAD_UNCHANGED); cv::cvtColor(src_image, src_image, cv::COLOR_BGRA2BGR); // remove alpha @@ -52,35 +90,64 @@ void SkipPartCanvas::LoadPickImage(const std::string & path) cv::Mat mask; // convery to binary cv::threshold(gray, mask, 0, 255, cv::THRESH_BINARY); std::vector> pick_counters; - cv::findContours(mask, pick_counters, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_TC89_KCOS); - std::vector> polygon; - for (const auto& counter : pick_counters) { - cv::Point center_pos{0,0}; - for (const auto& pt : counter) { - center_pos += pt; + std::vector hierarchy; + cv::findContours(mask, pick_counters, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_TC89_KCOS); + auto compute_depth = [&](int idx) { + int depth = 0; + while (hierarchy[idx][3] != -1) { + depth++; + idx = hierarchy[idx][3]; } - center_pos = center_pos / static_cast(counter.size()); - auto id = GetIdAtImagePt(wxPoint(center_pos.x, center_pos.y)); + return depth; + }; + for (int i = 0; i < pick_counters.size(); ++i) { + int depth = compute_depth(i); + int parent = hierarchy[i][3]; + if (parent != -1) continue; + + auto id = ParseShapeId(pick_image_, pick_counters, hierarchy, i); if (id > 0) { - polygon.clear(); - polygon.emplace_back(std::vector{}); - for (const auto& pt : counter) { - polygon[0].push_back(FloatPoint{pt.x * 1.0f, pt.y * 1.0f}); + std::vector flat_points; + std::vector> polygon; + + // part body + { + polygon.emplace_back(); + for (const auto &pt : pick_counters[i]) { + FloatPoint fp{pt.x * 1.0f, pt.y * 1.0f}; + polygon.back().push_back(fp); + flat_points.push_back(fp); + } + int child = hierarchy[i][2]; + while (child != -1) { + polygon.emplace_back(); + for (const auto &pt : pick_counters[child]) { + FloatPoint fp{pt.x * 1.0f, pt.y * 1.0f}; + polygon.back().push_back(fp); + flat_points.push_back(fp); + } + child = hierarchy[child][0]; + } + std::vector indices = mapbox::earcut(polygon); + std::vector final_counter; + for (size_t j = 0; j < indices.size(); j += 3) { + final_counter.push_back(flat_points[indices[j]]); + final_counter.push_back(flat_points[indices[j + 1]]); + final_counter.push_back(flat_points[indices[j + 2]]); + } + + parts_triangles_[id].emplace_back(final_counter); } - std::vector indices = mapbox::earcut(polygon); - std::vector final_counter{}; - for (size_t i = 0; i < indices.size(); i += 3) { - FloatPoint a = polygon[0][indices[i]]; - FloatPoint b = polygon[0][indices[i+1]]; - FloatPoint c = polygon[0][indices[i+2]]; - final_counter.push_back(FloatPoint{a[0], a[1]}); - final_counter.push_back(FloatPoint{b[0], b[1]}); - final_counter.push_back(FloatPoint{c[0], c[1]}); + // part outlines + { + pick_parts_[id].emplace_back(pick_counters[i]); + int child = hierarchy[i][2]; + while (child != -1) { + pick_parts_[id].emplace_back(pick_counters[child]); + child = hierarchy[child][0]; + } } - parts_triangles_.emplace(id, final_counter); - pick_parts_.emplace(id, counter); - if (parts_state_.find(id) == parts_state_.end()) - parts_state_.emplace(id, psUnCheck); + if (parts_state_.find(id) == parts_state_.end()) parts_state_.emplace(id, psUnCheck); } } } @@ -220,13 +287,15 @@ void SkipPartCanvas::Render() if (part_info == parts_state_.end() || part_info->second != part_type) continue; glColor3f(1, 1, 1); - glBegin(GL_TRIANGLES); - for (size_t i = 0; i < contour.second.size(); i += 3) { - glVertex2f(contour.second[i][0], contour.second[i][1]); - glVertex2f(contour.second[i+1][0], contour.second[i+1][1]); - glVertex2f(contour.second[i+2][0], contour.second[i+2][1]); + for (const auto &contour_item : contour.second) { + glBegin(GL_TRIANGLES); + for (size_t i = 0; i < contour_item.size(); i += 3) { + glVertex2f(contour_item[i][0], contour_item[i][1]); + glVertex2f(contour_item[i + 1][0], contour_item[i + 1][1]); + glVertex2f(contour_item[i + 2][0], contour_item[i + 2][1]); + } + glEnd(); } - glEnd(); } for (const auto& contour : pick_parts_) { @@ -237,11 +306,11 @@ void SkipPartCanvas::Render() glColor3f(rgb.r(), rgb.g(), rgb.b()); glLineWidth(border_w); - glBegin(GL_LINE_LOOP); - for (const auto& pt : contour.second) { - glVertex2f(pt.x, pt.y); + for (const auto &contour_item : contour.second) { + glBegin(GL_LINE_LOOP); + for (const auto &pt : contour_item) { glVertex2f(pt.x, pt.y); } + glEnd(); } - glEnd(); } }; // draw unchecked shapes @@ -277,11 +346,11 @@ void SkipPartCanvas::Render() continue; glColor3f(bound.r(), bound.g(), bound.b()); glLineWidth(border_w); - glBegin(GL_LINE_LOOP); - for (const auto& pt : contour.second) { - glVertex2f(pt.x, pt.y); + for (const auto &contour_item : contour.second) { + glBegin(GL_LINE_LOOP); + for (const auto &pt : contour_item) { glVertex2f(pt.x, pt.y); } + glEnd(); } - glEnd(); } }; @@ -559,29 +628,41 @@ bool ModelSettingHelper::Parse() return true; } -std::vector ModelSettingHelper::GetResults() { - return context_.objects; -} - void XMLCALL ModelSettingHelper::StartElementHandler(void *userData, const XML_Char *name, const XML_Char **atts) { - ModelSettingHelper* self = static_cast(userData); - if (strcmp(name, "object") == 0) { + ModelSettingHelper *self = static_cast(userData); + if (strcmp(name, "plate") == 0) { + self->context_.current_plate = PlateInfo(); // start a new plate + self->context_.in_plate = true; + } else if (strcmp(name, "metadata") == 0 && self->context_.in_plate) { + std::string key, value; for (int i = 0; atts[i]; i += 2) { - if (strcmp(atts[i], "identify_id") == 0) { self->context_.temp_object.identify_id = atoi(atts[i + 1]); } - if (strcmp(atts[i], "name") == 0) { self->context_.temp_object.name = std::string(atts[i + 1]); } + if (strcmp(atts[i], "key") == 0) key = atts[i + 1]; + if (strcmp(atts[i], "value") == 0) value = atts[i + 1]; } + if (key == "index") { self->context_.current_plate.index = std::stoi(value); } + } else if (strcmp(name, "object") == 0 && self->context_.in_plate) { + ObjectInfo obj; + for (int i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "identify_id") == 0) obj.identify_id = atoi(atts[i + 1]); + if (strcmp(atts[i], "name") == 0) obj.name = atts[i + 1]; + } + self->context_.current_plate.objects.push_back(obj); } } void XMLCALL ModelSettingHelper::EndElementHandler(void *userData, const XML_Char *name) { - ModelSettingHelper* self = static_cast(userData); - if (strcmp(name, "object") == 0) { - self->context_.objects.push_back(self->context_.temp_object); + ModelSettingHelper *self = static_cast(userData); + if (strcmp(name, "plate") == 0 && self->context_.in_plate) { + self->context_.plates.push_back(self->context_.current_plate); + self->context_.current_plate = PlateInfo(); // reset + self->context_.in_plate = false; } } +std::vector ModelSettingHelper::GetPlates() { return context_.plates; } + void ModelSettingHelper::DataHandler(const XML_Char *s, int len) { // do nothing diff --git a/src/slic3r/GUI/SkipPartCanvas.hpp b/src/slic3r/GUI/SkipPartCanvas.hpp index 6f02510872..77dd4ffa42 100644 --- a/src/slic3r/GUI/SkipPartCanvas.hpp +++ b/src/slic3r/GUI/SkipPartCanvas.hpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -85,8 +84,8 @@ protected: private: wxGLContext* context_; cv::Mat pick_image_; - std::unordered_map> parts_triangles_; - std::unordered_map> pick_parts_; + std::unordered_map < uint32_t, std::vector>> parts_triangles_; + std::unordered_map < uint32_t, std::vector>> pick_parts_; std::unordered_map parts_state_; bool gl_inited_{false}; int zoom_percent_{100}; @@ -131,25 +130,35 @@ public: void log_errors(); }; -class ModelSettingHelper : public _BBS_3MF_Base { - struct ParseContext{ - std::vector objects; - ObjectInfo temp_object; +struct PlateInfo +{ + int index{-1}; + std::vector objects; +}; + +class ModelSettingHelper : public _BBS_3MF_Base +{ + struct ParseContext + { + std::vector plates; + PlateInfo current_plate; + ObjectInfo temp_object; + bool in_plate = false; }; public: - ModelSettingHelper(const std::string& path); + ModelSettingHelper(const std::string &path); + bool Parse(); + std::vector GetPlates(); - bool Parse(); - std::vector GetResults(); private: - std::string path_; + std::string path_; ParseContext context_; - void static XMLCALL StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts); - void static XMLCALL EndElementHandler(void* userData, const XML_Char* name); - void DataHandler(const XML_Char* s, int len); + static void XMLCALL StartElementHandler(void *userData, const XML_Char *name, const XML_Char **atts); + static void XMLCALL EndElementHandler(void *userData, const XML_Char *name); + void DataHandler(const XML_Char *s, int len); }; } diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp index 7763563b5c..8065d09f77 100644 --- a/src/slic3r/GUI/StatusPanel.cpp +++ b/src/slic3r/GUI/StatusPanel.cpp @@ -269,7 +269,8 @@ void PrintingTaskPanel::create_panel(wxWindow* parent) StateColor white_bg(std::pair(wxColour(255, 255, 255), StateColor::Disabled), std::pair(wxColour(255, 255, 255), StateColor::Pressed), std::pair(wxColour(255, 255, 255), StateColor::Hovered), std::pair(wxColour(255, 255, 255), StateColor::Enabled), std::pair(wxColour(255, 255, 255), StateColor::Normal)); - m_button_partskip = new Button(progress_lr_panel, ""); + + m_button_partskip = new Button(progress_lr_panel, wxEmptyString, "print_control_partskip_disable", 0, 20, wxID_ANY); m_button_partskip->Enable(false); m_button_partskip->Hide(); m_button_partskip->SetBackgroundColor(white_bg); @@ -278,7 +279,7 @@ void PrintingTaskPanel::create_panel(wxWindow* parent) m_button_partskip->SetFont(Label::Body_12); m_button_partskip->SetCornerRadius(0); m_button_partskip->SetToolTip(_L("Parts Skip")); - m_button_partskip->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { m_button_partskip->SetIcon("print_control_partskip"); }); + m_button_partskip->Bind(wxEVT_ENTER_WINDOW, [this](auto &e) { m_button_partskip->SetIcon("print_control_partskip_hover"); }); m_button_partskip->Bind(wxEVT_LEAVE_WINDOW, [this](auto &e) { m_button_partskip->SetIcon("print_control_partskip"); }); m_button_pause_resume = new ScalableButton(progress_lr_panel, wxID_ANY, "print_control_pause", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER,true); @@ -648,15 +649,13 @@ void PrintingTaskPanel::update_machine_object(MachineObject* obj){ void PrintingTaskPanel::enable_partskip_button(bool enable) { - if(m_obj){ - if( m_obj->is_support_partskip ){ - m_button_partskip->Show(); - }else{ - m_button_partskip->Hide(); - } + int stage = 0; + bool in_calibration_mode = false; + if( m_obj && (m_obj->print_type == "system" || CalibUtils::get_calib_mode_by_name(m_obj->subtask_name, stage) != CalibMode::Calib_None)){ + in_calibration_mode = true; } - if (!enable) { + if (!enable || in_calibration_mode) { m_button_partskip->Enable(false); m_button_partskip->SetLabel(""); m_button_partskip->SetIcon("print_control_partskip_disable"); @@ -1971,6 +1970,19 @@ void StatusPanel::on_market_retry(wxCommandEvent &event) } } +void StatusPanel::update_partskip_button(MachineObject *obj) { + if (!obj) return; + + m_project_task_panel->update_machine_object(obj); + auto partskip_button = m_project_task_panel->get_partskip_button(); + if( obj->is_support_partskip ){ + partskip_button->Show(); + }else{ + partskip_button->Hide(); + } + BOOST_LOG_TRIVIAL(info) << "part skip: is_support_partskip: "<< obj->is_support_partskip; +} + void StatusPanel::on_subtask_partskip(wxCommandEvent &event) { if (m_partskip_dlg == nullptr) { @@ -1979,7 +1991,13 @@ void StatusPanel::on_subtask_partskip(wxCommandEvent &event) auto dm = GUI::wxGetApp().getDeviceManager(); m_partskip_dlg->InitSchedule(dm->get_selected_machine()); - m_partskip_dlg->ShowModal(); + BOOST_LOG_TRIVIAL(info) << "part skip: initial part skip dialog."; + if(m_partskip_dlg->ShowModal() == wxID_OK){ + int cnt = m_partskip_dlg->GetAllSkippedPartsNum(); + m_project_task_panel->set_part_skipped_count(cnt); + m_project_task_panel->set_part_skipped_dirty(5); + BOOST_LOG_TRIVIAL(info) << "part skip: prepare to filter printer dirty data."; + } } void StatusPanel::on_subtask_pause_resume(wxCommandEvent &event) @@ -3126,6 +3144,7 @@ void StatusPanel::update_subtask(MachineObject *obj) } update_model_info(); + update_partskip_button(obj); if (obj->is_system_printing() || obj->is_in_calibration()) { @@ -3267,11 +3286,17 @@ void StatusPanel::update_partskip_subtask(MachineObject *obj){ if (!obj) return; if (!obj->subtask_) return; - m_project_task_panel->update_machine_object(obj); - auto partskip_button = m_project_task_panel->get_partskip_button(); if (partskip_button) { - int part_cnt = obj->m_partskip_ids.size(); + int part_cnt = 0; + if(m_project_task_panel->get_part_skipped_dirty() > 0){ + m_project_task_panel->set_part_skipped_dirty(m_project_task_panel->get_part_skipped_dirty() - 1); + part_cnt = m_project_task_panel->get_part_skipped_count(); + BOOST_LOG_TRIVIAL(info) << "part skip: stop recv printer dirty data."; + }else{ + part_cnt = obj->m_partskip_ids.size(); + BOOST_LOG_TRIVIAL(info) << "part skip: recv printer normal data."; + } if (part_cnt > 0) partskip_button->SetLabel(wxString::Format(_L("(%d)"), part_cnt)); else diff --git a/src/slic3r/GUI/StatusPanel.hpp b/src/slic3r/GUI/StatusPanel.hpp index 6afc194cd8..a300d1682e 100644 --- a/src/slic3r/GUI/StatusPanel.hpp +++ b/src/slic3r/GUI/StatusPanel.hpp @@ -205,6 +205,10 @@ private: std::vector m_score_star; bool m_star_count_dirty = false; + // partskip button + int m_part_skipped_count{ 0 }; + int m_part_skipped_dirty{ 0 }; + ProgressBar* m_gauge_progress; Label* m_error_text; PrintingTaskType m_type; @@ -251,6 +255,10 @@ public: std::vector &get_score_star() { return m_score_star; } bool get_star_count_dirty() { return m_star_count_dirty; } void set_star_count_dirty(bool dirty) { m_star_count_dirty = dirty; } + int get_part_skipped_count() { return m_part_skipped_count; } + void set_part_skipped_count(int count) { m_part_skipped_count = count; } + int get_part_skipped_dirty() { return m_part_skipped_dirty; } + void set_part_skipped_dirty(int dirty) { m_part_skipped_dirty = dirty; } void set_has_reted_text(bool has_rated); void paint(wxPaintEvent&); }; @@ -631,6 +639,9 @@ protected: void update_camera_state(MachineObject* obj); bool show_vcamera = false; + // partskip button + void update_partskip_button(MachineObject* obj); + public: void update_error_message();