diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index d9db4d6a77..cddc8ad680 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -348,6 +348,8 @@ set(SLIC3R_GUI_SOURCES GUI/ReleaseNote.cpp GUI/Calibration.hpp GUI/Calibration.cpp + GUI/PrintOptionsDialog.hpp + GUI/PrintOptionsDialog.cpp Utils/json_diff.hpp Utils/json_diff.cpp GUI/KBShortcutsDialog.hpp diff --git a/src/slic3r/GUI/DeviceManager.cpp b/src/slic3r/GUI/DeviceManager.cpp index a635749666..f6a0c824b8 100644 --- a/src/slic3r/GUI/DeviceManager.cpp +++ b/src/slic3r/GUI/DeviceManager.cpp @@ -1388,6 +1388,31 @@ int MachineObject::command_ipcam_timelapse(bool on_off) return this->publish_json(j.dump()); } +int MachineObject::command_xcam_control(std::string module_name, bool on_off, bool print_halt) +{ + json j; + j["xcam"]["command"] = "xcam_control_set"; + j["xcam"]["sequence_id"] = std::to_string(MachineObject::m_sequence_id++); + j["xcam"]["module_name"] = module_name; + j["xcam"]["control"] = on_off; + j["xcam"]["print_halt"] = print_halt; + return this->publish_json(j.dump()); +} + +int MachineObject::command_xcam_control_first_layer_inspector(bool on_off, bool print_halt) +{ + xcam_first_layer_inspector = on_off; + xcam_first_layer_hold_count = HOLD_COUNT_MAX; + return command_xcam_control("first_layer_inspector", on_off, print_halt); +} + +int MachineObject::command_xcam_control_spaghetti_detector(bool on_off, bool print_halt) +{ + xcam_spaghetti_detector = on_off; + xcam_spaghetti_print_halt = print_halt; + xcam_spaghetti_hold_count = HOLD_COUNT_MAX; + return command_xcam_control("spaghetti_detector", on_off, print_halt); +} void MachineObject::set_bind_status(std::string status) { @@ -1973,6 +1998,32 @@ int MachineObject::parse_json(std::string payload) catch (...) { ; } + + try { + if (jj.contains("xcam")) { + if (xcam_first_layer_hold_count > 0) + xcam_first_layer_hold_count--; + else { + if (jj["xcam"].contains("first_layer_inspector")) { + xcam_first_layer_inspector = jj["xcam"]["first_layer_inspector"].get(); + } + } + + if (xcam_spaghetti_hold_count > 0) { + xcam_spaghetti_hold_count--; + } else { + if (jj["xcam"].contains("spaghetti_detector")) { + xcam_spaghetti_detector = jj["xcam"]["spaghetti_detector"].get(); + } + if (jj["xcam"].contains("print_halt")) { + xcam_spaghetti_print_halt = jj["xcam"]["print_halt"].get(); + } + } + } + } + catch (...) { + ; + } #pragma endregion #pragma region hms @@ -2249,6 +2300,18 @@ int MachineObject::parse_json(std::string payload) BOOST_LOG_TRIVIAL(warning) << "ams_filament_setting, can not find in amsList, ams_id=" << ams_id; } } + } else if (jj["command"].get() == "xcam_control_set") { + if (jj.contains("module_name") && jj.contains("control")) { + if (jj["module_name"].get() == "first_layer_inspector") { + xcam_first_layer_inspector = jj["control"].get(); + xcam_first_layer_hold_count = HOLD_COUNT_MAX; + } else if (jj["module_name"].get() == "spaghetti_detector") { + xcam_spaghetti_detector = jj["control"].get(); + xcam_spaghetti_hold_count = HOLD_COUNT_MAX; + if (jj.contains("print_halt")) + xcam_spaghetti_print_halt = jj["print_halt"].get(); + } + } } } } diff --git a/src/slic3r/GUI/DeviceManager.hpp b/src/slic3r/GUI/DeviceManager.hpp index 7c2472d7b9..d67d9af152 100644 --- a/src/slic3r/GUI/DeviceManager.hpp +++ b/src/slic3r/GUI/DeviceManager.hpp @@ -21,6 +21,8 @@ #define FILAMENT_DEF_TEMP 220 #define FILAMENT_MIN_TEMP 120 +#define HOLD_COUNT_MAX 3 + inline int correct_filament_temperature(int filament_temp) { int temp = std::min(filament_temp, FILAMENT_MAX_TEMP); @@ -159,7 +161,7 @@ public: AmsStep step_state; AmsRfidState rfid_state; - void set_hold_count() { hold_count = 3; } + void set_hold_count() { hold_count = HOLD_COUNT_MAX; } void update_color_from_str(std::string color); wxColour get_color(); @@ -453,6 +455,11 @@ public: bool camera_recording { false }; bool camera_timelapse { false }; bool camera_has_sdcard { false }; + bool xcam_first_layer_inspector { false }; + int xcam_first_layer_hold_count = 0; + bool xcam_spaghetti_detector { false }; + bool xcam_spaghetti_print_halt{ false }; + int xcam_spaghetti_hold_count = 0; /* HMS */ std::vector hms_list; @@ -526,6 +533,9 @@ public: // camera control int command_ipcam_record(bool on_off); int command_ipcam_timelapse(bool on_off); + int command_xcam_control(std::string module_name, bool on_off, bool print_halt); + int command_xcam_control_first_layer_inspector(bool on_off, bool print_halt); + int command_xcam_control_spaghetti_detector(bool on_off, bool print_halt); /* common apis */ inline bool is_local() { return !dev_ip.empty(); } diff --git a/src/slic3r/GUI/PrintOptionsDialog.cpp b/src/slic3r/GUI/PrintOptionsDialog.cpp new file mode 100644 index 0000000000..aee32515d7 --- /dev/null +++ b/src/slic3r/GUI/PrintOptionsDialog.cpp @@ -0,0 +1,137 @@ +#include "PrintOptionsDialog.hpp" +#include "I18N.hpp" + +#include "libslic3r/Utils.hpp" + +#define DLG_SIZE (wxSize(FromDIP(360), FromDIP(160))) + +static const wxColour STATIC_BOX_LINE_COL = wxColour(238, 238, 238); + +namespace Slic3r { namespace GUI { + +PrintOptionsDialog::PrintOptionsDialog(wxWindow* parent) + : DPIDialog(parent, wxID_ANY, _L("Print Options"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) +{ + this->SetDoubleBuffered(true); + std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); + SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); + + SetBackgroundColour(*wxWHITE); + + this->SetMinSize(DLG_SIZE); + this->SetSize(DLG_SIZE); + + auto m_options_sizer = create_settings_group(this); + this->SetSizer(m_options_sizer); + this->Layout(); + m_options_sizer->Fit(this); + this->Fit(); + + m_cb_first_layer->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent& evt) { + if (obj) { + obj->command_xcam_control_first_layer_inspector(m_cb_first_layer->GetValue(), false); + } + evt.Skip(); + }); + + m_cb_spaqhetti->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent& evt) { + update_spaqhetti(); + + if (obj) { + obj->command_xcam_control_spaghetti_detector(m_cb_spaqhetti->GetValue(), m_cb_spaqhetti_print_halt->GetValue()); + } + evt.Skip(); + }); + + m_cb_spaqhetti_print_halt->Bind(wxEVT_TOGGLEBUTTON, [this](wxCommandEvent&evt) { + if (obj) { + obj->command_xcam_control_spaghetti_detector(m_cb_spaqhetti->GetValue(), m_cb_spaqhetti_print_halt->GetValue()); + } + evt.Skip(); + }); +} + +PrintOptionsDialog::~PrintOptionsDialog() {} + +void PrintOptionsDialog::on_dpi_changed(const wxRect &suggested_rect) +{ + this->SetMinSize(DLG_SIZE); + this->SetSize(DLG_SIZE); + Fit(); +} + +void PrintOptionsDialog::update_spaqhetti() +{ + if (m_cb_spaqhetti->GetValue()) { + m_cb_spaqhetti_print_halt->Enable(); + text_spaqhetti_print_halt->Enable(); + } + else { + m_cb_spaqhetti_print_halt->Disable(); + text_spaqhetti_print_halt->Disable(); + } +} + +void PrintOptionsDialog::update_options(MachineObject *obj_) +{ + if (!obj_) return; + this->Freeze(); + m_cb_spaqhetti->SetValue(obj_->xcam_spaghetti_detector); + m_cb_spaqhetti_print_halt->SetValue(obj_->xcam_spaghetti_print_halt); + m_cb_first_layer->SetValue(obj_->xcam_first_layer_inspector); + update_spaqhetti(); + this->Thaw(); +} + +wxBoxSizer* PrintOptionsDialog::create_settings_group(wxWindow* parent) +{ + auto sizer = new wxBoxSizer(wxVERTICAL); + auto line_sizer = new wxBoxSizer(wxHORIZONTAL); + m_cb_spaqhetti = new CheckBox(parent); + auto text_spaqhetti = new wxStaticText(parent, wxID_ANY, _L("Spaqhetti Detection")); + text_spaqhetti->SetFont(Label::Body_14); + line_sizer->Add(FromDIP(5), 0, 0, 0); + line_sizer->Add(m_cb_spaqhetti, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); + line_sizer->Add(text_spaqhetti, 1, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); + sizer->Add(line_sizer, 0, wxEXPAND | wxALL, FromDIP(5)); + + line_sizer = new wxBoxSizer(wxHORIZONTAL); + m_cb_spaqhetti_print_halt = new CheckBox(parent); + text_spaqhetti_print_halt = new wxStaticText(parent, wxID_ANY, _L("Stop printing when Spaqhetti detected")); + text_spaqhetti_print_halt->SetFont(Label::Body_12); + line_sizer->Add(FromDIP(30), 0, 0, 0); + line_sizer->Add(m_cb_spaqhetti_print_halt, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); + line_sizer->Add(text_spaqhetti_print_halt, 1, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); + + sizer->Add(line_sizer, 0, wxEXPAND | wxALL , 0); + + sizer->Add(0, FromDIP(10), 0, 0); + StaticLine* line = new StaticLine(parent, false); + line->SetLineColour(STATIC_BOX_LINE_COL); + sizer->Add(line, 0, wxEXPAND | wxLEFT | wxRIGHT, FromDIP(20)); + + line_sizer = new wxBoxSizer(wxHORIZONTAL); + m_cb_first_layer = new CheckBox(parent); + auto text_first_layer = new wxStaticText(parent, wxID_ANY, _L("First Layer Inspection")); + text_first_layer->SetFont(Label::Body_14); + line_sizer->Add(FromDIP(5), 0, 0, 0); + line_sizer->Add(m_cb_first_layer, 0, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); + line_sizer->Add(text_first_layer, 1, wxALL | wxALIGN_CENTER_VERTICAL, FromDIP(5)); + sizer->Add(line_sizer, 1, wxEXPAND | wxALL, FromDIP(5)); + line_sizer->Add(FromDIP(5), 0, 0, 0); + + return sizer; +} + +void PrintOptionsDialog::update_machine_obj(MachineObject *obj_) +{ + obj = obj_; +} + +bool PrintOptionsDialog::Show(bool show) +{ + if (show) { CentreOnParent(); } + return DPIDialog::Show(show); +} + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/PrintOptionsDialog.hpp b/src/slic3r/GUI/PrintOptionsDialog.hpp new file mode 100644 index 0000000000..668a992685 --- /dev/null +++ b/src/slic3r/GUI/PrintOptionsDialog.hpp @@ -0,0 +1,47 @@ +#ifndef slic3r_GUI_PrintOptionsDialog_hpp_ +#define slic3r_GUI_PrintOptionsDialog_hpp_ + +#include +#include +#include +#include +#include +#include + +#include "GUI_Utils.hpp" +#include "wxExtensions.hpp" +#include "DeviceManager.hpp" +#include "Widgets/Label.hpp" +#include "Widgets/CheckBox.hpp" +#include "Widgets/StaticLine.hpp" + +namespace Slic3r { namespace GUI { + +class PrintOptionsDialog : public DPIDialog +{ +protected: + // settings + CheckBox* m_cb_first_layer; + CheckBox* m_cb_spaqhetti; + CheckBox* m_cb_spaqhetti_print_halt; + wxStaticText* text_spaqhetti_print_halt; + wxBoxSizer* create_settings_group(wxWindow* parent); + +public: + PrintOptionsDialog(wxWindow* parent); + ~PrintOptionsDialog(); + void on_dpi_changed(const wxRect &suggested_rect) override; + void update_spaqhetti(); + + MachineObject *obj { nullptr }; + + std::vector last_stage_list_info; + int m_state{0}; + void update_options(MachineObject *obj_); + void update_machine_obj(MachineObject *obj_); + bool Show(bool show) override; +}; + +}} // namespace Slic3r::GUI + +#endif diff --git a/src/slic3r/GUI/StatusPanel.cpp b/src/slic3r/GUI/StatusPanel.cpp index 1ed473357e..2fc9c3bd28 100644 --- a/src/slic3r/GUI/StatusPanel.cpp +++ b/src/slic3r/GUI/StatusPanel.cpp @@ -482,11 +482,19 @@ wxBoxSizer *StatusBasePanel::create_machine_control_page(wxWindow *parent) m_staticText_control->SetFont(PAGE_TITLE_FONT); m_staticText_control->SetForegroundColour(PAGE_TITLE_FONT_COL); - m_calibration_btn = new Button(m_panel_control_title, _L("Start Calibration")); StateColor btn_bg_green(std::pair(AMS_CONTROL_DISABLE_COLOUR, StateColor::Disabled), std::pair(wxColour(27, 136, 68), StateColor::Pressed), - std::pair(wxColour(61, 203, 115), StateColor::Hovered), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); + std::pair(wxColour(61, 203, 115), StateColor::Hovered), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Normal)); StateColor btn_bd_green(std::pair(AMS_CONTROL_WHITE_COLOUR, StateColor::Disabled), std::pair(AMS_CONTROL_BRAND_COLOUR, StateColor::Enabled)); + m_options_btn = new Button(m_panel_control_title, _L("Print Options")); + m_options_btn->SetBackgroundColor(btn_bg_green); + m_options_btn->SetBorderColor(btn_bd_green); + m_options_btn->SetTextColor(*wxWHITE); + m_options_btn->SetSize(wxSize(FromDIP(128), FromDIP(26))); + m_options_btn->SetMinSize(wxSize(-1, FromDIP(26))); + + + m_calibration_btn = new Button(m_panel_control_title, _L("Calibration")); m_calibration_btn->SetBackgroundColor(btn_bg_green); m_calibration_btn->SetBorderColor(btn_bd_green); m_calibration_btn->SetTextColor(*wxWHITE); @@ -495,6 +503,7 @@ wxBoxSizer *StatusBasePanel::create_machine_control_page(wxWindow *parent) bSizer_control_title->Add(m_staticText_control, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, PAGE_TITLE_LEFT_MARGIN); bSizer_control_title->Add(0, 0, 1, wxEXPAND, 0); + bSizer_control_title->Add(m_options_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10)); bSizer_control_title->Add(m_calibration_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(10)); m_panel_control_title->SetSizer(bSizer_control_title); @@ -975,6 +984,7 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co } }); + // Connect Events //m_bitmap_thumbnail->Connect(wxEVT_ENTER_WINDOW, wxMouseEventHandler(StatusPanel::on_thumbnail_enter), NULL, this); //m_bitmap_thumbnail->Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(StatusPanel::on_thumbnail_leave), NULL, this); @@ -1009,6 +1019,7 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co m_switch_speed->Connect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this); m_calibration_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this); + m_options_btn->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_print_options), NULL, this); } StatusPanel::~StatusPanel() @@ -1036,6 +1047,7 @@ StatusPanel::~StatusPanel() m_bpButton_e_down_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_down_10), NULL, this); m_switch_speed->Disconnect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), NULL, this); m_calibration_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_calibration), NULL, this); + m_options_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_print_options), NULL, this); m_button_unload->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_start_unload), NULL, this); } @@ -1205,6 +1217,7 @@ void StatusPanel::update(MachineObject *obj) update_ams(obj); update_cali(obj); + if (obj) { if (calibration_dlg == nullptr) { calibration_dlg = new CalibrationDialog(); @@ -1214,6 +1227,14 @@ void StatusPanel::update(MachineObject *obj) } calibration_dlg->update_cali(obj); + if (print_options_dlg == nullptr) { + print_options_dlg = new PrintOptionsDialog(this); + print_options_dlg->update_machine_obj(obj); + } else { + print_options_dlg->update_machine_obj(obj); + } + print_options_dlg->update_options(obj); + update_error_message(); } @@ -1582,7 +1603,7 @@ void StatusPanel::update_cali(MachineObject *obj) } } else { // IDLE - m_calibration_btn->SetLabel(_L("Start Calibration")); + m_calibration_btn->SetLabel(_L("Calibration")); // disable in printing if (obj->is_in_printing()) { m_calibration_btn->Disable(); @@ -2145,6 +2166,21 @@ void StatusPanel::on_xyz_abs(wxCommandEvent &event) if (obj) obj->command_xyz_abs(); } +void StatusPanel::on_show_print_options(wxCommandEvent &event) +{ + if (obj) { + if (print_options_dlg == nullptr) { + print_options_dlg = new PrintOptionsDialog(this); + print_options_dlg->update_machine_obj(obj); + print_options_dlg->ShowModal(); + } + else { + print_options_dlg->update_machine_obj(obj); + print_options_dlg->ShowModal(); + } + } +} + void StatusPanel::on_start_calibration(wxCommandEvent &event) { if (obj) { @@ -2209,9 +2245,11 @@ void StatusPanel::show_status(int status) m_text_tasklist_caption->SetForegroundColour(DISCONNECT_TEXT_COL); show_printing_status(false, false); m_calibration_btn->Disable(); + m_options_btn->Disable(); } else if ((status & (int) MonitorStatus::MONITOR_NORMAL) != 0) { show_printing_status(true, true); m_calibration_btn->Disable(); + m_options_btn->Enable(); } } @@ -2289,6 +2327,9 @@ void StatusPanel::msw_rescale() m_calibration_btn->SetMinSize(wxSize(-1, FromDIP(26))); m_calibration_btn->Rescale(); + m_options_btn->SetMinSize(wxSize(-1, FromDIP(26))); + m_options_btn->Rescale(); + Layout(); Refresh(); } diff --git a/src/slic3r/GUI/StatusPanel.hpp b/src/slic3r/GUI/StatusPanel.hpp index 8430dcad3c..d1f7c19924 100644 --- a/src/slic3r/GUI/StatusPanel.hpp +++ b/src/slic3r/GUI/StatusPanel.hpp @@ -17,6 +17,7 @@ #include "MediaPlayCtrl.h" #include "AMSSetting.hpp" #include "Calibration.hpp" +#include "PrintOptionsDialog.hpp" #include "AMSMaterialsSetting.hpp" #include "Widgets/SwitchButton.hpp" #include "Widgets/AxisCtrlButton.hpp" @@ -172,6 +173,7 @@ protected: wxStaticText* m_staticText_calibration_caption; wxStaticText* m_staticText_calibration_caption_top; wxStaticText* m_calibration_text; + Button* m_options_btn; Button* m_calibration_btn; StepIndicator* m_calibration_flow; @@ -220,6 +222,7 @@ public: void reset_temp_misc_control(); int before_error_code = 0; wxBoxSizer *create_ams_group(wxWindow *parent); + wxBoxSizer *create_settings_group(wxWindow *parent); void show_ams_group(bool show = true); void upodate_camera_state(bool recording, bool timelapse, bool has_sdcard); @@ -237,7 +240,8 @@ protected: std::shared_ptr m_camera_popup; std::vector slice_info_list; AMSSetting *m_ams_setting_dlg{nullptr}; - CalibrationDialog* calibration_dlg{nullptr}; + PrintOptionsDialog* print_options_dlg { nullptr }; + CalibrationDialog* calibration_dlg {nullptr}; AMSMaterialsSetting *m_filament_setting_dlg{nullptr}; wxString m_request_url; @@ -304,6 +308,9 @@ protected: void on_auto_leveling(wxCommandEvent &event); void on_xyz_abs(wxCommandEvent &event); + /* print options */ + void on_show_print_options(wxCommandEvent &event); + /* calibration */ void on_start_calibration(wxCommandEvent &event);