mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-25 09:50:59 +00:00
Fix broken editing of filament in device
This commit is contained in:
@@ -4255,9 +4255,19 @@ std::vector<std::vector<DynamicPrintConfig>> PresetBundle::get_extruder_filament
|
||||
return filament_infos;
|
||||
}
|
||||
|
||||
// ORCA TODO: currently, this function assumes the printer name follows the pattern of "<printer_model> <nozzle_diameter>", e.g.
|
||||
// printer_type: "Bambu Lab X2D", nozzle_diameter_str: "0.4 nozzle" => printer_name: "Bambu Lab X2D 0.4 nozzle". If the printer name does
|
||||
// not follow this pattern, the function may not work correctly.
|
||||
std::string PresetBundle::get_printer_model_display_name(const std::string &model_id) const
|
||||
{
|
||||
for (const auto &vendor_entry : vendors) {
|
||||
for (const auto &model : vendor_entry.second.models) {
|
||||
if (model.model_id == model_id)
|
||||
return model.name;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// ORCA TODO: this assumes printer names follow "<printer_model> <nozzle_diameter>", e.g.
|
||||
// "Bambu Lab X2D 0.4 nozzle". Other naming schemes may not resolve correctly.
|
||||
std::set<std::string> PresetBundle::get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, std::string nozzle_diameter_str, bool system_only)
|
||||
{
|
||||
std::set<std::string> printer_names;
|
||||
|
||||
@@ -391,6 +391,7 @@ public:
|
||||
|
||||
std::vector<std::vector<DynamicPrintConfig>> get_extruder_filament_info() const;
|
||||
|
||||
std::string get_printer_model_display_name(const std::string &model_id) const;
|
||||
std::set<std::string> get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, std::string nozzle_diameter_str, bool system_only = true);
|
||||
// Orca: the root filament presets a connected machine can use, resolved with the rule the rest
|
||||
// of the app applies (is_compatible_with_printer): an empty compatible_printers means every
|
||||
|
||||
@@ -431,6 +431,10 @@ void AMSMaterialsSetting::update_filament_editing(bool is_printing)
|
||||
m_button_confirm->Show(true);
|
||||
}
|
||||
|
||||
const bool can_edit = !is_printing || obj->is_support_filament_setting_inprinting;
|
||||
m_input_nozzle_min->Enable(m_is_third && can_edit);
|
||||
m_input_nozzle_max->Enable(m_is_third && can_edit);
|
||||
|
||||
if (!m_is_third) {
|
||||
m_tip_readonly->SetLabelText(wxEmptyString);
|
||||
m_tip_readonly->Hide();
|
||||
@@ -453,6 +457,8 @@ void AMSMaterialsSetting::update_filament_editing(bool is_printing)
|
||||
if (m_view_only) { // Orca: view-only (2D laser/cut) — lock every edit control and hide apply/reset
|
||||
m_comboBox_filament->Enable(false);
|
||||
m_comboBox_cali_result->Enable(false);
|
||||
m_input_nozzle_min->Enable(false);
|
||||
m_input_nozzle_max->Enable(false);
|
||||
m_input_k_val->Enable(false);
|
||||
m_input_n_val->Enable(false);
|
||||
m_button_confirm->Hide();
|
||||
@@ -940,6 +946,21 @@ static void _collect_filament_info(const wxString& shown_name,
|
||||
query_filament_types[shown_name] = filament.config.get_filament_type();
|
||||
}
|
||||
|
||||
static std::string sGetFilamentPrinterModel(MachineObject *obj, PresetBundle *preset_bundle)
|
||||
{
|
||||
if (!obj || !preset_bundle)
|
||||
return {};
|
||||
|
||||
const wxString device_model = obj->get_printer_type_display_str();
|
||||
if (!device_model.empty() && device_model != "OrcaSonar Printer" && device_model != _L("Unknown"))
|
||||
return device_model.ToStdString();
|
||||
|
||||
// OrcaSonar's model ID is optional; use the selected profile when it is generic.
|
||||
const ConfigOption *opt = preset_bundle->printers.get_selected_preset().config.option("printer_model");
|
||||
const auto *model = dynamic_cast<const ConfigOptionString *>(opt);
|
||||
return model ? model->value : std::string();
|
||||
}
|
||||
|
||||
void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_min, wxString temp_max, wxString k, wxString n)
|
||||
{
|
||||
if (!obj) return;
|
||||
@@ -952,6 +973,8 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
|
||||
m_input_k_val->GetTextCtrl()->SetValue(k);
|
||||
m_input_n_val->GetTextCtrl()->SetValue(n);
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
|
||||
wxArrayString filament_items;
|
||||
wxString bambu_filament_name;
|
||||
@@ -965,9 +988,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
map_filament_items.clear();
|
||||
PresetBundle * preset_bundle = wxGetApp().preset_bundle;
|
||||
std::ostringstream stream;
|
||||
// Defensive: this dialog is opened only from StatusPanel (BBL-only) today, so the fallback fires
|
||||
// only during the brief BBL startup window before firmware reports nozzle info. Without this,
|
||||
// the "0.0" lookup string returns an empty set and the filament dropdown goes blank.
|
||||
// Use the selected profile's nozzle diameter until the connected device reports one.
|
||||
float machine_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
|
||||
if (machine_diameter == 0.0f && preset_bundle) {
|
||||
const ConfigOption *opt = preset_bundle->printers.get_selected_preset().config.option("nozzle_diameter");
|
||||
@@ -975,11 +996,12 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
}
|
||||
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
||||
std::string nozzle_diameter_str = stream.str();
|
||||
const std::string filament_printer_model = sGetFilamentPrinterModel(obj, preset_bundle);
|
||||
|
||||
if (preset_bundle) {
|
||||
if (preset_bundle && !filament_printer_model.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "system_preset_bundle filament number=" << preset_bundle->filaments.size();
|
||||
for (Preset *filament_it : preset_bundle->get_filament_presets_for_machine(
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
filament_printer_model, nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
if (!filament_id_set.insert(filament_it->filament_id).second)
|
||||
continue;
|
||||
const std::string alias = preset_bundle->filaments.get_preset_alias(*filament_it, true);
|
||||
@@ -1045,6 +1067,10 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
else {
|
||||
m_comboBox_filament->Show();
|
||||
m_readonly_filament->Hide();
|
||||
if (!temp_min.IsEmpty() && temp_min != "0")
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(temp_min);
|
||||
if (!temp_max.IsEmpty() && temp_max != "0")
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(temp_max);
|
||||
}
|
||||
|
||||
if (obj->cali_version >= 0) {
|
||||
@@ -1182,6 +1208,7 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
}
|
||||
|
||||
m_comboBox_filament->Set(filament_items);
|
||||
m_comboBox_filament->SetClientData(new int(1));
|
||||
m_comboBox_filament->SetSelection(selection_idx);
|
||||
post_select_event(selection_idx);
|
||||
|
||||
@@ -1189,9 +1216,6 @@ void AMSMaterialsSetting::Popup(wxString filament, wxString sn, wxString temp_mi
|
||||
m_comboBox_filament->SetValue(wxEmptyString);
|
||||
}
|
||||
|
||||
// Set the flag whether to open the filament setting dialog from the device page
|
||||
m_comboBox_filament->SetClientData(new int(1));
|
||||
|
||||
update();
|
||||
Layout();
|
||||
Fit();
|
||||
@@ -1222,15 +1246,14 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
{
|
||||
// Get the flag whether to open the filament setting dialog from the device page
|
||||
int* from_printer = static_cast<int*>(m_comboBox_filament->GetClientData());
|
||||
const bool initial_printer_selection = from_printer && *from_printer == 1;
|
||||
|
||||
m_filament_type = "";
|
||||
PresetBundle* preset_bundle = wxGetApp().preset_bundle;
|
||||
if (preset_bundle) {
|
||||
std::ostringstream stream;
|
||||
if (obj) {
|
||||
// Defensive: this dialog is opened only from StatusPanel (BBL-only) today, so the fallback fires
|
||||
// only during the brief BBL startup window before firmware reports nozzle info. Without this,
|
||||
// the "0.0" lookup string returns an empty set and filament lookup yields no results.
|
||||
// Use the selected profile's nozzle diameter until the connected device reports one.
|
||||
float machine_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
|
||||
if (machine_diameter == 0.0f) {
|
||||
const ConfigOption *opt = preset_bundle->printers.get_selected_preset().config.option("nozzle_diameter");
|
||||
@@ -1239,30 +1262,32 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
stream << std::fixed << std::setprecision(1) << machine_diameter;
|
||||
}
|
||||
std::string nozzle_diameter_str = stream.str();
|
||||
const std::string filament_printer_model = sGetFilamentPrinterModel(obj, preset_bundle);
|
||||
// Resolve the selection against the same list Popup() built the dropdown from, so the two
|
||||
// halves of the dialog cannot disagree about which filaments this machine can use.
|
||||
const std::string selected = m_comboBox_filament->GetValue().ToStdString();
|
||||
if (!selected.empty()) {
|
||||
if (!selected.empty() && !filament_printer_model.empty()) {
|
||||
const std::string filament_id = map_filament_items[selected].filament_id;
|
||||
for (Preset *it : preset_bundle->get_filament_presets_for_machine(
|
||||
DevPrinterConfigUtil::get_printer_display_name(obj->printer_type), nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
filament_printer_model, nozzle_diameter_str, obj->is_support_user_preset)) {
|
||||
if (it->filament_id != filament_id)
|
||||
continue;
|
||||
// ) if nozzle_temperature_range is found
|
||||
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
|
||||
if (opt_min_ints) {
|
||||
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
|
||||
if (!initial_printer_selection) {
|
||||
ConfigOption* opt_min = it->config.option("nozzle_temperature_range_low");
|
||||
if (opt_min) {
|
||||
ConfigOptionInts* opt_min_ints = dynamic_cast<ConfigOptionInts*>(opt_min);
|
||||
if (opt_min_ints) {
|
||||
wxString text_nozzle_temp_min = wxString::Format("%d", opt_min_ints->get_at(0));
|
||||
m_input_nozzle_min->GetTextCtrl()->SetValue(text_nozzle_temp_min);
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigOption* opt_max = it->config.option("nozzle_temperature_range_high");
|
||||
if (opt_max) {
|
||||
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
|
||||
if (opt_max_ints) {
|
||||
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
|
||||
ConfigOption* opt_max = it->config.option("nozzle_temperature_range_high");
|
||||
if (opt_max) {
|
||||
ConfigOptionInts* opt_max_ints = dynamic_cast<ConfigOptionInts*>(opt_max);
|
||||
if (opt_max_ints) {
|
||||
wxString text_nozzle_temp_max = wxString::Format("%d", opt_max_ints->get_at(0));
|
||||
m_input_nozzle_max->GetTextCtrl()->SetValue(text_nozzle_temp_max);
|
||||
}
|
||||
}
|
||||
}
|
||||
ConfigOption* opt_type = it->config.option("filament_type");
|
||||
@@ -1301,13 +1326,16 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
m_button_confirm->Disable(); // ORCA No need to change style
|
||||
m_comboBox_cali_result->Clear();
|
||||
m_comboBox_cali_result->SetValue(wxEmptyString);
|
||||
m_input_k_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
m_input_n_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
if (!initial_printer_selection) {
|
||||
m_input_k_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
m_input_n_val->GetTextCtrl()->SetValue(wxEmptyString);
|
||||
}
|
||||
m_comboBox_filament->SetClientData(new int(0));
|
||||
return;
|
||||
}
|
||||
else {
|
||||
m_button_confirm->Enable(true); // ORCA No need to change style
|
||||
if (!m_view_only)
|
||||
m_button_confirm->Enable(true); // ORCA No need to change style
|
||||
}
|
||||
|
||||
//filament id
|
||||
@@ -1331,6 +1359,9 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ams_filament_id.empty())
|
||||
m_clr_picker->is_empty(false);
|
||||
|
||||
wxArrayString items;
|
||||
m_pa_profile_items.clear();
|
||||
m_comboBox_cali_result->SetValue(wxEmptyString);
|
||||
@@ -1437,7 +1468,7 @@ void AMSMaterialsSetting::on_select_filament(wxCommandEvent &evt)
|
||||
else {
|
||||
if (!ams_filament_id.empty()) {
|
||||
//m_input_k_val->GetTextCtrl()->SetValue("0.00");
|
||||
m_input_k_val->Enable(true);
|
||||
m_input_k_val->Enable(!m_view_only);
|
||||
}
|
||||
else {
|
||||
//m_input_k_val->GetTextCtrl()->SetValue("0.00");
|
||||
|
||||
@@ -378,16 +378,9 @@ wxString MachineObject::get_printer_type_display_str() const
|
||||
{
|
||||
std::string display_name = DevPrinterConfigUtil::get_printer_display_name(printer_type);
|
||||
|
||||
// Bambu printers use m_resource_file_path + "/printers/" + type_str + ".json", which is a semantic that only works for their profiles.
|
||||
// For any other profile, we can simply consult preset bundle if the model_id exists.
|
||||
if (display_name.empty()) {
|
||||
for (const auto& [vendor_id, vendor] : GUI::wxGetApp().preset_bundle->vendors) {
|
||||
for (const auto& model : vendor.models) {
|
||||
if (printer_type == model.model_id)
|
||||
display_name = model.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Bambu names come from Bambu configs; other vendors resolve through preset model IDs.
|
||||
if (display_name.empty() && GUI::wxGetApp().preset_bundle)
|
||||
display_name = GUI::wxGetApp().preset_bundle->get_printer_model_display_name(printer_type);
|
||||
|
||||
if (!display_name.empty())
|
||||
return display_name;
|
||||
|
||||
@@ -4593,7 +4593,7 @@ void StatusPanel::on_filament_edit(wxCommandEvent &event)
|
||||
m_filament_setting_dlg->set_ctype(tray->ctype);
|
||||
m_filament_setting_dlg->ams_filament_id = tray->setting_id;
|
||||
|
||||
if (m_filament_setting_dlg->ams_filament_id.empty())
|
||||
if (tray->is_empty)
|
||||
{
|
||||
m_filament_setting_dlg->set_empty_color(color);
|
||||
}
|
||||
@@ -4608,12 +4608,12 @@ void StatusPanel::on_filament_edit(wxCommandEvent &event)
|
||||
// metadata, and the spec says it must never be interpreted — so
|
||||
// the tag alone must not make their trays read-only.
|
||||
m_filament_setting_dlg->m_is_third = !obj->is_bbl_agent() || !DevFilaSystem::IsBBL_Filament(tray->tag_uid);
|
||||
temp_max = tray->nozzle_temp_max;
|
||||
temp_min = tray->nozzle_temp_min;
|
||||
if (!m_filament_setting_dlg->m_is_third)
|
||||
{
|
||||
sn_number = tray->uuid;
|
||||
filament = tray->sub_brands;
|
||||
temp_max = tray->nozzle_temp_max;
|
||||
temp_min = tray->nozzle_temp_min;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4667,7 +4667,7 @@ void StatusPanel::on_ext_spool_edit(wxCommandEvent &event)
|
||||
}
|
||||
m_filament_setting_dlg->set_ctype(obj->vt_slot[nozzle_index].ctype);
|
||||
|
||||
if (m_filament_setting_dlg->ams_filament_id.empty()) {
|
||||
if (obj->vt_slot[nozzle_index].is_empty) {
|
||||
m_filament_setting_dlg->set_empty_color(color);
|
||||
}
|
||||
else {
|
||||
@@ -4676,11 +4676,11 @@ void StatusPanel::on_ext_spool_edit(wxCommandEvent &event)
|
||||
}
|
||||
|
||||
m_filament_setting_dlg->m_is_third = !obj->is_bbl_agent() || !DevFilaSystem::IsBBL_Filament(obj->vt_slot[nozzle_index].tag_uid);
|
||||
temp_max = obj->vt_slot[nozzle_index].nozzle_temp_max;
|
||||
temp_min = obj->vt_slot[nozzle_index].nozzle_temp_min;
|
||||
if (!m_filament_setting_dlg->m_is_third) {
|
||||
sn_number = obj->vt_slot[nozzle_index].uuid;
|
||||
filament = obj->vt_slot[nozzle_index].sub_brands;
|
||||
temp_max = obj->vt_slot[nozzle_index].nozzle_temp_max;
|
||||
temp_min = obj->vt_slot[nozzle_index].nozzle_temp_min;
|
||||
}
|
||||
|
||||
m_filament_setting_dlg->Move(wxPoint(current_position_x,current_position_y));
|
||||
|
||||
@@ -1407,6 +1407,21 @@ TEST_CASE("Filaments offered for a machine follow the app's compatibility rule",
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Printer model ids resolve to vendor display names", "[Preset][Bundle]")
|
||||
{
|
||||
PresetBundle bundle;
|
||||
VendorProfile qidi("Qidi");
|
||||
qidi.name = "Qidi";
|
||||
VendorProfile::PrinterModel model;
|
||||
model.model_id = "Qidi-Q1Pro";
|
||||
model.name = "Qidi Q1 Pro";
|
||||
qidi.models.push_back(model);
|
||||
bundle.vendors.emplace(qidi.id, qidi);
|
||||
|
||||
CHECK(bundle.get_printer_model_display_name("Qidi-Q1Pro") == "Qidi Q1 Pro");
|
||||
CHECK(bundle.get_printer_model_display_name("unknown-model").empty());
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
@@ -20,16 +20,17 @@
|
||||
using namespace Slic3r;
|
||||
using namespace Slic3r::GUI;
|
||||
|
||||
TEST_CASE("Configured empty AMS trays remain distinct from unknown trays", "[AMSItem]")
|
||||
TEST_CASE("Configured empty and partial AMS trays remain distinct from unknown trays", "[AMSItem]")
|
||||
{
|
||||
MachineObject machine(nullptr, nullptr, "test", "test-device", "127.0.0.1");
|
||||
machine.printer_agent_id = "orca";
|
||||
|
||||
machine.parse_json("lan", R"({"print":{"command":"push_status","msg":0,"ams":{
|
||||
"ams_exist_bits":"1","tray_exist_bits":"3","ams":[
|
||||
"ams_exist_bits":"1","tray_exist_bits":"7","ams":[
|
||||
{"id":"0","info":"0001","tray":[
|
||||
{"id":"0","tag_uid":"0000000000000000","tray_info_idx":"","tray_type":"","tray_color":"00000000"},
|
||||
{"id":"1"}
|
||||
{"id":"1"},
|
||||
{"id":"2","tag_uid":"0000000000000000","tray_info_idx":"","tray_type":"PLA","tray_color":"FF0000FF"}
|
||||
]}
|
||||
]
|
||||
}}})", false);
|
||||
@@ -43,12 +44,14 @@ TEST_CASE("Configured empty AMS trays remain distinct from unknown trays", "[AMS
|
||||
CHECK(ams->GetTray("0")->is_exists);
|
||||
AMSinfo info;
|
||||
REQUIRE(info.parse_ams_info(&machine, ams));
|
||||
REQUIRE(info.cans.size() == 2);
|
||||
REQUIRE(info.cans.size() == 3);
|
||||
|
||||
CHECK(info.cans[0].is_empty);
|
||||
CHECK(info.cans[0].material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND);
|
||||
CHECK_FALSE(info.cans[1].is_empty);
|
||||
CHECK(info.cans[1].material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND);
|
||||
CHECK_FALSE(info.cans[2].is_empty);
|
||||
CHECK(info.cans[2].material_state == AMSCanType::AMS_CAN_TYPE_THIRDBRAND);
|
||||
}
|
||||
|
||||
TEST_CASE("Empty external slots remain distinct from unknown slots", "[AMSItem]")
|
||||
|
||||
Reference in New Issue
Block a user