mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-16 18:12:10 +00:00
FIX: partskip button display bug && cavas update bug
Jira: [STUDIO-12687] Change-Id: Ibb42dab945be9b9b4b8b8ac8f2c268960d553325 (cherry picked from commit 15d8fb70c93d243a1592c050302e76867ed6582c)
This commit is contained in:
@@ -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<int> 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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<std::vector<cv::Point>> &contours, const std::vector<cv::Vec4i> &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<cv::Vec3b> pixels;
|
||||
for (int y = 0; y < image.rows; ++y) {
|
||||
for (int x = 0; x < image.cols; ++x) {
|
||||
if (mask.at<uchar>(y, x)) { pixels.push_back(image.at<cv::Vec3b>(y, x)); }
|
||||
}
|
||||
}
|
||||
|
||||
std::map<cv::Vec3b, int, std::function<bool(const cv::Vec3b &, const cv::Vec3b &)>> 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<std::vector<cv::Point>> pick_counters;
|
||||
cv::findContours(mask, pick_counters, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_TC89_KCOS);
|
||||
std::vector<std::vector<FloatPoint>> polygon;
|
||||
for (const auto& counter : pick_counters) {
|
||||
cv::Point center_pos{0,0};
|
||||
for (const auto& pt : counter) {
|
||||
center_pos += pt;
|
||||
std::vector<cv::Vec4i> 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<int>(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<FloatPoint>{});
|
||||
for (const auto& pt : counter) {
|
||||
polygon[0].push_back(FloatPoint{pt.x * 1.0f, pt.y * 1.0f});
|
||||
std::vector<FloatPoint> flat_points;
|
||||
std::vector<std::vector<FloatPoint>> 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<uint32_t> indices = mapbox::earcut<uint32_t>(polygon);
|
||||
std::vector<FloatPoint> 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<uint32_t> indices = mapbox::earcut<uint32_t>(polygon);
|
||||
std::vector<FloatPoint> 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<ObjectInfo> ModelSettingHelper::GetResults() {
|
||||
return context_.objects;
|
||||
}
|
||||
|
||||
void XMLCALL ModelSettingHelper::StartElementHandler(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
ModelSettingHelper* self = static_cast<ModelSettingHelper*>(userData);
|
||||
if (strcmp(name, "object") == 0) {
|
||||
ModelSettingHelper *self = static_cast<ModelSettingHelper *>(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<ModelSettingHelper*>(userData);
|
||||
if (strcmp(name, "object") == 0) {
|
||||
self->context_.objects.push_back(self->context_.temp_object);
|
||||
ModelSettingHelper *self = static_cast<ModelSettingHelper *>(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<PlateInfo> ModelSettingHelper::GetPlates() { return context_.plates; }
|
||||
|
||||
void ModelSettingHelper::DataHandler(const XML_Char *s, int len)
|
||||
{
|
||||
// do nothing
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <wx/textctrl.h>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <expat.h>
|
||||
#include <libslic3r/Color.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
@@ -85,8 +84,8 @@ protected:
|
||||
private:
|
||||
wxGLContext* context_;
|
||||
cv::Mat pick_image_;
|
||||
std::unordered_map<uint32_t, std::vector<FloatPoint>> parts_triangles_;
|
||||
std::unordered_map<uint32_t, std::vector<cv::Point>> pick_parts_;
|
||||
std::unordered_map < uint32_t, std::vector<std::vector<FloatPoint>>> parts_triangles_;
|
||||
std::unordered_map < uint32_t, std::vector<std::vector<cv::Point>>> pick_parts_;
|
||||
std::unordered_map<uint32_t, PartState> 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<ObjectInfo> objects;
|
||||
ObjectInfo temp_object;
|
||||
struct PlateInfo
|
||||
{
|
||||
int index{-1};
|
||||
std::vector<ObjectInfo> objects;
|
||||
};
|
||||
|
||||
class ModelSettingHelper : public _BBS_3MF_Base
|
||||
{
|
||||
struct ParseContext
|
||||
{
|
||||
std::vector<PlateInfo> 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<PlateInfo> GetPlates();
|
||||
|
||||
bool Parse();
|
||||
std::vector<ObjectInfo> 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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -269,7 +269,8 @@ void PrintingTaskPanel::create_panel(wxWindow* parent)
|
||||
StateColor white_bg(std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Disabled), std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Pressed),
|
||||
std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Hovered), std::pair<wxColour, int>(wxColour(255, 255, 255), StateColor::Enabled),
|
||||
std::pair<wxColour, int>(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
|
||||
|
||||
@@ -205,6 +205,10 @@ private:
|
||||
std::vector<ScalableButton *> 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<ScalableButton *> &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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user