diff --git a/resources/images/monitor_axis_home_icon.svg b/resources/images/monitor_axis_home_icon.svg
new file mode 100644
index 0000000000..99a5a5b3bf
--- /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 2b6a3bb7b7..208bcc9695 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 18d23148f8..3d80fa8962 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 8b769791c2..65c0e2dd02 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 0000000000..a3545c82ca
--- /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 0000000000..566c1d9892
--- /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 0544e4f4c5..cc6c81c106 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 39d1efea5f..4d4f4e4485 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);