From 2dc2d8252d91ccbc832da94bab60947a322b34c6 Mon Sep 17 00:00:00 2001 From: Stone Li Date: Wed, 31 Aug 2022 16:32:56 +0800 Subject: [PATCH] NEW: support software limit of axis control Change-Id: I0d241aeddeed112b21ed576ce793c3e9f061c923 Signed-off-by: Stone Li --- resources/images/monitor_axis_home_icon.svg | 3 + src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/DeviceManager.cpp | 25 ++- src/slic3r/GUI/DeviceManager.hpp | 3 + src/slic3r/GUI/RecenterDialog.cpp | 183 ++++++++++++++++++++ src/slic3r/GUI/RecenterDialog.hpp | 38 ++++ src/slic3r/GUI/StatusPanel.cpp | 66 ++++++- src/slic3r/GUI/StatusPanel.hpp | 2 + 8 files changed, 315 insertions(+), 7 deletions(-) create mode 100644 resources/images/monitor_axis_home_icon.svg create mode 100644 src/slic3r/GUI/RecenterDialog.cpp create mode 100644 src/slic3r/GUI/RecenterDialog.hpp diff --git a/resources/images/monitor_axis_home_icon.svg b/resources/images/monitor_axis_home_icon.svg new file mode 100644 index 000000000..99a5a5b3b --- /dev/null +++ b/resources/images/monitor_axis_home_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 2b6a3bb7b..208bcc969 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -340,6 +340,8 @@ set(SLIC3R_GUI_SOURCES GUI/DesktopIntegrationDialog.hpp GUI/PublishDialog.cpp GUI/PublishDialog.hpp + GUI/RecenterDialog.cpp + GUI/RecenterDialog.hpp GUI/BindDialog.cpp GUI/BindDialog.hpp GUI/SelectMachine.hpp diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index 18d23148f..3d80fa896 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -356,6 +356,7 @@ MachineObject::MachineObject(NetworkAgent* agent, std::string name, std::string mc_print_percent = 0; mc_print_sub_stage = 0; mc_left_time = 0; + home_flag = -1; printing_speed_lvl = PrintingSpeedLevel::SPEED_LEVEL_INVALID; } @@ -1026,6 +1027,22 @@ bool MachineObject::is_system_printing() return false; } +bool MachineObject::is_axis_at_home(std::string axis) +{ + if (home_flag < 0) + return true; + + if (axis == "X") { + return home_flag & 1 == 1; + } else if (axis == "Y") { + return home_flag >> 1 & 1 == 1; + } else if (axis == "Z") { + return home_flag >> 2 & 1 == 1; + } else { + return true; + } +} + wxString MachineObject::get_curr_stage() { if (stage_list_info.empty()) { @@ -1399,11 +1416,11 @@ int MachineObject::command_set_printing_speed(PrintingSpeedLevel lvl) int MachineObject::command_axis_control(std::string axis, double unit, double value, int speed) { - char cmd[64]; + char cmd[256]; if (axis.compare("X") == 0 || axis.compare("Y") == 0 || axis.compare("Z") == 0) { - sprintf(cmd, "G91 \nG0 %s%0.1f F%d\n", axis.c_str(), value * unit, speed); + sprintf(cmd, "M211 S \nM211 X1 Y1 Z1\nM1002 push_ref_mode\nG91 \nG1 %s%0.1f F%d\nM1002 pop_ref_mode\nM211 R\n", axis.c_str(), value * unit, speed); } else if (axis.compare("E") == 0) { sprintf(cmd, "M83 \nG0 %s%0.1f F%d\n", axis.c_str(), value * unit, speed); @@ -1799,6 +1816,10 @@ int MachineObject::parse_json(std::string payload) print_type = jj["print_type"].get(); } + if (jj.contains("home_flag")) { + home_flag = jj["home_flag"].get(); + } + if (jj.contains("mc_remaining_time")) { if (jj["mc_remaining_time"].is_string()) mc_left_time = stoi(j["print"]["mc_remaining_time"].get()) * 60; diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index 8b769791c..65c0e2dd0 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -459,6 +459,7 @@ public: int mc_print_percent; /* left print progess in percent */ int mc_left_time; /* left time in seconds */ int last_mc_print_stage; + int home_flag; bool is_system_printing(); int print_error; @@ -467,6 +468,8 @@ public: int m_push_count = 0; bool calibration_done { false }; + bool is_axis_at_home(std::string axis); + wxString get_curr_stage(); // return curr stage index of stage list int get_curr_stage_idx(); diff --git a/src/slic3r/GUI/RecenterDialog.cpp b/src/slic3r/GUI/RecenterDialog.cpp new file mode 100644 index 000000000..a3545c82c --- /dev/null +++ b/src/slic3r/GUI/RecenterDialog.cpp @@ -0,0 +1,183 @@ +#include "RecenterDialog.hpp" +#include +#include +#include +#include + +#define BORDER FromDIP(25) +#define DRAW_PANEL_SIZE wxSize(FromDIP(475), FromDIP(100)) + +wxString hint1 = _L("Please perform \"recenter "); +wxString hint2 = _L("\" action to locate the current position of the extruder to prevent device breakdown by moving the axis out of line."); + +namespace Slic3r { namespace GUI { +RecenterDialog::RecenterDialog(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style) + : DPIDialog(parent, id, _L("Reminder"), pos, size, style) +{ + std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); + SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); + + init_bitmap(); + + auto* main_sizer = new wxBoxSizer(wxVERTICAL); + auto* button_sizer = new wxBoxSizer(wxHORIZONTAL); + + wxPanel* m_line_top = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL); + m_line_top->SetBackgroundColour(wxColour(166, 169, 170)); + + m_button_confirm = new Button(this, _L("Center")); + m_button_confirm->SetFont(Label::Body_12); + m_button_confirm->SetMinSize(wxSize(-1, FromDIP(24))); + m_button_confirm->SetCornerRadius(FromDIP(12)); + StateColor confirm_btn_bg(std::pair(wxColour(61, 203, 115), StateColor::Hovered), + std::pair(wxColour(0, 174, 66), StateColor::Normal)); + m_button_confirm->SetBackgroundColor(confirm_btn_bg); + m_button_confirm->SetBorderColor(wxColour(0, 174, 66)); + m_button_confirm->SetTextColor(*wxWHITE); + + m_button_close = new Button(this, _L("Close")); + m_button_close->SetFont(Label::Body_12); + m_button_close->SetMinSize(wxSize(-1, FromDIP(24))); + m_button_close->SetCornerRadius(FromDIP(12)); + StateColor close_btn_bg(std::pair(wxColour(206, 206, 206), StateColor::Hovered), + std::pair(*wxWHITE, StateColor::Normal)); + m_button_close->SetBackgroundColor(close_btn_bg); + m_button_close->SetBorderColor(wxColour(38, 46, 48)); + m_button_close->SetTextColor(wxColour(38, 46, 48)); + + button_sizer->AddStretchSpacer(); + button_sizer->Add(m_button_confirm); + button_sizer->AddSpacer(FromDIP(20)); + button_sizer->Add(m_button_close); + + main_sizer->Add(m_line_top, 0, wxEXPAND, 0); + main_sizer->AddSpacer(DRAW_PANEL_SIZE.y); + main_sizer->Add(button_sizer, 0, wxBOTTOM | wxRIGHT | wxEXPAND, BORDER); + + SetSizer(main_sizer); + + CenterOnParent(); + + this->SetSize(wxSize(DRAW_PANEL_SIZE.x, -1)); + this->SetMinSize(wxSize(DRAW_PANEL_SIZE.x, -1)); + Fit(); + this->Bind(wxEVT_PAINT, &RecenterDialog::OnPaint, this); + m_button_confirm->Bind(wxEVT_BUTTON, &RecenterDialog::on_button_confirm, this); + m_button_close->Bind(wxEVT_BUTTON, &RecenterDialog::on_button_close, this); +} + +RecenterDialog::~RecenterDialog() {} + +void RecenterDialog::init_bitmap() { + m_home_bmp = ScalableBitmap(this, "monitor_axis_home_icon", 30); +} + +void RecenterDialog::OnPaint(wxPaintEvent& event){ + wxPaintDC dc(this); + wxGCDC dc2(dc); + render(dc2); +} + +void RecenterDialog::render(wxDC& dc) { + wxSize size = GetSize(); + + dc.SetFont(Label::Body_14); + dc.SetTextForeground(*wxBLACK); + wxPoint pos_start = wxPoint(BORDER, BORDER); + + wxSize hint1_size = dc.GetTextExtent(hint1); + wxPoint pos_hint1 = pos_start; + pos_hint1.y += (m_home_bmp.GetBmpWidth() - hint1_size.y) / 2; + dc.DrawText(hint1, pos_hint1); + + wxPoint pos_bmp = pos_start; + pos_bmp.x += hint1_size.x; + dc.DrawBitmap(m_home_bmp.bmp(), pos_bmp); + + wxSize hint2_size = dc.GetTextExtent(hint2); + wxPoint pos_hint2 = pos_hint1; + pos_hint2.x = pos_hint2.x + hint1_size.x + m_home_bmp.GetBmpWidth(); + + if (hint2_size.x + pos_hint2.x + BORDER > DRAW_PANEL_SIZE.x) { + bool is_ch = false; + if (hint2[0] > 0x80 && hint2[1] > 0x80) + is_ch = true; + + wxString fisrt_line; + wxString remaining_line; + + wxString count_txt; + int new_line_pos = 0; + for (int i = 0; i < hint2.length(); i++) { + count_txt += hint2[i]; + auto text_size = dc.GetTextExtent(count_txt); + if (text_size.x + pos_hint2.x + BORDER < DRAW_PANEL_SIZE.x) + { + if (hint2[i] == ' ' || hint2[i] == '\n') + new_line_pos = i; + } + else { + if (!is_ch) { + fisrt_line = hint2.SubString(0, new_line_pos); + remaining_line = hint2.SubString(new_line_pos + 1, hint2.length()); + break; + } + else { + fisrt_line = hint2.SubString(0, i); + remaining_line = hint2.SubString(i, hint2.length()); + break; + } + count_txt = ""; + } + } + dc.DrawText(fisrt_line, pos_hint2); + + + count_txt = ""; + new_line_pos = 0; + for (int i = 0; i < remaining_line.length(); i++) { + count_txt += remaining_line[i]; + auto text_size = dc.GetTextExtent(count_txt); + if (text_size.x + BORDER + BORDER < DRAW_PANEL_SIZE.x) + { + if (remaining_line[i] == ' ' || remaining_line[i] == '\n') + new_line_pos = i; + } + else { + if (!is_ch){ + remaining_line[new_line_pos] = '\n'; + } + else { + remaining_line.insert(i, '\n'); + } + count_txt = ""; + } + } + wxPoint pos_txt = pos_hint1; + pos_txt.y += dc.GetCharHeight(); + dc.DrawText(remaining_line, pos_txt); + } + else + dc.DrawText(hint2, pos_hint2); +} + +void RecenterDialog::on_button_confirm(wxCommandEvent& event) { + if (this->IsModal()) + this->EndModal(wxID_OK); + else + this->Close(); +} + +void RecenterDialog::on_button_close(wxCommandEvent& event) { + this->Close(); +} + +void RecenterDialog::on_dpi_changed(const wxRect& suggested_rect) { + init_bitmap(); + m_button_confirm->SetMinSize(wxSize(-1, FromDIP(24))); + m_button_confirm->SetCornerRadius(FromDIP(12)); + m_button_close->SetMinSize(wxSize(-1, FromDIP(24))); + m_button_close->SetCornerRadius(FromDIP(12)); +} + +}} // namespace Slic3r::GUI \ No newline at end of file diff --git a/src/slic3r/GUI/RecenterDialog.hpp b/src/slic3r/GUI/RecenterDialog.hpp new file mode 100644 index 000000000..566c1d989 --- /dev/null +++ b/src/slic3r/GUI/RecenterDialog.hpp @@ -0,0 +1,38 @@ +#ifndef slic3r_GUI_RecenterDialog_hpp_ +#define slic3r_GUI_RecenterDialog_hpp_ + +#include "GUI_Utils.hpp" +#include +#include "Widgets/Button.hpp" +#include + +namespace Slic3r { namespace GUI { +class RecenterDialog : public DPIDialog +{ +private: + wxStaticText* m_staticText_hint; + Button* m_button_confirm; + Button* m_button_close; + wxStaticBitmap* m_bitmap_home; + ScalableBitmap m_home_bmp; + + void init_bitmap(); + void OnPaint(wxPaintEvent& event); + void render(wxDC& dc); + void on_button_confirm(wxCommandEvent& event); + void on_button_close(wxCommandEvent& event); + void on_dpi_changed(const wxRect& suggested_rect) override; + +public: + RecenterDialog(wxWindow* parent, + wxWindowID id = wxID_ANY, + const wxString& title = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxCLOSE_BOX | wxCAPTION); + + ~RecenterDialog(); +}; +}} // namespace Slic3r::GUI + +#endif \ No newline at end of file diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp index 0544e4f4c..cc6c81c10 100644 --- a/src/slic3r/GUI/StatusPanel.cpp +++ b/src/slic3r/GUI/StatusPanel.cpp @@ -9,7 +9,7 @@ #include "slic3r/Utils/Http.hpp" #include "libslic3r/Thread.hpp" - +#include "RecenterDialog.hpp" namespace Slic3r { namespace GUI { @@ -1355,6 +1355,12 @@ void StatusPanel::update(MachineObject *obj) m_machine_ctrl_panel->Thaw(); } +void StatusPanel::show_recenter_dialog() { + RecenterDialog dlg(this); + if (dlg.ShowModal() == wxID_OK) + obj->command_go_home(); +} + void StatusPanel::show_error_message(wxString msg) { m_error_text->SetLabel(msg); @@ -1944,6 +1950,27 @@ void StatusPanel::reset_printing_values() void StatusPanel::on_axis_ctrl_xy(wxCommandEvent &event) { if (!obj) return; + + //check is at home + if (event.GetInt() == 1 + || event.GetInt() == 3 + || event.GetInt() == 5 + || event.GetInt() == 7) { + if (!obj->is_axis_at_home("X")) { + BOOST_LOG_TRIVIAL(info) << "axis x is not at home"; + show_recenter_dialog(); + return; + } + } else if (event.GetInt() == 0 + || event.GetInt() == 2 + || event.GetInt() == 4 + || event.GetInt() == 6) { + if (!obj->is_axis_at_home("Y")) { + BOOST_LOG_TRIVIAL(info) << "axis y is not at home"; + show_recenter_dialog(); + return; + } + } if (event.GetInt() == 0) { obj->command_axis_control("Y", 1.0, 10.0f, 3000); } if (event.GetInt() == 1) { obj->command_axis_control("X", 1.0, -10.0f, 3000); } if (event.GetInt() == 2) { obj->command_axis_control("Y", 1.0, -10.0f, 3000); } @@ -1955,24 +1982,53 @@ void StatusPanel::on_axis_ctrl_xy(wxCommandEvent &event) if (event.GetInt() == 8) { obj->command_go_home(); } } +bool StatusPanel::check_axis_z_at_home(MachineObject* obj) +{ + if (obj) { + if (!obj->is_axis_at_home("Z")) { + BOOST_LOG_TRIVIAL(info) << "axis z is not at home"; + show_recenter_dialog(); + return false; + } + return true; + } + return false; +} + void StatusPanel::on_axis_ctrl_z_up_10(wxCommandEvent &event) { - if (obj) obj->command_axis_control("Z", 1.0, -10.0f, 900); + if (obj) { + if (!check_axis_z_at_home(obj)) + return; + obj->command_axis_control("Z", 1.0, -10.0f, 900); + } } void StatusPanel::on_axis_ctrl_z_up_1(wxCommandEvent &event) { - if (obj) obj->command_axis_control("Z", 1.0, -1.0f, 900); + if (obj) { + if (!check_axis_z_at_home(obj)) + return; + obj->command_axis_control("Z", 1.0, -1.0f, 900); + } } void StatusPanel::on_axis_ctrl_z_down_1(wxCommandEvent &event) { - if (obj) obj->command_axis_control("Z", 1.0, 1.0f, 900); + if (obj) { + if (!check_axis_z_at_home(obj)) + return; + obj->command_axis_control("Z", 1.0, 1.0f, 900); + } } void StatusPanel::on_axis_ctrl_z_down_10(wxCommandEvent &event) { - if (obj) obj->command_axis_control("Z", 1.0, 10.0f, 900); + if (obj) { + if (!check_axis_z_at_home(obj)) + return; + obj->command_axis_control("Z", 1.0, 10.0f, 900); + } } void StatusPanel::on_axis_ctrl_e_up_10(wxCommandEvent &event) diff --git a/src/slic3r/GUI/StatusPanel.hpp b/src/slic3r/GUI/StatusPanel.hpp index 39d1efea5..4d4f4e448 100644 --- a/src/slic3r/GUI/StatusPanel.hpp +++ b/src/slic3r/GUI/StatusPanel.hpp @@ -277,8 +277,10 @@ protected: void on_subtask_clean(wxCommandEvent &event); void show_error_message(wxString msg); void error_info_reset(); + void show_recenter_dialog(); /* axis control */ + bool check_axis_z_at_home(MachineObject* obj); void on_axis_ctrl_xy(wxCommandEvent &event); void on_axis_ctrl_z_up_10(wxCommandEvent &event); void on_axis_ctrl_z_up_1(wxCommandEvent &event);