Compare commits

...
7 changed files with 861 additions and 293 deletions
@@ -9,6 +9,8 @@
#include "libslic3r/libslic3r.h" #include "libslic3r/libslic3r.h"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include <slic3r/GUI/DeviceCore/DevDefs.h>
#include <slic3r/GUI/GUI_App.hpp>
namespace Slic3r namespace Slic3r
{ {
@@ -156,6 +158,8 @@ DevFirmwareVersionInfo DevNozzle::GetFirmwareInfo() const
int DevNozzle::GetLogicExtruderId() const int DevNozzle::GetLogicExtruderId() const
{ {
int total_ext_count = GetTotalExtruderCount(); int total_ext_count = GetTotalExtruderCount();
if (GUI::wxGetApp().preset_bundle->is_bbl_vendor()) {
if (total_ext_count == 1) { if (total_ext_count == 1) {
return LOGIC_UNIQUE_EXTRUDER_ID; return LOGIC_UNIQUE_EXTRUDER_ID;
} else if (total_ext_count == 2) { } else if (total_ext_count == 2) {
@@ -170,8 +174,17 @@ int DevNozzle::GetLogicExtruderId() const
return LOGIC_UNIQUE_EXTRUDER_ID; return LOGIC_UNIQUE_EXTRUDER_ID;
} }
// For some reason, BBL's logical extruder ID is inverted:
// physical extruder id = 0 (MAIN_EXTRUDER_ID) vs logical extruder id = 1 (LOGIC_R_EXTRUDER_ID)
// Likely because logical id reads from left to right (left = 0, right = 1)
// For generic N extruders, this inversion does not apply.
if (IsOnRack()) return INVALID_EXTRUDER_ID;
return m_nozzle_id;
}
int DevNozzle::GetExtruderId() const int DevNozzle::GetExtruderId() const
{ {
if (GUI::wxGetApp().preset_bundle->is_bbl_vendor()) {
int total_ext_count = GetTotalExtruderCount(); int total_ext_count = GetTotalExtruderCount();
if (total_ext_count == 1) { if (total_ext_count == 1) {
return MAIN_EXTRUDER_ID; return MAIN_EXTRUDER_ID;
@@ -186,6 +199,9 @@ int DevNozzle::GetExtruderId() const
return MAIN_EXTRUDER_ID; return MAIN_EXTRUDER_ID;
} }
return m_nozzle_id;
}
bool DevNozzle::AtLeftExtruder() const bool DevNozzle::AtLeftExtruder() const
{ {
assert(GetTotalExtruderCount() == 2); assert(GetTotalExtruderCount() == 2);
+17 -12
View File
@@ -1222,20 +1222,25 @@ int MachineObject::get_bed_temperature_limit()
bool MachineObject::is_filament_installed() bool MachineObject::is_filament_installed()
{ {
if (m_extder_system->GetTotalExtderCount() > 0) { // if (m_extder_system->GetTotalExtderCount() > 0) {
// right//or single // // right//or single
auto ext = m_extder_system->m_extders[MAIN_EXTRUDER_ID]; // auto ext = m_extder_system->m_extders[MAIN_EXTRUDER_ID];
if (ext.m_ext_has_filament) { // if (ext.m_ext_has_filament) {
// return true;
// }
// }
// /*left*/
// if (m_extder_system->GetTotalExtderCount() > 1) {
// auto ext = m_extder_system->m_extders[DEPUTY_EXTRUDER_ID];
// if (ext.m_ext_has_filament) {
// return true;
// }
// }
for (auto& ext : m_extder_system->m_extders) {
if (ext.m_ext_has_filament)
return true; return true;
} }
}
/*left*/
if (m_extder_system->GetTotalExtderCount() > 1) {
auto ext = m_extder_system->m_extders[DEPUTY_EXTRUDER_ID];
if (ext.m_ext_has_filament) {
return true;
}
}
return false; return false;
} }
+499 -81
View File
@@ -17,7 +17,10 @@
#include "RecenterDialog.hpp" #include "RecenterDialog.hpp"
#include "CalibUtils.hpp" #include "CalibUtils.hpp"
#include <algorithm>
#include <boost/log/trivial.hpp>
#include <slic3r/GUI/Widgets/ProgressDialog.hpp> #include <slic3r/GUI/Widgets/ProgressDialog.hpp>
#include <wx/choice.h>
#include <wx/display.h> #include <wx/display.h>
#include <wx/mstream.h> #include <wx/mstream.h>
#include <wx/sstream.h> #include <wx/sstream.h>
@@ -213,7 +216,22 @@ void ExtruderImage::msw_rescale()
void ExtruderImage::setExtruderCount(int nozzle_num) void ExtruderImage::setExtruderCount(int nozzle_num)
{ {
m_nozzle_num = nozzle_num; const int normalized_count = std::max(0, nozzle_num);
if (m_nozzle_num == normalized_count && m_multi_extruder_states.size() == static_cast<size_t>(normalized_count))
return;
m_nozzle_num = normalized_count;
m_multi_extruder_states.resize(static_cast<size_t>(m_nozzle_num), ExtruderState::EMPTY_LOAD);
Refresh();
}
void ExtruderImage::setGenericNozzleDisplay(bool enabled)
{
if (m_generic_nozzle_display == enabled)
return;
m_generic_nozzle_display = enabled;
Refresh();
} }
void ExtruderImage::setExtruderUsed(std::string loc) void ExtruderImage::setExtruderUsed(std::string loc)
@@ -228,14 +246,36 @@ void ExtruderImage::setExtruderUsed(std::string loc)
Refresh(); Refresh();
} }
void ExtruderImage::setExtruderUsed(int nozzle_idx)
{
if (current_nozzle_idx == nozzle_idx)
return;
current_nozzle_idx = nozzle_idx;
Refresh();
}
void ExtruderImage::update(ExtruderState single_state) void ExtruderImage::update(ExtruderState single_state)
{ {
m_single_ext_state = single_state; m_single_ext_state = single_state;
Refresh();
} }
void ExtruderImage::update(ExtruderState right_state, ExtruderState left_state) { void ExtruderImage::update(ExtruderState right_state, ExtruderState left_state) {
m_left_ext_state = left_state; m_left_ext_state = left_state;
m_right_ext_state = right_state; m_right_ext_state = right_state;
Refresh();
}
void ExtruderImage::update(ExtruderState state, int idx) {
if (idx < 0 || m_multi_extruder_states.size() <= static_cast<size_t>(idx)) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ": Index exceeded number of extruders.";
return;
}
if (m_multi_extruder_states[idx] == state)
return;
m_multi_extruder_states[idx] = state;
} }
void ExtruderImage::paintEvent(wxPaintEvent& evt) void ExtruderImage::paintEvent(wxPaintEvent& evt)
@@ -270,6 +310,50 @@ void ExtruderImage::doRender(wxDC& dc)
auto size = GetSize(); auto size = GetSize();
//dc.DrawRectangle(0, FromDIP(5), size.x, size.y - FromDIP(5) - FromDIP(2)); //dc.DrawRectangle(0, FromDIP(5), size.x, size.y - FromDIP(5) - FromDIP(2));
if (m_generic_nozzle_display) {
const wxSize source_size = m_left_extruder_active_filled->GetBmpSize();
const int count = std::min(m_nozzle_num, static_cast<int>(m_multi_extruder_states.size()));
if (count <= 0 || size.x <= 0 || size.y <= 0 || source_size.x <= 0 || source_size.y <= 0)
return;
double best_scale = 0.0;
int columns = 1;
int rows = count;
for (int candidate_columns = 1; candidate_columns <= count; ++candidate_columns) {
const int candidate_rows = (count + candidate_columns - 1) / candidate_columns;
const double scale = std::min(static_cast<double>(size.x) / candidate_columns / source_size.x,
static_cast<double>(size.y) / candidate_rows / source_size.y);
if (scale > best_scale) {
best_scale = scale;
columns = candidate_columns;
rows = candidate_rows;
}
}
const int icon_width = std::max(1, static_cast<int>(source_size.x * best_scale));
const int icon_height = std::max(1, static_cast<int>(source_size.y * best_scale));
const int cell_width = size.x / columns;
const int cell_height = size.y / rows;
for (int i = 0; i < count; ++i) {
const ExtruderState state = m_multi_extruder_states[i];
const bool filled = state == ExtruderState::FILLED_LOAD || state == ExtruderState::FILLED_UNLOAD;
const bool selected = i == current_nozzle_idx;
ScalableBitmap* icon = nullptr;
if (selected)
icon = filled ? m_left_extruder_active_filled : m_left_extruder_active_empty;
else
icon = filled ? m_left_extruder_unactive_filled : m_left_extruder_unactive_empty;
const int col = i % columns;
const int row = i / columns;
const int x = col * cell_width + (cell_width - icon_width) / 2;
const int y = row * cell_height + (cell_height - icon_height) / 2;
const wxImage scaled_image = icon->bmp().ConvertToImage().Scale(icon_width, icon_height, wxIMAGE_QUALITY_HIGH);
dc.DrawBitmap(wxBitmap(scaled_image), x, y, true);
}
return;
}
auto pot = wxPoint(size.x / 2, (size.y - m_pipe_filled_load->GetBmpSize().y - m_left_extruder_active_filled->GetBmpSize().y) / 2); auto pot = wxPoint(size.x / 2, (size.y - m_pipe_filled_load->GetBmpSize().y - m_left_extruder_active_filled->GetBmpSize().y) / 2);
if (m_nozzle_num >= 2){ if (m_nozzle_num >= 2){
@@ -1716,32 +1800,14 @@ wxBoxSizer *StatusBasePanel::create_temp_control(wxWindow *parent)
{ {
auto sizer = new wxBoxSizer(wxVERTICAL); auto sizer = new wxBoxSizer(wxVERTICAL);
wxWindowID nozzle_id = wxWindow::NewControlId(); m_nozzle_temp_control_id = wxWindow::NewControlId();
m_tempCtrl_nozzle = new TempInput(parent, nozzle_id, TEMP_BLANK_STR, TempInputType::TEMP_OF_NORMAL_TYPE, TEMP_BLANK_STR, wxString("monitor_nozzle_temp"), m_temp_nozzle_parent = parent;
wxString("monitor_nozzle_temp_active"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER); m_temp_nozzle_sizer = sizer;
m_tempCtrl_nozzle->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON);
m_tempCtrl_nozzle->AddTemp(0); // zero is default temp
m_tempCtrl_nozzle->SetMinTemp(20);
m_tempCtrl_nozzle->SetMaxTemp(300);
m_tempCtrl_nozzle->SetBorderWidth(FromDIP(2));
StateColor tempinput_text_colour(std::make_pair(DISCONNECT_TEXT_COL, (int) StateColor::Disabled), std::make_pair(NORMAL_TEXT_COL, (int) StateColor::Normal)); // Keep the two legacy controls for Bambu's main/deputy nozzle presentation. Generic
StateColor tempinput_border_colour(std::make_pair(*wxWHITE, (int)StateColor::Disabled), std::make_pair(BUTTON_HOVER_COL, (int)StateColor::Focused), // printers use the grow-on-demand pool below, so these do not limit their nozzle count.
std::make_pair(BUTTON_HOVER_COL, (int)StateColor::Hovered), std::make_pair(*wxWHITE, (int)StateColor::Normal)); m_tempCtrl_nozzle = create_nozzle_temp_control(parent, m_nozzle_temp_control_id);
m_tempCtrl_nozzle_deputy = create_nozzle_temp_control(parent, m_nozzle_temp_control_id);
m_tempCtrl_nozzle->SetTextColor(tempinput_text_colour);
m_tempCtrl_nozzle->SetBorderColor(tempinput_border_colour);
m_tempCtrl_nozzle_deputy = new TempInput(parent, nozzle_id, TEMP_BLANK_STR, TempInputType::TEMP_OF_NORMAL_TYPE, TEMP_BLANK_STR, wxString("monitor_nozzle_temp"), wxString("monitor_nozzle_temp_active"),
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
m_tempCtrl_nozzle_deputy->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON);
m_tempCtrl_nozzle_deputy->AddTemp(0); // zero is default temp
m_tempCtrl_nozzle_deputy->SetMinTemp(20);
m_tempCtrl_nozzle_deputy->SetMaxTemp(300);
m_tempCtrl_nozzle_deputy->SetBorderWidth(FromDIP(2));
m_tempCtrl_nozzle_deputy->SetTextColor(tempinput_text_colour);
m_tempCtrl_nozzle_deputy->SetBorderColor(tempinput_border_colour);
sizer->Add(m_tempCtrl_nozzle_deputy, 0, wxEXPAND | wxALL, 1); sizer->Add(m_tempCtrl_nozzle_deputy, 0, wxEXPAND | wxALL, 1);
sizer->Add(m_tempCtrl_nozzle, 0, wxEXPAND | wxALL, 1); sizer->Add(m_tempCtrl_nozzle, 0, wxEXPAND | wxALL, 1);
@@ -1760,8 +1826,7 @@ wxBoxSizer *StatusBasePanel::create_temp_control(wxWindow *parent)
m_tempCtrl_bed->SetMaxTemp(bed_temp_range[1]); m_tempCtrl_bed->SetMaxTemp(bed_temp_range[1]);
m_tempCtrl_bed->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON); m_tempCtrl_bed->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON);
m_tempCtrl_bed->SetBorderWidth(FromDIP(2)); m_tempCtrl_bed->SetBorderWidth(FromDIP(2));
m_tempCtrl_bed->SetTextColor(tempinput_text_colour); set_temp_input_colors(m_tempCtrl_bed);
m_tempCtrl_bed->SetBorderColor(tempinput_border_colour);
sizer->Add(m_tempCtrl_bed, 0, wxEXPAND | wxALL, 1); sizer->Add(m_tempCtrl_bed, 0, wxEXPAND | wxALL, 1);
auto line = new StaticLine(parent); auto line = new StaticLine(parent);
@@ -1777,8 +1842,7 @@ wxBoxSizer *StatusBasePanel::create_temp_control(wxWindow *parent)
m_tempCtrl_chamber->SetMaxTemp(default_champer_temp_max); m_tempCtrl_chamber->SetMaxTemp(default_champer_temp_max);
m_tempCtrl_chamber->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON); m_tempCtrl_chamber->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON);
m_tempCtrl_chamber->SetBorderWidth(FromDIP(2)); m_tempCtrl_chamber->SetBorderWidth(FromDIP(2));
m_tempCtrl_chamber->SetTextColor(tempinput_text_colour); set_temp_input_colors(m_tempCtrl_chamber);
m_tempCtrl_chamber->SetBorderColor(tempinput_border_colour);
sizer->Add(m_tempCtrl_chamber, 0, wxEXPAND | wxALL, 1); sizer->Add(m_tempCtrl_chamber, 0, wxEXPAND | wxALL, 1);
m_misc_ctrl_sizer = create_misc_control(parent); m_misc_ctrl_sizer = create_misc_control(parent);
@@ -1786,6 +1850,73 @@ wxBoxSizer *StatusBasePanel::create_temp_control(wxWindow *parent)
return sizer; return sizer;
} }
TempInput* StatusBasePanel::create_nozzle_temp_control(wxWindow* parent, wxWindowID id)
{
auto* temp_ctrl = new TempInput(parent, id, TEMP_BLANK_STR, TempInputType::TEMP_OF_NORMAL_TYPE, TEMP_BLANK_STR,
wxString("monitor_nozzle_temp"), wxString("monitor_nozzle_temp_active"),
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
temp_ctrl->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON);
temp_ctrl->AddTemp(0); // zero is default temp
temp_ctrl->SetMinTemp(20);
temp_ctrl->SetMaxTemp(300);
temp_ctrl->SetBorderWidth(FromDIP(2));
set_temp_input_colors(temp_ctrl);
return temp_ctrl;
}
void StatusBasePanel::set_temp_input_colors(TempInput* temp_ctrl)
{
StateColor tempinput_text_colour(std::make_pair(DISCONNECT_TEXT_COL, (int)StateColor::Disabled),
std::make_pair(NORMAL_TEXT_COL, (int)StateColor::Normal));
StateColor tempinput_border_colour(std::make_pair(*wxWHITE, (int)StateColor::Disabled),
std::make_pair(BUTTON_HOVER_COL, (int)StateColor::Focused),
std::make_pair(BUTTON_HOVER_COL, (int)StateColor::Hovered),
std::make_pair(*wxWHITE, (int)StateColor::Normal));
temp_ctrl->SetTextColor(tempinput_text_colour);
temp_ctrl->SetBorderColor(tempinput_border_colour);
}
void StatusBasePanel::ensure_nozzle_temp_controls(size_t count)
{
if (!m_temp_nozzle_parent || !m_temp_nozzle_sizer)
return;
bool changed = count != m_temp_nozzle_active_count;
while (m_tempCtrl_nozzles.size() < count) {
TempInput* temp_ctrl = create_nozzle_temp_control(m_temp_nozzle_parent, m_nozzle_temp_control_id);
temp_ctrl->Hide();
m_temp_nozzle_sizer->Insert(m_tempCtrl_nozzles.size(), temp_ctrl, 0, wxEXPAND | wxALL, 1);
m_tempCtrl_nozzles.push_back(temp_ctrl);
m_temp_nozzle_timeouts.push_back(0);
changed = true;
}
const wxSize nozzle_size = count >= 2 ? TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON : TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON;
for (size_t i = 0; i < m_tempCtrl_nozzles.size(); ++i) {
const bool show = i < count;
if (m_tempCtrl_nozzles[i]->IsShown() != show) {
m_tempCtrl_nozzles[i]->Show(show);
changed = true;
}
if (m_tempCtrl_nozzles[i]->GetMinSize() != nozzle_size) {
m_tempCtrl_nozzles[i]->SetMinSize(nozzle_size);
changed = true;
}
}
if (count < m_temp_nozzle_active_count) {
for (size_t i = count; i < m_temp_nozzle_timeouts.size(); ++i)
m_temp_nozzle_timeouts[i] = 0;
}
m_temp_nozzle_active_count = count;
if (changed) {
m_temp_nozzle_parent->Layout();
Layout();
}
}
wxBoxSizer *StatusBasePanel::create_misc_control(wxWindow *parent) wxBoxSizer *StatusBasePanel::create_misc_control(wxWindow *parent)
{ {
wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL); wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
@@ -1870,6 +2001,7 @@ wxBoxSizer *StatusBasePanel::create_misc_control(wxWindow *parent)
void StatusBasePanel::reset_temp_misc_control() void StatusBasePanel::reset_temp_misc_control()
{ {
// reset temp string // reset temp string
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
m_tempCtrl_nozzle->SetIconNormal(); m_tempCtrl_nozzle->SetIconNormal();
m_tempCtrl_nozzle->SetLabel(TEMP_BLANK_STR); m_tempCtrl_nozzle->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_nozzle->GetTextCtrl()->SetValue(TEMP_BLANK_STR); m_tempCtrl_nozzle->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
@@ -1878,6 +2010,17 @@ void StatusBasePanel::reset_temp_misc_control()
m_tempCtrl_nozzle_deputy->SetLabel(TEMP_BLANK_STR); m_tempCtrl_nozzle_deputy->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_nozzle_deputy->GetTextCtrl()->SetValue(TEMP_BLANK_STR); m_tempCtrl_nozzle_deputy->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
m_tempCtrl_nozzle->Enable(true);
m_tempCtrl_nozzle_deputy->Enable(true);
} else {
for (auto& tempCtrl : m_tempCtrl_nozzles) {
tempCtrl->SetIconNormal();
tempCtrl->SetLabel(TEMP_BLANK_STR);
tempCtrl->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
tempCtrl->Enable(true);
}
}
m_tempCtrl_bed->SetIconNormal(); m_tempCtrl_bed->SetIconNormal();
m_tempCtrl_bed->SetLabel(TEMP_BLANK_STR); m_tempCtrl_bed->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_bed->GetTextCtrl()->SetValue(TEMP_BLANK_STR); m_tempCtrl_bed->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
@@ -1886,8 +2029,6 @@ void StatusBasePanel::reset_temp_misc_control()
m_tempCtrl_chamber->SetLabel(TEMP_BLANK_STR); m_tempCtrl_chamber->SetLabel(TEMP_BLANK_STR);
m_tempCtrl_chamber->GetTextCtrl()->SetValue(TEMP_BLANK_STR); m_tempCtrl_chamber->GetTextCtrl()->SetValue(TEMP_BLANK_STR);
m_tempCtrl_nozzle->Enable(true);
m_tempCtrl_nozzle_deputy->Enable(true);
m_tempCtrl_chamber->Enable(true); m_tempCtrl_chamber->Enable(true);
m_tempCtrl_bed->Enable(true); m_tempCtrl_bed->Enable(true);
@@ -1999,6 +2140,9 @@ wxBoxSizer *StatusBasePanel::create_extruder_control(wxWindow *parent)
m_nozzle_btn_panel = new SwitchBoard(panel, _L_CONTEXT("Left", "Nozzle position"), _L_CONTEXT("Right", "Nozzle position"), wxSize(FromDIP(126), FromDIP(26))); m_nozzle_btn_panel = new SwitchBoard(panel, _L_CONTEXT("Left", "Nozzle position"), _L_CONTEXT("Right", "Nozzle position"), wxSize(FromDIP(126), FromDIP(26)));
m_nozzle_btn_panel->SetAutoDisableWhenSwitch(); m_nozzle_btn_panel->SetAutoDisableWhenSwitch();
m_generic_nozzle_selector = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxSize(FromDIP(126), FromDIP(26)));
m_generic_nozzle_selector->SetMinSize(wxSize(FromDIP(126), FromDIP(26)));
m_generic_nozzle_selector->Hide();
m_bpButton_e_10 = new Button(panel, "", "monitor_extruder_up", 0, 22); // Orca Dont scale icon size m_bpButton_e_10 = new Button(panel, "", "monitor_extruder_up", 0, 22); // Orca Dont scale icon size
m_bpButton_e_10->SetBorderWidth(2); m_bpButton_e_10->SetBorderWidth(2);
@@ -2031,6 +2175,7 @@ wxBoxSizer *StatusBasePanel::create_extruder_control(wxWindow *parent)
bSizer_e_ctrl->Add(0, 0, 0, wxTOP, FromDIP(15)); bSizer_e_ctrl->Add(0, 0, 0, wxTOP, FromDIP(15));
bSizer_e_ctrl->Add(m_nozzle_btn_panel, 0, wxALIGN_CENTER_HORIZONTAL, 0); bSizer_e_ctrl->Add(m_nozzle_btn_panel, 0, wxALIGN_CENTER_HORIZONTAL, 0);
bSizer_e_ctrl->Add(m_generic_nozzle_selector, 0, wxALIGN_CENTER_HORIZONTAL, 0);
bSizer_e_ctrl->Add(0, 0, 0, wxTOP, FromDIP(15)); bSizer_e_ctrl->Add(0, 0, 0, wxTOP, FromDIP(15));
bSizer_e_ctrl->Add(m_bpButton_e_10, 0, wxALIGN_CENTER_HORIZONTAL, 0); bSizer_e_ctrl->Add(m_bpButton_e_10, 0, wxALIGN_CENTER_HORIZONTAL, 0);
bSizer_e_ctrl->Add(0, 0, 0, wxTOP, FromDIP(7)); bSizer_e_ctrl->Add(0, 0, 0, wxTOP, FromDIP(7));
@@ -2453,9 +2598,43 @@ StatusPanel::StatusPanel(wxWindow *parent, wxWindowID id, const wxPoint &pos, co
add_build_step([this] { wire_controls(); }); add_build_step([this] { wire_controls(); });
} }
void StatusPanel::sync_nozzle_temp_controls(size_t count)
{
const size_t old_size = m_tempCtrl_nozzles.size();
ensure_nozzle_temp_controls(count);
bool layout_changed = false;
if (m_tempCtrl_nozzle->IsShown()) {
m_tempCtrl_nozzle->Hide();
layout_changed = true;
}
if (m_tempCtrl_nozzle_deputy->IsShown()) {
m_tempCtrl_nozzle_deputy->Hide();
layout_changed = true;
}
if (layout_changed) {
m_temp_nozzle_parent->Layout();
Layout();
}
for (size_t i = old_size; i < m_tempCtrl_nozzles.size(); ++i) {
m_tempCtrl_nozzles[i]->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this);
m_tempCtrl_nozzles[i]->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this);
}
}
void StatusPanel::wire_controls() void StatusPanel::wire_controls()
{ {
init_scaled_buttons(); init_scaled_buttons();
const bool is_bbl_vendor = wxGetApp().preset_bundle->is_bbl_vendor();
if (!is_bbl_vendor)
sync_nozzle_temp_controls(obj ? obj->GetExtderSystem()->GetTotalExtderCount() : 0);
if (is_bbl_vendor)
m_generic_nozzle_selector->Hide();
else
m_nozzle_btn_panel->Hide();
m_nozzle_btn_panel->GetParent()->Layout();
m_buttons.push_back(m_bpButton_z_10); m_buttons.push_back(m_bpButton_z_10);
m_buttons.push_back(m_bpButton_z_1); m_buttons.push_back(m_bpButton_z_1);
m_buttons.push_back(m_bpButton_z_down_1); m_buttons.push_back(m_bpButton_z_down_1);
@@ -2485,7 +2664,8 @@ void StatusPanel::wire_controls()
int id = e.GetInt(); int id = e.GetInt();
if (id == m_tempCtrl_bed->GetType()) { if (id == m_tempCtrl_bed->GetType()) {
on_set_bed_temp(); on_set_bed_temp();
} else if (id == m_tempCtrl_nozzle->GetType()) { } else if (id == m_nozzle_temp_control_id) {
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
if (e.GetString() == wxString::Format("%d", MAIN_EXTRUDER_ID)) { if (e.GetString() == wxString::Format("%d", MAIN_EXTRUDER_ID)) {
on_set_nozzle_temp(MAIN_EXTRUDER_ID); on_set_nozzle_temp(MAIN_EXTRUDER_ID);
} else if (e.GetString() == wxString::Format("%d", DEPUTY_EXTRUDER_ID)) { } else if (e.GetString() == wxString::Format("%d", DEPUTY_EXTRUDER_ID)) {
@@ -2493,6 +2673,16 @@ void StatusPanel::wire_controls()
} else { } else {
on_set_nozzle_temp(UNIQUE_EXTRUDER_ID);//there is only one nozzle on_set_nozzle_temp(UNIQUE_EXTRUDER_ID);//there is only one nozzle
} }
} else {
// N-extruder widgets all share TEMP_OF_NORMAL_TYPE, so e.GetString() can't
// disambiguate them; identify the one that fired by object identity instead.
for (size_t i = 0; i < m_tempCtrl_nozzles.size(); ++i) {
if (m_tempCtrl_nozzles[i] == e.GetEventObject()) {
on_set_nozzle_temp((int)i);
break;
}
}
}
} else if (id == m_tempCtrl_chamber->GetType()) { } else if (id == m_tempCtrl_chamber->GetType()) {
if (!m_tempCtrl_chamber->IsOnChanging()) { if (!m_tempCtrl_chamber->IsOnChanging()) {
m_tempCtrl_chamber->SetOnChanging(); m_tempCtrl_chamber->SetOnChanging();
@@ -2516,10 +2706,12 @@ void StatusPanel::wire_controls()
m_setting_button->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this); m_setting_button->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this);
m_tempCtrl_bed->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_kill_focus), NULL, this); m_tempCtrl_bed->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_kill_focus), NULL, this);
m_tempCtrl_bed->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_set_focus), NULL, this); m_tempCtrl_bed->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_set_focus), NULL, this);
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
m_tempCtrl_nozzle->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this); m_tempCtrl_nozzle->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this);
m_tempCtrl_nozzle->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this); m_tempCtrl_nozzle->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this);
m_tempCtrl_nozzle_deputy->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this); m_tempCtrl_nozzle_deputy->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this);
m_tempCtrl_nozzle_deputy->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this); m_tempCtrl_nozzle_deputy->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this);
}
m_tempCtrl_chamber->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_cham_temp_kill_focus), NULL, this); m_tempCtrl_chamber->Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_cham_temp_kill_focus), NULL, this);
m_tempCtrl_chamber->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_cham_temp_set_focus), NULL, this); m_tempCtrl_chamber->Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_cham_temp_set_focus), NULL, this);
m_switch_lamp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_lamp_switch), NULL, this); m_switch_lamp->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_lamp_switch), NULL, this);
@@ -2539,6 +2731,7 @@ void StatusPanel::wire_controls()
m_bpButton_e_10->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_up_10), NULL, this); m_bpButton_e_10->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_up_10), NULL, this);
m_bpButton_e_down_10->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_down_10), NULL, this); m_bpButton_e_down_10->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_down_10), NULL, this);
m_nozzle_btn_panel->Connect(wxCUSTOMEVT_SWITCH_POS, wxCommandEventHandler(StatusPanel::on_nozzle_selected), NULL, this); m_nozzle_btn_panel->Connect(wxCUSTOMEVT_SWITCH_POS, wxCommandEventHandler(StatusPanel::on_nozzle_selected), NULL, this);
m_generic_nozzle_selector->Connect(wxEVT_CHOICE, wxCommandEventHandler(StatusPanel::on_nozzle_selected), NULL, this);
Bind(EVT_AMS_EXTRUSION_CALI, &StatusPanel::on_filament_extrusion_cali, this); Bind(EVT_AMS_EXTRUSION_CALI, &StatusPanel::on_filament_extrusion_cali, this);
Bind(EVT_AMS_LOAD, &StatusPanel::on_ams_load, this); Bind(EVT_AMS_LOAD, &StatusPanel::on_ams_load, this);
@@ -2580,11 +2773,19 @@ StatusPanel::~StatusPanel()
m_setting_button->Disconnect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this); m_setting_button->Disconnect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(StatusPanel::on_camera_enter), NULL, this);
m_tempCtrl_bed->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_kill_focus), NULL, this); m_tempCtrl_bed->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_kill_focus), NULL, this);
m_tempCtrl_bed->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_set_focus), NULL, this); m_tempCtrl_bed->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_bed_temp_set_focus), NULL, this);
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
m_tempCtrl_nozzle->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this); m_tempCtrl_nozzle->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this);
m_tempCtrl_nozzle->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this); m_tempCtrl_nozzle->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this);
m_tempCtrl_nozzle_deputy->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this); m_tempCtrl_nozzle_deputy->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this);
m_tempCtrl_nozzle_deputy->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this); m_tempCtrl_nozzle_deputy->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this);
} else {
for (auto& tempCtrl : m_tempCtrl_nozzles) {
tempCtrl->Disconnect(wxEVT_KILL_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_kill_focus), NULL, this);
tempCtrl->Disconnect(wxEVT_SET_FOCUS, wxFocusEventHandler(StatusPanel::on_nozzle_temp_set_focus), NULL, this);
}
}
m_switch_lamp->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_lamp_switch), NULL, this); m_switch_lamp->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_lamp_switch), NULL, this);
/*m_switch_nozzle_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this); /*m_switch_nozzle_fan->Disconnect(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_nozzle_fan_switch), NULL, this);
@@ -2603,6 +2804,7 @@ StatusPanel::~StatusPanel()
m_bpButton_e_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_up_10), NULL, this); m_bpButton_e_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_up_10), NULL, this);
m_bpButton_e_down_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_down_10), NULL, this); m_bpButton_e_down_10->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_axis_ctrl_e_down_10), NULL, this);
m_nozzle_btn_panel->Disconnect(wxCUSTOMEVT_SWITCH_POS, wxCommandEventHandler(StatusPanel::on_nozzle_selected), NULL, this); m_nozzle_btn_panel->Disconnect(wxCUSTOMEVT_SWITCH_POS, wxCommandEventHandler(StatusPanel::on_nozzle_selected), NULL, this);
m_generic_nozzle_selector->Disconnect(wxEVT_CHOICE, wxCommandEventHandler(StatusPanel::on_nozzle_selected), NULL, this);
m_switch_speed->Disconnect(wxEVT_LEFT_DOWN, wxCommandEventHandler(StatusPanel::on_switch_speed), 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_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_options_btn->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(StatusPanel::on_show_print_options), NULL, this);
@@ -2860,6 +3062,7 @@ void StatusPanel::update(MachineObject *obj)
if (!obj || !obj->is_info_ready()) if (!obj || !obj->is_info_ready())
{ {
m_nozzle_btn_panel->Disable(); m_nozzle_btn_panel->Disable();
m_generic_nozzle_selector->Disable();
return; return;
} }
@@ -3054,8 +3257,14 @@ void StatusPanel::show_printing_status(bool ctrl_area, bool temp_area)
} }
if (!temp_area) { if (!temp_area) {
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
m_tempCtrl_nozzle->Enable(false); m_tempCtrl_nozzle->Enable(false);
m_tempCtrl_nozzle_deputy->Enable(false); m_tempCtrl_nozzle_deputy->Enable(false);
} else {
for (auto& tempCtrl : m_tempCtrl_nozzles)
tempCtrl->Enable(false);
}
m_tempCtrl_bed->Enable(false); m_tempCtrl_bed->Enable(false);
m_tempCtrl_chamber->Enable(false); m_tempCtrl_chamber->Enable(false);
m_switch_speed->Enable(false); m_switch_speed->Enable(false);
@@ -3066,8 +3275,14 @@ void StatusPanel::show_printing_status(bool ctrl_area, bool temp_area)
m_switch_cham_fan->Enable(false);*/ m_switch_cham_fan->Enable(false);*/
m_switch_fan->Enable(false); m_switch_fan->Enable(false);
} else { } else {
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
m_tempCtrl_nozzle->Enable(); m_tempCtrl_nozzle->Enable();
m_tempCtrl_nozzle_deputy->Enable(); m_tempCtrl_nozzle_deputy->Enable();
} else {
for (auto& tempCtrl : m_tempCtrl_nozzles)
tempCtrl->Enable();
}
m_tempCtrl_bed->Enable(); m_tempCtrl_bed->Enable();
m_tempCtrl_chamber->Enable(); m_tempCtrl_chamber->Enable();
m_switch_speed->Enable(); m_switch_speed->Enable();
@@ -3084,6 +3299,10 @@ void StatusPanel::update_temp_ctrl(MachineObject *obj)
{ {
if (!obj) return; if (!obj) return;
const int nozzle_num = obj->GetExtderSystem()->GetTotalExtderCount();
if (!wxGetApp().preset_bundle->is_bbl_vendor())
sync_nozzle_temp_controls(nozzle_num);
DevBed* bed = obj->GetBed(); DevBed* bed = obj->GetBed();
int bed_cur_temp = bed->GetBedTemp(); int bed_cur_temp = bed->GetBedTemp();
int bed_target_temp = bed->GetBedTempTarget(); int bed_target_temp = bed->GetBedTempTarget();
@@ -3096,11 +3315,18 @@ void StatusPanel::update_temp_ctrl(MachineObject *obj)
m_tempCtrl_bed->SetMaxTemp(limit); m_tempCtrl_bed->SetMaxTemp(limit);
if (obj->nozzle_temp_range.size() >= 2) { if (obj->nozzle_temp_range.size() >= 2) {
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
m_tempCtrl_nozzle->SetMinTemp(obj->nozzle_temp_range[0]); m_tempCtrl_nozzle->SetMinTemp(obj->nozzle_temp_range[0]);
m_tempCtrl_nozzle->SetMaxTemp(obj->nozzle_temp_range[1]); m_tempCtrl_nozzle->SetMaxTemp(obj->nozzle_temp_range[1]);
m_tempCtrl_nozzle_deputy->SetMinTemp(obj->nozzle_temp_range[0]); m_tempCtrl_nozzle_deputy->SetMinTemp(obj->nozzle_temp_range[0]);
m_tempCtrl_nozzle_deputy->SetMaxTemp(obj->nozzle_temp_range[1]); m_tempCtrl_nozzle_deputy->SetMaxTemp(obj->nozzle_temp_range[1]);
} else {
for (auto& tempCtrl : m_tempCtrl_nozzles) {
tempCtrl->SetMinTemp(obj->nozzle_temp_range[0]);
tempCtrl->SetMaxTemp(obj->nozzle_temp_range[1]);
}
}
} }
// update temprature if not input temp target // update temprature if not input temp target
@@ -3117,15 +3343,31 @@ void StatusPanel::update_temp_ctrl(MachineObject *obj)
} }
bool to_update_layout = false; bool to_update_layout = false;
int nozzle_num = obj->GetExtderSystem()->GetTotalExtderCount();
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
for (auto& tempCtrl : m_tempCtrl_nozzles) {
if (tempCtrl->IsShown()) {
tempCtrl->Hide();
to_update_layout = true;
}
}
if (nozzle_num == 1) if (nozzle_num == 1)
{ {
m_tempCtrl_nozzle->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(MAIN_EXTRUDER_ID)); m_tempCtrl_nozzle->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(MAIN_EXTRUDER_ID));
m_tempCtrl_nozzle->SetCurrType(TEMP_OF_NORMAL_TYPE); m_tempCtrl_nozzle->SetCurrType(TEMP_OF_NORMAL_TYPE);
if (!m_tempCtrl_nozzle->IsShown()) {
m_tempCtrl_nozzle->Show();
to_update_layout = true;
}
m_tempCtrl_nozzle_deputy->SetCurrType(TEMP_OF_NORMAL_TYPE); m_tempCtrl_nozzle_deputy->SetCurrType(TEMP_OF_NORMAL_TYPE);
m_tempCtrl_nozzle_deputy->SetLabel(TEMP_BLANK_STR); m_tempCtrl_nozzle_deputy->SetLabel(TEMP_BLANK_STR);
if (m_tempCtrl_nozzle_deputy->IsShown()) {
m_tempCtrl_nozzle_deputy->Hide(); m_tempCtrl_nozzle_deputy->Hide();
to_update_layout = true;
}
if (m_tempCtrl_nozzle->GetMinSize() != TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON) if (m_tempCtrl_nozzle->GetMinSize() != TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON)
{ {
@@ -3137,11 +3379,17 @@ void StatusPanel::update_temp_ctrl(MachineObject *obj)
{ {
m_tempCtrl_nozzle->SetCurrType(TEMP_OF_MAIN_NOZZLE_TYPE); m_tempCtrl_nozzle->SetCurrType(TEMP_OF_MAIN_NOZZLE_TYPE);
m_tempCtrl_nozzle->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(MAIN_EXTRUDER_ID)); m_tempCtrl_nozzle->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(MAIN_EXTRUDER_ID));
if (!m_tempCtrl_nozzle->IsShown()) {
m_tempCtrl_nozzle->Show(); m_tempCtrl_nozzle->Show();
to_update_layout = true;
}
m_tempCtrl_nozzle_deputy->SetCurrType(TEMP_OF_DEPUTY_NOZZLE_TYPE); m_tempCtrl_nozzle_deputy->SetCurrType(TEMP_OF_DEPUTY_NOZZLE_TYPE);
m_tempCtrl_nozzle_deputy->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(DEPUTY_EXTRUDER_ID)); m_tempCtrl_nozzle_deputy->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent(DEPUTY_EXTRUDER_ID));
if (!m_tempCtrl_nozzle_deputy->IsShown()) {
m_tempCtrl_nozzle_deputy->Show(); m_tempCtrl_nozzle_deputy->Show();
to_update_layout = true;
}
if (m_tempCtrl_nozzle->GetMinSize() != TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON) if (m_tempCtrl_nozzle->GetMinSize() != TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON)
{ {
@@ -3149,7 +3397,25 @@ void StatusPanel::update_temp_ctrl(MachineObject *obj)
m_tempCtrl_nozzle->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON); m_tempCtrl_nozzle->SetMinSize(TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON);
} }
} }
}
else
{
if (m_tempCtrl_nozzle->IsShown()) {
m_tempCtrl_nozzle->Hide();
to_update_layout = true;
}
if (m_tempCtrl_nozzle_deputy->IsShown()) {
m_tempCtrl_nozzle_deputy->Hide();
to_update_layout = true;
}
for (size_t i = 0; i < static_cast<size_t>(nozzle_num); ++i)
{
m_tempCtrl_nozzles[i]->SetCurrTemp(obj->GetExtderSystem()->GetNozzleTempCurrent((int)i));
m_tempCtrl_nozzles[i]->SetCurrType(TEMP_OF_NORMAL_TYPE);
}
}
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
if (m_temp_nozzle_timeout > 0) { if (m_temp_nozzle_timeout > 0) {
m_temp_nozzle_timeout--; m_temp_nozzle_timeout--;
} else { } else {
@@ -3192,6 +3458,32 @@ void StatusPanel::update_temp_ctrl(MachineObject *obj)
} }
} }
} }
}
else {
assert(m_temp_nozzle_timeouts.size() == m_tempCtrl_nozzles.size());
for (size_t i = 0; i < static_cast<size_t>(nozzle_num); ++i) {
if (m_temp_nozzle_timeouts[i] > 0) {
m_temp_nozzle_timeouts[i]--;
} else {
if (!nozzle_temp_input) {
auto extder = obj->GetExtderSystem()->GetExtderById(i);
if (extder)
{
m_tempCtrl_nozzles[i]->SetTagTemp(extder->GetTargetTemp());
m_tempCtrl_nozzles[i]->SetCurrTemp((int)extder->GetCurrentTemp());
if (extder->GetTargetTemp() - extder->GetCurrentTemp() > TEMP_THRESHOLD_VAL)
{
m_tempCtrl_nozzles[i]->SetIconActive();
}
else
{
m_tempCtrl_nozzles[i]->SetIconNormal();
}
}
}
}
}
}
// support current temp for chamber // support current temp for chamber
if (obj->get_printer_series() == PrinterSeries::SERIES_X1) if (obj->get_printer_series() == PrinterSeries::SERIES_X1)
@@ -3260,65 +3552,91 @@ void StatusPanel::update_misc_ctrl(MachineObject *obj)
/*extder*/ /*extder*/
auto extder_system = obj->GetExtderSystem(); auto extder_system = obj->GetExtderSystem();
m_nozzle_num = extder_system->GetTotalExtderCount(); m_nozzle_num = extder_system->GetTotalExtderCount();
int select_index = m_nozzle_num - 1; const bool is_bbl_vendor = wxGetApp().preset_bundle->is_bbl_vendor();
const bool bbl_selector_was_shown = m_nozzle_btn_panel->IsShown();
const bool generic_selector_was_shown = m_generic_nozzle_selector->IsShown();
if (m_nozzle_num <= 0) {
m_nozzle_btn_panel->Hide();
m_generic_nozzle_selector->Hide();
m_extruder_book->SetSelection(0);
} else if (is_bbl_vendor) {
// Preserve Bambu's existing main/deputy presentation and left/right selector.
const int display_num = std::min(m_nozzle_num, static_cast<int>(m_extruderImage.size()));
const int select_index = display_num - 1;
ExtruderImage* image = m_extruderImage[select_index];
image->setGenericNozzleDisplay(false);
image->setExtruderCount(m_nozzle_num);
if (m_nozzle_num >= 2) { if (m_nozzle_num >= 2) {
m_extruder_book->SetSelection(m_nozzle_num); m_extruder_book->SetSelection(display_num);
/*style*/
m_nozzle_btn_panel->Show(); m_nozzle_btn_panel->Show();
m_extruderImage[select_index]->setExtruderCount(m_nozzle_num); m_generic_nozzle_selector->Hide();
if (obj->GetExtderSystem()->GetTotalExtderSize() > 1) if (extder_system->GetTotalExtderSize() > 1) {
{ image->update(get_extder_shown_state(extder_system->HasFilamentInExt(0)),
m_extruderImage[select_index]->update(get_extder_shown_state(obj->GetExtderSystem()->HasFilamentInExt(0)), get_extder_shown_state(extder_system->HasFilamentInExt(1)));
get_extder_shown_state(obj->GetExtderSystem()->HasFilamentInExt(1)));
} }
/*current*/ if (extder_system->GetCurrentExtderId() == 0xf) {
/*update when extder position changed or the machine changed*/ image->setExtruderUsed("");
if (obj->GetExtderSystem()->GetCurrentExtderId() == 0xf)
{
m_extruderImage[select_index]->setExtruderUsed("");
m_nozzle_btn_panel->updateState(""); m_nozzle_btn_panel->updateState("");
} } else if (extder_system->GetCurrentExtderId() == MAIN_EXTRUDER_ID) {
else if (obj->GetExtderSystem()->GetCurrentExtderId() == MAIN_EXTRUDER_ID) image->setExtruderUsed("right");
{
m_extruderImage[select_index]->setExtruderUsed("right");
m_nozzle_btn_panel->updateState("right"); m_nozzle_btn_panel->updateState("right");
} } else if (extder_system->GetCurrentExtderId() == DEPUTY_EXTRUDER_ID) {
else if (obj->GetExtderSystem()->GetCurrentExtderId() == DEPUTY_EXTRUDER_ID) image->setExtruderUsed("left");
{
m_extruderImage[select_index]->setExtruderUsed("left");
m_nozzle_btn_panel->updateState("left"); m_nozzle_btn_panel->updateState("left");
} }
m_nozzle_btn_panel->SetClientData(obj); m_nozzle_btn_panel->SetClientData(obj);
/*enable status*/
/* Can do switch while printing pause STUDIO-9789*/
if ((obj->is_in_printing() && !obj->is_in_printing_pause()) || if ((obj->is_in_printing() && !obj->is_in_printing_pause()) ||
obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE || obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE ||
obj->targ_nozzle_id_from_pc != INVALID_EXTRUDER_ID) obj->targ_nozzle_id_from_pc != INVALID_EXTRUDER_ID)
{
m_nozzle_btn_panel->Disable(); m_nozzle_btn_panel->Disable();
}
else else
{
m_nozzle_btn_panel->Enable(); m_nozzle_btn_panel->Enable();
} else {
m_nozzle_btn_panel->Hide();
m_generic_nozzle_selector->Hide();
m_extruder_book->SetSelection(display_num);
if (extder_system->GetTotalExtderSize() > 0)
image->update(get_extder_shown_state(extder_system->HasFilamentInExt(0)));
} }
} else { } else {
m_nozzle_btn_panel->Hide(); m_nozzle_btn_panel->Hide();
m_extruder_book->SetSelection(m_nozzle_num); m_extruder_book->SetSelection(1);
m_extruderImage[select_index]->setExtruderCount(m_nozzle_num); ExtruderImage* image = m_extruderImage.front();
image->setGenericNozzleDisplay(true);
image->setExtruderCount(m_nozzle_num);
if (extder_system->GetTotalExtderSize() > 0) const int current_nozzle_id = extder_system->GetCurrentExtderId();
{ const int selected_nozzle_id = current_nozzle_id >= 0 && current_nozzle_id < m_nozzle_num ? current_nozzle_id : -1;
ExtruderState shown_state = get_extder_shown_state(extder_system->HasFilamentInExt(0)); image->setExtruderUsed(selected_nozzle_id);
m_extruderImage[select_index]->update(shown_state); for (int i = 0; i < m_nozzle_num; ++i)
image->update(get_extder_shown_state(extder_system->HasFilamentInExt(i)), i);
image->Refresh();
if (m_generic_nozzle_selector_count != m_nozzle_num) {
m_generic_nozzle_selector->Clear();
for (int i = 0; i < m_nozzle_num; ++i)
m_generic_nozzle_selector->Append(wxString::Format("%s %d", _L("Nozzle"), i + 1));
m_generic_nozzle_selector_count = m_nozzle_num;
} }
m_generic_nozzle_selector->SetSelection(selected_nozzle_id);
m_generic_nozzle_selector->Show(m_nozzle_num > 1);
if ((obj->is_in_printing() && !obj->is_in_printing_pause()) ||
obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE ||
obj->targ_nozzle_id_from_pc != INVALID_EXTRUDER_ID)
m_generic_nozzle_selector->Disable();
else
m_generic_nozzle_selector->Enable();
} }
if (bbl_selector_was_shown != m_nozzle_btn_panel->IsShown() ||
generic_selector_was_shown != m_generic_nozzle_selector->IsShown())
m_nozzle_btn_panel->GetParent()->Layout();
/*switch extder*/ /*switch extder*/
m_extruder_switching_status->updateBy(obj); m_extruder_switching_status->updateBy(obj);
m_extruder_label->Show(!m_extruder_switching_status->has_content_shown());/*hide the label if there are shown infos from m_extruder_switching_status*/ m_extruder_label->Show(!m_extruder_switching_status->has_content_shown());/*hide the label if there are shown infos from m_extruder_switching_status*/
@@ -3496,6 +3814,7 @@ void StatusPanel::update_ams(MachineObject *obj)
// m_ams_control->SetExtruder(obj->is_filament_at_extruder(), obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id, obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id); // m_ams_control->SetExtruder(obj->is_filament_at_extruder(), obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.ams_id, obj->m_extder_data.extders[MAIN_NOZZLE_ID].snow.slot_id);
//} else { //} else {
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
/*right*/ /*right*/
if (obj->GetExtderSystem()->GetTotalExtderCount() > 0) { if (obj->GetExtderSystem()->GetTotalExtderCount() > 0) {
auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID); auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID);
@@ -3525,6 +3844,21 @@ void StatusPanel::update_ams(MachineObject *obj)
} }
m_ams_control->SetExtruder(ext->HasFilamentInExt(), DEPUTY_EXTRUDER_ID, ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id); m_ams_control->SetExtruder(ext->HasFilamentInExt(), DEPUTY_EXTRUDER_ID, ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id);
} }
} else {
/*all extruders, in id order*/
for (const auto& ext : obj->GetExtderSystem()->GetExtruders()) {
if (ext.HasFilamentInExt()) {
if (ext.GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext.GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) {
m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3);
} else {
m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2);
}
} else {
m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE);
}
m_ams_control->SetExtruder(ext.HasFilamentInExt(), ext.GetExtId(), ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id);
}
}
update_filament_loading_panel(obj); update_filament_loading_panel(obj);
@@ -4230,6 +4564,7 @@ void StatusPanel::on_set_nozzle_temp(int nozzle_id)
try { try {
long nozzle_temp; long nozzle_temp;
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
if (nozzle_id == MAIN_EXTRUDER_ID) { if (nozzle_id == MAIN_EXTRUDER_ID) {
wxString str = m_tempCtrl_nozzle->GetTextCtrl()->GetValue(); wxString str = m_tempCtrl_nozzle->GetTextCtrl()->GetValue();
if (str.ToLong(&nozzle_temp) && obj) { if (str.ToLong(&nozzle_temp) && obj) {
@@ -4259,6 +4594,21 @@ void StatusPanel::on_set_nozzle_temp(int nozzle_id)
obj->command_set_nozzle_new(DEPUTY_EXTRUDER_ID, nozzle_temp); obj->command_set_nozzle_new(DEPUTY_EXTRUDER_ID, nozzle_temp);
} }
} }
}
else if (nozzle_id >= 0 && nozzle_id < (int)m_tempCtrl_nozzles.size() &&
nozzle_id < obj->GetExtderSystem()->GetTotalExtderCount()) {
assert(m_tempCtrl_nozzles.size() == m_temp_nozzle_timeouts.size());
wxString str = m_tempCtrl_nozzles[nozzle_id]->GetTextCtrl()->GetValue();
if (str.ToLong(&nozzle_temp) && obj) {
set_hold_count(m_temp_nozzle_timeouts[nozzle_id]);
if (nozzle_temp > m_tempCtrl_nozzles[nozzle_id]->get_max_temp()) {
nozzle_temp = m_tempCtrl_nozzles[nozzle_id]->get_max_temp();
m_tempCtrl_nozzles[nozzle_id]->SetTagTemp(wxString::Format("%d", nozzle_temp));
m_tempCtrl_nozzles[nozzle_id]->Warning(false);
}
obj->command_set_nozzle_new(nozzle_id, nozzle_temp);
}
}
} catch (...) { } catch (...) {
; ;
} }
@@ -4340,10 +4690,17 @@ void StatusPanel::on_ams_load_curr()
return; return;
} }
// Filament Track Switch is calibrated: the load can go to either extruder, so ask the // Filament Track Switch is calibrated: the load can go to either/any extruder, so ask
// user which. Record each extruder's currently-loaded slot so the dialog can grey out a // the user which. Record each extruder's currently-loaded slot so the dialog can grey
// side that already holds this filament. // out a side that already holds this filament.
std::vector<std::pair<std::string, std::string>> extruderSlots(2, {"", ""}); // NOTE: FeedDirectionDialog/SetExtruderMapping (Widgets/AMSItem.{hpp,cpp}) take the real
// extruder count in the non-BBL path now, but that class's own internals haven't been
// audited for N > 2 -- this only fixes what's local to StatusPanel.cpp.
int extruder_count;
std::vector<std::pair<std::string, std::string>> extruderSlots;
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
extruder_count = 2;
extruderSlots.assign(2, {"", ""});
if (auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID); ext.has_value()) if (auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID); ext.has_value())
{ {
if (ext->HasFilamentInExt()) if (ext->HasFilamentInExt())
@@ -4358,8 +4715,19 @@ void StatusPanel::on_ams_load_curr()
extruderSlots[DEPUTY_EXTRUDER_ID] = {ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id}; extruderSlots[DEPUTY_EXTRUDER_ID] = {ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id};
} }
} }
} else {
extruder_count = obj->GetExtderSystem()->GetTotalExtderCount();
extruderSlots.assign(extruder_count, {"", ""});
for (const auto& ext : obj->GetExtderSystem()->GetExtruders())
{
if (ext.HasFilamentInExt())
{
extruderSlots[ext.GetExtId()] = {ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id};
}
}
}
FeedDirectionDialog dialog(nullptr, 2, obj->printer_type); FeedDirectionDialog dialog(nullptr, extruder_count, obj->printer_type);
dialog.SetExtruderMapping(obj, curr_ams_id, curr_can_id, extruderSlots); dialog.SetExtruderMapping(obj, curr_ams_id, curr_can_id, extruderSlots);
auto rtn = dialog.ShowModal(); auto rtn = dialog.ShowModal();
@@ -4461,6 +4829,7 @@ void StatusPanel::on_ams_switch(SimpleEvent &event)
{ {
if(obj){ if(obj){
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
/*right*/ /*right*/
if (obj->GetExtderSystem()->GetTotalExtderCount() > 0) { if (obj->GetExtderSystem()->GetTotalExtderCount() > 0) {
auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID); auto ext = obj->GetExtderSystem()->GetExtderById(MAIN_EXTRUDER_ID);
@@ -4478,7 +4847,21 @@ void StatusPanel::on_ams_switch(SimpleEvent &event)
/*left*/ /*left*/
if (obj->GetExtderSystem()->GetTotalExtderCount() > 1) { if (obj->GetExtderSystem()->GetTotalExtderCount() > 1) {
auto ext = obj->GetExtderSystem()->GetExtruders()[DEPUTY_EXTRUDER_ID]; auto ext = obj->GetExtderSystem()->GetExtderById(DEPUTY_EXTRUDER_ID);
if (ext->HasFilamentInExt()) {
if (ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext->GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3);
} else {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP2);
}
} else {
m_ams_control->SetAmsStep(ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE);
}
m_ams_control->SetExtruder(ext->HasFilamentInExt(), DEPUTY_EXTRUDER_ID, ext->GetSlotNow().ams_id, ext->GetSlotNow().slot_id);
}
} else {
/*all extruders, in id order*/
for (const auto& ext : obj->GetExtderSystem()->GetExtruders()) {
if (ext.HasFilamentInExt()) { if (ext.HasFilamentInExt()) {
if (ext.GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext.GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) { if (ext.GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_MAIN_ID) || ext.GetSlotNow().ams_id == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) {
m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3); m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, "0", AMSPassRoadType::AMS_ROAD_TYPE_LOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_COMBO_LOAD_STEP3);
@@ -4488,7 +4871,8 @@ void StatusPanel::on_ams_switch(SimpleEvent &event)
} else { } else {
m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE); m_ams_control->SetAmsStep(ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id, AMSPassRoadType::AMS_ROAD_TYPE_UNLOAD, AMSPassRoadSTEP::AMS_ROAD_STEP_NONE);
} }
m_ams_control->SetExtruder(ext.HasFilamentInExt(), DEPUTY_EXTRUDER_ID, ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id); m_ams_control->SetExtruder(ext.HasFilamentInExt(), ext.GetExtId(), ext.GetSlotNow().ams_id, ext.GetSlotNow().slot_id);
}
} }
} }
} }
@@ -5083,23 +5467,42 @@ void StatusPanel::on_xyz_abs(wxCommandEvent &event)
void StatusPanel::on_nozzle_selected(wxCommandEvent &event) void StatusPanel::on_nozzle_selected(wxCommandEvent &event)
{ {
const bool is_bbl_vendor = wxGetApp().preset_bundle->is_bbl_vendor();
if (obj) { if (obj) {
const int nozzle_id = event.GetInt();
/*Enable switch head while printing is paused STUDIO-9789*/ const auto extder_system = obj->GetExtderSystem();
if ((obj->is_in_printing() && !obj->is_in_printing_pause()) || obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE) { const int current_nozzle_id = extder_system->GetCurrentExtderId();
MessageDialog dlg(nullptr, _L("The printer is busy with another print job."), _L("Error"), wxICON_WARNING | wxOK); const int current_selection = current_nozzle_id >= 0 && current_nozzle_id < extder_system->GetTotalExtderCount()
dlg.ShowModal(); ? current_nozzle_id
: wxNOT_FOUND;
const bool nozzle_change_in_progress = !is_bbl_vendor && obj->targ_nozzle_id_from_pc != INVALID_EXTRUDER_ID;
if (!is_bbl_vendor && (nozzle_id < 0 || nozzle_id >= extder_system->GetTotalExtderCount())) {
m_generic_nozzle_selector->SetSelection(current_selection);
return; return;
} }
auto nozzle_id = event.GetInt(); /*Enable switch head while printing is paused STUDIO-9789*/
if ((obj->is_in_printing() && !obj->is_in_printing_pause()) ||
obj->ams_status_main == AMS_STATUS_MAIN_FILAMENT_CHANGE || nozzle_change_in_progress) {
MessageDialog dlg(nullptr, _L("The printer is busy with another print job."), _L("Error"), wxICON_WARNING | wxOK);
dlg.ShowModal();
if (!is_bbl_vendor)
m_generic_nozzle_selector->SetSelection(current_selection);
return;
}
if (!is_bbl_vendor)
m_generic_nozzle_selector->Disable();
if (obj->GetCtrl()->command_select_extruder(nozzle_id) == 0) if (obj->GetCtrl()->command_select_extruder(nozzle_id) == 0)
{ {
return; return;
} }
} }
if (is_bbl_vendor)
m_nozzle_btn_panel->Enable(); m_nozzle_btn_panel->Enable();
else
m_generic_nozzle_selector->Enable();
} }
void StatusPanel::on_show_print_options(wxCommandEvent& event) void StatusPanel::on_show_print_options(wxCommandEvent& event)
@@ -5211,6 +5614,8 @@ void StatusPanel::set_default()
m_switch_lamp_timeout = 0; m_switch_lamp_timeout = 0;
m_temp_nozzle_timeout = 0; m_temp_nozzle_timeout = 0;
m_temp_nozzle_deputy_timeout = 0; m_temp_nozzle_deputy_timeout = 0;
for (auto& timeout : m_temp_nozzle_timeouts)
timeout = 0;
m_temp_bed_timeout = 0; m_temp_bed_timeout = 0;
m_temp_chamber_timeout = 0; m_temp_chamber_timeout = 0;
m_switch_nozzle_fan_timeout = 0; m_switch_nozzle_fan_timeout = 0;
@@ -5218,6 +5623,12 @@ void StatusPanel::set_default()
m_switch_cham_fan_timeout = 0; m_switch_cham_fan_timeout = 0;
m_show_ams_group = false; m_show_ams_group = false;
m_show_filament_group = false; m_show_filament_group = false;
m_generic_nozzle_selector->Hide();
m_nozzle_btn_panel->Hide();
m_generic_nozzle_selector->Clear();
m_generic_nozzle_selector_count = 0;
m_extruder_book->SetSelection(0);
m_nozzle_btn_panel->GetParent()->Layout();
reset_printing_values(); reset_printing_values();
m_bitmap_timelapse_img->Hide(); m_bitmap_timelapse_img->Hide();
@@ -5370,10 +5781,17 @@ void StatusPanel::msw_rescale()
m_bpButton_xy->Rescale(); m_bpButton_xy->Rescale();
auto size = TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON; auto size = TEMP_CTRL_MIN_SIZE_ALIGN_ONE_ICON;
if (obj && obj->GetExtderSystem()->GetTotalExtderCount() >= 2) size = TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON; if (obj && obj->GetExtderSystem()->GetTotalExtderCount() >= 2) size = TEMP_CTRL_MIN_SIZE_ALIGN_TWO_ICON;
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
m_tempCtrl_nozzle->SetMinSize(size); m_tempCtrl_nozzle->SetMinSize(size);
m_tempCtrl_nozzle->Rescale(); m_tempCtrl_nozzle->Rescale();
m_tempCtrl_nozzle_deputy->SetMinSize(size); m_tempCtrl_nozzle_deputy->SetMinSize(size);
m_tempCtrl_nozzle_deputy->Rescale(); m_tempCtrl_nozzle_deputy->Rescale();
} else {
for (auto& tempCtrl : m_tempCtrl_nozzles) {
tempCtrl->SetMinSize(size);
tempCtrl->Rescale();
}
}
m_line_nozzle->SetSize(wxSize(-1, FromDIP(1))); m_line_nozzle->SetSize(wxSize(-1, FromDIP(1)));
m_tempCtrl_bed->SetMinSize(size); m_tempCtrl_bed->SetMinSize(size);
m_tempCtrl_bed->Rescale(); m_tempCtrl_bed->Rescale();
+26 -2
View File
@@ -1,6 +1,8 @@
#ifndef slic3r_StatusPanel_hpp_ #ifndef slic3r_StatusPanel_hpp_
#define slic3r_StatusPanel_hpp_ #define slic3r_StatusPanel_hpp_
#include <vector>
#include "libslic3r/ProjectTask.hpp" #include "libslic3r/ProjectTask.hpp"
#include "DeviceManager.hpp" #include "DeviceManager.hpp"
#include "MonitorPage.hpp" #include "MonitorPage.hpp"
@@ -41,6 +43,7 @@
#include "StagedBuild.hpp" #include "StagedBuild.hpp"
class StepIndicator; class StepIndicator;
class wxChoice;
#define COMMAND_TIMEOUT 5 #define COMMAND_TIMEOUT 5
@@ -115,6 +118,7 @@ class ExtruderImage : public wxWindow
ScalableBitmap *m_left_extruder_active_empty; ScalableBitmap *m_left_extruder_active_empty;
ScalableBitmap *m_left_extruder_unactive_filled; ScalableBitmap *m_left_extruder_unactive_filled;
ScalableBitmap *m_left_extruder_unactive_empty; ScalableBitmap *m_left_extruder_unactive_empty;
ScalableBitmap *m_right_extruder_active_filled; ScalableBitmap *m_right_extruder_active_filled;
ScalableBitmap *m_right_extruder_active_empty; ScalableBitmap *m_right_extruder_active_empty;
ScalableBitmap *m_right_extruder_unactive_filled; ScalableBitmap *m_right_extruder_unactive_filled;
@@ -128,15 +132,21 @@ class ExtruderImage : public wxWindow
ExtruderState m_left_ext_state = {ExtruderState::EMPTY_LOAD}; ExtruderState m_left_ext_state = {ExtruderState::EMPTY_LOAD};
ExtruderState m_right_ext_state = {ExtruderState::EMPTY_LOAD}; ExtruderState m_right_ext_state = {ExtruderState::EMPTY_LOAD};
ExtruderState m_single_ext_state = {ExtruderState::EMPTY_LOAD}; ExtruderState m_single_ext_state = {ExtruderState::EMPTY_LOAD};
std::vector<ExtruderState> m_multi_extruder_states;
bool m_generic_nozzle_display{false};
public: public:
void update(int nozzle_num, int nozzle_id); void update(int nozzle_num, int nozzle_id);
void update(ExtruderState single_state); void update(ExtruderState single_state);
void update(ExtruderState right_state, ExtruderState left_state); void update(ExtruderState right_state, ExtruderState left_state);
void update(ExtruderState state, int idx);
void msw_rescale(); void msw_rescale();
void setExtruderCount(int nozzle_num); void setExtruderCount(int nozzle_num);
void setGenericNozzleDisplay(bool enabled);
void setExtruderUsed(std::string loc); void setExtruderUsed(std::string loc);
void setExtruderUsed(int nozzle_idx);
void paintEvent(wxPaintEvent &evt); void paintEvent(wxPaintEvent &evt);
void render(wxDC &dc); void render(wxDC &dc);
@@ -470,6 +480,8 @@ protected:
std::vector<ExtruderImage *> m_extruderImage; std::vector<ExtruderImage *> m_extruderImage;
SwitchBoard * m_nozzle_btn_panel; SwitchBoard * m_nozzle_btn_panel;
wxChoice* m_generic_nozzle_selector{nullptr};
int m_generic_nozzle_selector_count{0};
wxStaticText * m_text_tasklist_caption; wxStaticText * m_text_tasklist_caption;
@@ -482,10 +494,18 @@ protected:
wxBoxSizer * m_misc_ctrl_sizer; wxBoxSizer * m_misc_ctrl_sizer;
StaticBox* m_fan_panel; StaticBox* m_fan_panel;
StaticLine * m_line_nozzle; StaticLine * m_line_nozzle;
TempInput* m_tempCtrl_nozzle; wxWindowID m_nozzle_temp_control_id{wxID_ANY};
wxWindow* m_temp_nozzle_parent{nullptr};
wxBoxSizer* m_temp_nozzle_sizer{nullptr};
size_t m_temp_nozzle_active_count{0};
TempInput* m_tempCtrl_nozzle{nullptr};
int m_temp_nozzle_timeout{ 0 }; int m_temp_nozzle_timeout{ 0 };
TempInput* m_tempCtrl_nozzle_deputy; TempInput* m_tempCtrl_nozzle_deputy{nullptr};
int m_temp_nozzle_deputy_timeout{ 0 }; int m_temp_nozzle_deputy_timeout{ 0 };
std::vector<TempInput*> m_tempCtrl_nozzles;
std::vector<int> m_temp_nozzle_timeouts;
TempInput * m_tempCtrl_bed; TempInput * m_tempCtrl_bed;
int m_temp_bed_timeout {0}; int m_temp_bed_timeout {0};
TempInput * m_tempCtrl_chamber; TempInput * m_tempCtrl_chamber;
@@ -601,6 +621,9 @@ public:
wxBoxSizer *create_temp_axis_group(wxWindow *parent); wxBoxSizer *create_temp_axis_group(wxWindow *parent);
wxBoxSizer *create_temp_control(wxWindow *parent); wxBoxSizer *create_temp_control(wxWindow *parent);
TempInput* create_nozzle_temp_control(wxWindow *parent, wxWindowID id);
void set_temp_input_colors(TempInput* temp_ctrl);
void ensure_nozzle_temp_controls(size_t count);
wxBoxSizer *create_misc_control(wxWindow *parent); wxBoxSizer *create_misc_control(wxWindow *parent);
wxBoxSizer *create_axis_control(wxWindow *parent); wxBoxSizer *create_axis_control(wxWindow *parent);
wxPanel *create_bed_control(wxWindow *parent); wxPanel *create_bed_control(wxWindow *parent);
@@ -631,6 +654,7 @@ private:
friend class MonitorPanel; friend class MonitorPanel;
void wire_controls(); void wire_controls();
bool load_thumbnail_from_url(const wxString &url, MachineObject *obj); bool load_thumbnail_from_url(const wxString &url, MachineObject *obj);
void sync_nozzle_temp_controls(size_t count);
protected: protected:
std::shared_ptr<SliceInfoPopup> m_slice_info_popup; std::shared_ptr<SliceInfoPopup> m_slice_info_popup;
+8 -1
View File
@@ -835,14 +835,21 @@ void MultiNozzleStatusTable::UpdateRackInfo(std::weak_ptr<DevNozzleRack> rack)
bool has_right = false; bool has_right = false;
for (auto& elem : nozzles_in_extruder) { for (auto& elem : nozzles_in_extruder) {
auto& nozzle = elem.second; auto& nozzle = elem.second;
int extruder_id = nozzle.AtLeftExtruder() ? 0 : 1;
int extruder_id{};
if (wxGetApp().preset_bundle->is_bbl_vendor()) {
extruder_id = nozzle.AtLeftExtruder() ? 0 : 1;
if (nozzle.AtRightExtruder()) if (nozzle.AtRightExtruder())
has_right = true; has_right = true;
}
else
extruder_id = nozzle.GetExtruderId();
NozzleVolumeType volume_type = DevNozzle::ToNozzleVolumeType(nozzle.m_nozzle_flow); NozzleVolumeType volume_type = DevNozzle::ToNozzleVolumeType(nozzle.m_nozzle_flow);
m_badge->SetExtruderInfo(extruder_id, format_diameter_to_str(nozzle.GetNozzleDiameter()), volume_type); m_badge->SetExtruderInfo(extruder_id, format_diameter_to_str(nozzle.GetNozzleDiameter()), volume_type);
} }
// TODO: Update for N extruders
m_badge->SetExtruderValid(has_right); m_badge->SetExtruderValid(has_right);
} }
} }
+3
View File
@@ -170,6 +170,9 @@ void TempInput::SetFinish()
wxCommandEvent event(wxCUSTOMEVT_SET_TEMP_FINISH); wxCommandEvent event(wxCUSTOMEVT_SET_TEMP_FINISH);
event.SetInt(temp_type); event.SetInt(temp_type);
event.SetString(wxString::Format("%d", m_input_type)); event.SetString(wxString::Format("%d", m_input_type));
// N-extruder temp controls all share TEMP_OF_NORMAL_TYPE, so the string payload above can't
// tell them apart; carry widget identity so the listener can find which one fired.
event.SetEventObject(this);
wxPostEvent(this->GetParent(), event); wxPostEvent(this->GetParent(), event);
} }
+100 -5
View File
@@ -1472,6 +1472,25 @@ int MoonrakerPrinterAgent::handle_request(const std::string& dev_id, const std::
} }
} }
// Tool selection is printer-specific G-code. Moonraker forwards the
// conventional T<index> command to Klipper, where the printer can
// implement logical selection or a physical toolhead attach macro.
if (cmd == "select_extruder") {
if (!json["print"].contains("extruder_index") || !json["print"]["extruder_index"].is_number_integer()) {
BOOST_LOG_TRIVIAL(error) << "MoonrakerPrinterAgent: select_extruder missing integer extruder_index, full json: " << json_str;
return BAMBU_NETWORK_ERR_INVALID_RESULT;
}
const int extruder_idx = json["print"]["extruder_index"].get<int>();
if (extruder_idx < 0) {
BOOST_LOG_TRIVIAL(error) << "MoonrakerPrinterAgent: select_extruder received negative extruder_index: " << extruder_idx;
return BAMBU_NETWORK_ERR_INVALID_RESULT;
}
send_gcode_async(dev_id, "T" + std::to_string(extruder_idx));
return BAMBU_NETWORK_SUCCESS;
}
// why: no current OrcaSlicer sender emits the "home" discriminator; // why: no current OrcaSlicer sender emits the "home" discriminator;
// GUI homing uses gcode_line with G28 instead. // GUI homing uses gcode_line with G28 instead.
if (cmd == "home") { if (cmd == "home") {
@@ -1669,7 +1688,7 @@ bool MoonrakerPrinterAgent::query_printer_status(const ConnectionSettings& conne
nlohmann::json& status, nlohmann::json& status,
std::string& error) const std::string& error) const
{ {
std::string url = join_url(connection.base_url, "/printer/objects/query?print_stats&virtual_sdcard&extruder&heater_bed&fan"); std::string url = join_url(connection.base_url, "/printer/objects/query?print_stats&virtual_sdcard&toolhead&extruder&heater_bed&fan");
std::string response_body; std::string response_body;
bool success = false; bool success = false;
@@ -2332,11 +2351,12 @@ void MoonrakerPrinterAgent::run_status_stream(std::string dev_id, ConnectionSett
} }
for (const auto& name : this->available_objects) { for (const auto& name : this->available_objects) {
if (name == "extruder" || name.rfind("extruder", 0) == 0) { const bool is_main_extruder = name == "extruder";
const bool is_additional_extruder =
name.rfind("extruder", 0) == 0 && name.size() > 8 &&
std::all_of(name.begin() + 8, name.end(), [](unsigned char c) { return std::isdigit(c) != 0; });
if (is_main_extruder || is_additional_extruder) {
subscribe_objects.insert(name); subscribe_objects.insert(name);
if (name == "extruder") {
break;
}
} }
} }
} else { } else {
@@ -2771,6 +2791,81 @@ nlohmann::json MoonrakerPrinterAgent::build_print_payload_locked() const
} }
} }
// MachineObject::parse_new_info() only parses device.extruder when the four
// legacy new-protocol fields are present. Moonraker has no equivalents, so
// empty values act as compatibility markers without enabling any features.
std::map<int, const nlohmann::json*> extruder_status;
for (const auto& item : status_cache.items()) {
int extruder_id = -1;
if (item.key() == "extruder") {
extruder_id = 0;
} else if (item.key().rfind("extruder", 0) == 0 && item.key().size() > 8 &&
std::all_of(item.key().begin() + 8, item.key().end(), [](unsigned char c) { return std::isdigit(c) != 0; })) {
try {
extruder_id = std::stoi(item.key().substr(8));
} catch (...) {
extruder_id = -1;
}
}
if (extruder_id >= 0 && item.value().is_object()) {
extruder_status.emplace(extruder_id, &item.value());
}
}
if (!extruder_status.empty()) {
auto& device_extruder = payload["print"]["device"]["extruder"];
int current_extruder_id = 0;
if (status_cache.contains("toolhead") && status_cache["toolhead"].is_object() &&
status_cache["toolhead"].contains("extruder") && status_cache["toolhead"]["extruder"].is_string()) {
const std::string active_extruder = status_cache["toolhead"]["extruder"].get<std::string>();
if (active_extruder != "extruder" && active_extruder.rfind("extruder", 0) == 0 && active_extruder.size() > 8 &&
std::all_of(active_extruder.begin() + 8, active_extruder.end(), [](unsigned char c) { return std::isdigit(c) != 0; })) {
try {
const int parsed_id = std::stoi(active_extruder.substr(8));
if (parsed_id >= 0 && parsed_id < 16 && extruder_status.count(parsed_id) != 0) {
current_extruder_id = parsed_id;
}
} catch (...) {
// Keep the main extruder as the fallback for malformed status data.
}
}
}
const int extruder_count = std::min<int>(static_cast<int>(extruder_status.size()), 0xF);
device_extruder["state"] = extruder_count | (current_extruder_id << 4);
device_extruder["info"] = nlohmann::json::array();
auto encoded_temperature = [](const nlohmann::json& status, const char* key) {
if (!status.contains(key) || !status[key].is_number()) {
return 0;
}
const double temperature = status[key].get<double>();
return std::clamp(static_cast<int>(temperature + 0.5), 0, 65535);
};
for (const auto& [extruder_id, status] : extruder_status) {
const int current_temperature = encoded_temperature(*status, "temperature");
const int target_temperature = encoded_temperature(*status, "target");
device_extruder["info"].push_back({
{"id", extruder_id},
{"filam_bak", nlohmann::json::array()},
{"info", 1 << 3}, // The configured Moonraker extruder has a toolhead.
{"temp", current_temperature | (target_temperature << 16)},
{"spre", 0},
{"snow", 0},
{"star", 0},
{"stat", 0},
{"hnow", 0},
});
}
payload["print"]["cfg"] = "";
payload["print"]["fun"] = "";
payload["print"]["aux"] = "";
payload["print"]["stat"] = "";
}
if (status_cache.contains("heater_bed") && status_cache["heater_bed"].is_object()) { if (status_cache.contains("heater_bed") && status_cache["heater_bed"].is_object()) {
const auto& bed = status_cache["heater_bed"]; const auto& bed = status_cache["heater_bed"];
if (bed.contains("temperature") && bed["temperature"].is_number()) { if (bed.contains("temperature") && bed["temperature"].is_number()) {