mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-28 19:31:22 +00:00
Merge main
This commit is contained in:
@@ -408,7 +408,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
|
|||||||
ExtrusionRole role = is_external ? erExternalPerimeter : erPerimeter;
|
ExtrusionRole role = is_external ? erExternalPerimeter : erPerimeter;
|
||||||
|
|
||||||
const bool is_contour = !extrusion->is_closed || pg_extrusion.is_contour;
|
const bool is_contour = !extrusion->is_closed || pg_extrusion.is_contour;
|
||||||
apply_fuzzy_skin(extrusion, perimeter_generator, is_contour);
|
apply_fuzzy_skin(extrusion, perimeter_generator, is_contour, extrusion->is_closed);
|
||||||
|
|
||||||
ExtrusionPaths paths;
|
ExtrusionPaths paths;
|
||||||
// detect overhanging/bridging perimeters
|
// detect overhanging/bridging perimeters
|
||||||
|
|||||||
@@ -3311,64 +3311,6 @@ void PresetBundle::export_selections(AppConfig& config)
|
|||||||
prints.get_selected_preset_name() % filament_presets[0];
|
prints.get_selected_preset_name() % filament_presets[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// BBS
|
|
||||||
void PresetBundle::set_num_filaments(unsigned int n, std::vector<std::string> new_colors)
|
|
||||||
{
|
|
||||||
int old_filament_count = this->filament_presets.size();
|
|
||||||
if (n > old_filament_count && old_filament_count != 0)
|
|
||||||
filament_presets.resize(n, filament_presets.back());
|
|
||||||
else {
|
|
||||||
filament_presets.resize(n);
|
|
||||||
}
|
|
||||||
ConfigOptionStrings* filament_color = project_config.option<ConfigOptionStrings>("filament_colour");
|
|
||||||
ConfigOptionStrings* filament_multi_color = project_config.option<ConfigOptionStrings>("filament_multi_colour");
|
|
||||||
ConfigOptionStrings* filament_color_type = project_config.option<ConfigOptionStrings>("filament_colour_type");
|
|
||||||
ConfigOptionInts* filament_map = project_config.option<ConfigOptionInts>("filament_map");
|
|
||||||
ConfigOptionInts* filament_nozzle_map = project_config.option<ConfigOptionInts>("filament_nozzle_map");
|
|
||||||
ConfigOptionInts* filament_volume_map = project_config.option<ConfigOptionInts>("filament_volume_map");
|
|
||||||
|
|
||||||
filament_color->resize(n);
|
|
||||||
// Sync filament multi colour
|
|
||||||
filament_multi_color->values.resize(n);
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
|
||||||
filament_multi_color->values[i] = filament_color->values[i];
|
|
||||||
}
|
|
||||||
filament_color_type->resize(n);
|
|
||||||
filament_map->values.resize(n, 1);
|
|
||||||
filament_nozzle_map->values.resize(n, 0);
|
|
||||||
filament_volume_map->values.resize(n, static_cast<int>(NozzleVolumeType::nvtStandard));
|
|
||||||
ams_multi_color_filment.resize(n);
|
|
||||||
|
|
||||||
// Mixed-color metadata is a parallel per-filament array set, so it has to grow and shrink
|
|
||||||
// with the filament count exactly like filament_colour above.
|
|
||||||
if (auto* opt = project_config.option<ConfigOptionBools>("filament_is_mixed"))
|
|
||||||
opt->values.resize(n, false);
|
|
||||||
if (auto* opt = project_config.option<ConfigOptionStrings>("filament_mixed_components"))
|
|
||||||
opt->values.resize(n, std::string{});
|
|
||||||
if (auto* opt = project_config.option<ConfigOptionStrings>("filament_mixed_sublayer_ratios"))
|
|
||||||
opt->values.resize(n, std::string{});
|
|
||||||
if (auto* opt = project_config.option<ConfigOptionBools>("filament_mixed_gradient"))
|
|
||||||
opt->values.resize(n, false);
|
|
||||||
if (auto* opt = project_config.option<ConfigOptionStrings>("filament_mixed_gradient_range"))
|
|
||||||
opt->values.resize(n, std::string{});
|
|
||||||
if (auto* opt = project_config.option<ConfigOptionStrings>("filament_mixed_gradient_curve"))
|
|
||||||
opt->values.resize(n, std::string{});
|
|
||||||
if (auto* opt = project_config.option<ConfigOptionBools>("filament_mixed_gradient_per_part"))
|
|
||||||
opt->values.resize(n, false);
|
|
||||||
|
|
||||||
// BBS set new filament color to new_color
|
|
||||||
if (old_filament_count < n) {
|
|
||||||
if (!new_colors.empty()) {
|
|
||||||
for (int i = old_filament_count; i < n; i++) {
|
|
||||||
filament_color->values[i] = new_colors[i - old_filament_count];
|
|
||||||
filament_multi_color->values[i] = new_colors[i - old_filament_count];
|
|
||||||
filament_color_type->values[i] = "1"; // default color type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
update_multi_material_filament_presets();
|
|
||||||
}
|
|
||||||
void PresetBundle::set_num_filaments(unsigned int n, std::string new_color)
|
void PresetBundle::set_num_filaments(unsigned int n, std::string new_color)
|
||||||
{
|
{
|
||||||
unsigned old_filament_count = this->filament_presets.size();
|
unsigned old_filament_count = this->filament_presets.size();
|
||||||
@@ -3384,6 +3326,11 @@ void PresetBundle::set_num_filaments(unsigned int n, std::string new_color)
|
|||||||
ConfigOptionInts* filament_nozzle_map = project_config.option<ConfigOptionInts>("filament_nozzle_map");
|
ConfigOptionInts* filament_nozzle_map = project_config.option<ConfigOptionInts>("filament_nozzle_map");
|
||||||
ConfigOptionInts* filament_volume_map = project_config.option<ConfigOptionInts>("filament_volume_map");
|
ConfigOptionInts* filament_volume_map = project_config.option<ConfigOptionInts>("filament_volume_map");
|
||||||
|
|
||||||
|
// Which slots are new is a fact about the arrays below, not about filament_presets:
|
||||||
|
// update_multi_material_filament_presets() tops that list up to the nozzle count on its own,
|
||||||
|
// so it can already sit at the new size while every array below is still at the old one.
|
||||||
|
const size_t old_slot_count = filament_color->values.size();
|
||||||
|
|
||||||
filament_color->resize(n);
|
filament_color->resize(n);
|
||||||
// Sync filament multi colour
|
// Sync filament multi colour
|
||||||
filament_multi_color->values.resize(n);
|
filament_multi_color->values.resize(n);
|
||||||
@@ -3414,13 +3361,11 @@ void PresetBundle::set_num_filaments(unsigned int n, std::string new_color)
|
|||||||
opt->values.resize(n, false);
|
opt->values.resize(n, false);
|
||||||
|
|
||||||
// BBS set new filament color to new_color
|
// BBS set new filament color to new_color
|
||||||
if (old_filament_count < n) {
|
if (!new_color.empty()) {
|
||||||
if (!new_color.empty()) {
|
for (size_t i = old_slot_count; i < n; i++) {
|
||||||
for (unsigned i = old_filament_count; i < n; i++) {
|
filament_color->values[i] = new_color;
|
||||||
filament_color->values[i] = new_color;
|
filament_multi_color->values[i] = new_color;
|
||||||
filament_multi_color->values[i] = new_color;
|
filament_color_type->values[i] = "1"; // default color type
|
||||||
filament_color_type->values[i] = "1"; // default color type
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3526,6 +3471,16 @@ size_t PresetBundle::num_mixed_filaments() const
|
|||||||
return opt == nullptr ? 0 : size_t(std::count(opt->values.begin(), opt->values.end(), true));
|
return opt == nullptr ? 0 : size_t(std::count(opt->values.begin(), opt->values.end(), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Counted off the mixed flags, not filament_presets: that list is topped up to the nozzle count on
|
||||||
|
// its own, so it can sit a slot ahead of the arrays that describe slots. Unlike the sibling
|
||||||
|
// physical_filament_config_indices(), which bounds by filament_presets, this ignores that top-up.
|
||||||
|
size_t PresetBundle::num_physical_filaments() const
|
||||||
|
{
|
||||||
|
const auto *opt = project_config.option<ConfigOptionBools>("filament_is_mixed");
|
||||||
|
return opt == nullptr ? filament_presets.size()
|
||||||
|
: size_t(std::count(opt->values.begin(), opt->values.end(), false));
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<size_t> PresetBundle::physical_filament_config_indices() const
|
std::vector<size_t> PresetBundle::physical_filament_config_indices() const
|
||||||
{
|
{
|
||||||
std::vector<size_t> indices;
|
std::vector<size_t> indices;
|
||||||
|
|||||||
@@ -346,8 +346,9 @@ public:
|
|||||||
// Export selections (current print, current filaments, current printer) into config.ini
|
// Export selections (current print, current filaments, current printer) into config.ini
|
||||||
void export_selections(AppConfig &config);
|
void export_selections(AppConfig &config);
|
||||||
|
|
||||||
// BBS
|
// n is the total slot count, and growth appends at the raw tail - which is where the mixed
|
||||||
void set_num_filaments(unsigned int n, std::vector<std::string> new_colors);
|
// slots live. A caller adding physical filaments has to add num_mixed_filaments() on top and
|
||||||
|
// then move the new slots ahead of the mixed tail, as Sidebar::add_custom_filament does.
|
||||||
void set_num_filaments(unsigned int n, std::string new_col = "");
|
void set_num_filaments(unsigned int n, std::string new_col = "");
|
||||||
void update_num_filaments(unsigned int to_del_flament_id);
|
void update_num_filaments(unsigned int to_del_flament_id);
|
||||||
|
|
||||||
@@ -523,6 +524,8 @@ public:
|
|||||||
// How many slots are mixed. They sit at the tail of the filament list and have no nozzle of
|
// How many slots are mixed. They sit at the tail of the filament list and have no nozzle of
|
||||||
// their own, so any resize driven by the printer's extruder count has to add this on top.
|
// their own, so any resize driven by the printer's extruder count has to add this on top.
|
||||||
size_t num_mixed_filaments() const;
|
size_t num_mixed_filaments() const;
|
||||||
|
// How many slots hold a real filament, i.e. everything ahead of the mixed tail.
|
||||||
|
size_t num_physical_filaments() const;
|
||||||
|
|
||||||
void on_extruders_count_changed(int extruder_count);
|
void on_extruders_count_changed(int extruder_count);
|
||||||
|
|
||||||
|
|||||||
@@ -1015,7 +1015,7 @@ wxBoxSizer* CalibrationPresetPage::create_ams_items_sizer(MachineObject* obj, wx
|
|||||||
auto ams_items_sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto ams_items_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
for (auto &info : ams_info) {
|
for (auto &info : ams_info) {
|
||||||
auto preview_ams_item = new AMSPreview(ams_preview_panel, wxID_ANY, info, info.ams_type);
|
auto preview_ams_item = new AMSPreview(ams_preview_panel, wxID_ANY, info, info.ams_type);
|
||||||
preview_ams_item->Update(info);
|
preview_ams_item->UpdateInfo(info);
|
||||||
preview_ams_item->Open();
|
preview_ams_item->Open();
|
||||||
ams_preview_list.push_back(preview_ams_item);
|
ams_preview_list.push_back(preview_ams_item);
|
||||||
std::string ams_id = preview_ams_item->get_ams_id();
|
std::string ams_id = preview_ams_item->get_ams_id();
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public:
|
|||||||
DevFirmware(MachineObject* obj) : m_owner(obj) {}
|
DevFirmware(MachineObject* obj) : m_owner(obj) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MachineObject* m_owner = nullptr;
|
[[maybe_unused]] MachineObject* m_owner = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
/* File: uiAMSBestPositionPopup.hpp
|
/* File: uiAMSBestPositionPopup.hpp
|
||||||
* Description: The popup with suggest best ams position
|
* Description: The popup with suggest best ams position
|
||||||
*
|
*
|
||||||
//**********************************************************/
|
************************************************************/
|
||||||
|
|
||||||
#include "uiAMSBestPositionPopup.hpp"
|
#include "uiAMSBestPositionPopup.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
/* File: uiAMSBestPositionPopup.hpp
|
/* File: uiAMSBestPositionPopup.hpp
|
||||||
* Description: The popup with suggest best ams position
|
* Description: The popup with suggest best ams position
|
||||||
*
|
*
|
||||||
//**********************************************************/
|
************************************************************/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "slic3r/GUI/Widgets/AMSItem.hpp"
|
#include "slic3r/GUI/Widgets/AMSItem.hpp"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* \n class wgtDeviceNozzleRackNozzleItem;
|
* \n class wgtDeviceNozzleRackNozzleItem;
|
||||||
* \n class wgtDeviceNozzleRackToolHead;
|
* \n class wgtDeviceNozzleRackToolHead;
|
||||||
* \n class wgtDeviceNozzleRackPos;
|
* \n class wgtDeviceNozzleRackPos;
|
||||||
//**********************************************************/
|
************************************************************/
|
||||||
|
|
||||||
#include "wgtDeviceNozzleRack.h"
|
#include "wgtDeviceNozzleRack.h"
|
||||||
#include "wgtDeviceNozzleRackUpdate.h"
|
#include "wgtDeviceNozzleRackUpdate.h"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* \n class wgtDeviceNozzleRackNozzleItem;
|
* \n class wgtDeviceNozzleRackNozzleItem;
|
||||||
* \n class wgtDeviceNozzleRackToolHead;
|
* \n class wgtDeviceNozzleRackToolHead;
|
||||||
* \n class wgtDeviceNozzleRackPos;
|
* \n class wgtDeviceNozzleRackPos;
|
||||||
//**********************************************************/
|
************************************************************/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "slic3r/GUI/DeviceCore/DevNozzleRack.h"
|
#include "slic3r/GUI/DeviceCore/DevNozzleRack.h"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Description: The panel with rack updating
|
* Description: The panel with rack updating
|
||||||
*
|
*
|
||||||
* \n class wgtDeviceNozzleRackUpdate
|
* \n class wgtDeviceNozzleRackUpdate
|
||||||
//**********************************************************/
|
************************************************************/
|
||||||
|
|
||||||
#include "wgtDeviceNozzleRackUpdate.h"
|
#include "wgtDeviceNozzleRackUpdate.h"
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Description: The panel for updating hotends
|
* Description: The panel for updating hotends
|
||||||
*
|
*
|
||||||
* \n class wgtDeviceNozzleRackUpdate
|
* \n class wgtDeviceNozzleRackUpdate
|
||||||
//**********************************************************/
|
************************************************************/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "slic3r/GUI/DeviceCore/DevNozzleRack.h"
|
#include "slic3r/GUI/DeviceCore/DevNozzleRack.h"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Description: The panel to select nozzle
|
* Description: The panel to select nozzle
|
||||||
*
|
*
|
||||||
* \n class wgtDeviceNozzleSelect;
|
* \n class wgtDeviceNozzleSelect;
|
||||||
//**********************************************************/
|
************************************************************/
|
||||||
|
|
||||||
#include "wgtDeviceNozzleSelect.h"
|
#include "wgtDeviceNozzleSelect.h"
|
||||||
#include "wgtDeviceNozzleRack.h"
|
#include "wgtDeviceNozzleRack.h"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Description: The panel to select nozzle
|
* Description: The panel to select nozzle
|
||||||
*
|
*
|
||||||
* \n class wgtDeviceNozzleSelect;
|
* \n class wgtDeviceNozzleSelect;
|
||||||
//**********************************************************/
|
************************************************************/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|||||||
@@ -8906,10 +8906,16 @@ void GUI_App::load_current_presets(bool active_preset_combox/*= false*/, bool ch
|
|||||||
auto* nozzle_diameter = edited_printer_preset.config.option<ConfigOptionFloats>("nozzle_diameter");
|
auto* nozzle_diameter = edited_printer_preset.config.option<ConfigOptionFloats>("nozzle_diameter");
|
||||||
if (nozzle_diameter) {
|
if (nozzle_diameter) {
|
||||||
// Mixed-color slots are virtual filaments kept at the tail of the list, so they have no
|
// Mixed-color slots are virtual filaments kept at the tail of the list, so they have no
|
||||||
// nozzle of their own. Sizing to the nozzle count alone would silently drop the mixes of
|
// nozzle of their own and the count has to allow for them. Only ever grow: this sizes
|
||||||
// a just-loaded project, and update_extruder_count() would then strip the facets painted
|
// the list so the combo boxes have something to bind to, and set_num_filaments() trims
|
||||||
// with them.
|
// at the raw tail, so shrinking here would eat the mixes rather than the surplus
|
||||||
preset_bundle->set_num_filaments(nozzle_diameter->values.size() + preset_bundle->num_mixed_filaments());
|
// physical slots. A list longer than the nozzle count is a state the app reaches
|
||||||
|
// legitimately - raising the extruder count and not saving the printer preset leaves
|
||||||
|
// exactly that on the next start - and losing the project's mixes to it is worse than
|
||||||
|
// carrying a filament the printer has no nozzle for until the count is next changed.
|
||||||
|
const size_t target = nozzle_diameter->values.size() + preset_bundle->num_mixed_filaments();
|
||||||
|
if (target > preset_bundle->filament_presets.size())
|
||||||
|
preset_bundle->set_num_filaments(target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->plater()->set_printer_technology(printer_technology);
|
this->plater()->set_printer_technology(printer_technology);
|
||||||
|
|||||||
@@ -155,6 +155,9 @@ public:
|
|||||||
update_dark_config();
|
update_dark_config();
|
||||||
on_sys_color_changed();
|
on_sys_color_changed();
|
||||||
event.Skip();
|
event.Skip();
|
||||||
|
#else
|
||||||
|
// Not calling Skip() is what stops the event propagating on Windows.
|
||||||
|
(void) this;
|
||||||
#endif // __WINDOWS__
|
#endif // __WINDOWS__
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1464,12 +1464,12 @@ void ExtruderGroup::update_ams()
|
|||||||
size_t left = 4;
|
size_t left = 4;
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (size_t i = i4; i < ams_n4 && left > 0; ++i, ++index, left -= 2) {
|
for (size_t i = i4; i < ams_n4 && left > 0; ++i, ++index, left -= 2) {
|
||||||
ams[index]->Update(i < ams_4.size() ? ams_4[i] : info4);
|
ams[index]->UpdateInfo(i < ams_4.size() ? ams_4[i] : info4);
|
||||||
ams[index]->Refresh();
|
ams[index]->Refresh();
|
||||||
ams[index]->Open();
|
ams[index]->Open();
|
||||||
}
|
}
|
||||||
for (size_t i = i1; i < ams_n1 && left > 0; ++i, ++index, --left) {
|
for (size_t i = i1; i < ams_n1 && left > 0; ++i, ++index, --left) {
|
||||||
ams[index]->Update(i < ams_1.size() ? ams_1[i] : info1);
|
ams[index]->UpdateInfo(i < ams_1.size() ? ams_1[i] : info1);
|
||||||
ams[index]->Refresh();
|
ams[index]->Refresh();
|
||||||
ams[index]->Open();
|
ams[index]->Open();
|
||||||
}
|
}
|
||||||
@@ -5593,12 +5593,15 @@ void Sidebar::add_custom_filament(wxColour new_col, const std::string& preset_na
|
|||||||
|
|
||||||
// Mixed-color slots are kept at the tail of the filament arrays, so a new physical
|
// Mixed-color slots are kept at the tail of the filament arrays, so a new physical
|
||||||
// filament has to be inserted just after the last physical one rather than appended.
|
// filament has to be inserted just after the last physical one rather than appended.
|
||||||
// total == every slot (physical + mixed); insert_pos == the physical slot count.
|
// Count off filament_is_mixed, not filament_presets or the combos: the extruder-count spinner
|
||||||
size_t total = wxGetApp().preset_bundle->filament_presets.size();
|
// reaches this before the sidebar has rebuilt, and update_multi_material_filament_presets()
|
||||||
size_t insert_pos = p->combos_filament.size();
|
// can have grown filament_presets alone.
|
||||||
int filament_count = (int) (total + 1);
|
auto *bundle = wxGetApp().preset_bundle;
|
||||||
std::string new_color = new_col.GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
|
size_t insert_pos = bundle->num_physical_filaments();
|
||||||
wxGetApp().preset_bundle->set_num_filaments(filament_count, new_color);
|
size_t total = insert_pos + bundle->num_mixed_filaments();
|
||||||
|
int filament_count = (int)(total + 1);
|
||||||
|
std::string new_color = new_col.GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
|
||||||
|
bundle->set_num_filaments(filament_count, new_color);
|
||||||
|
|
||||||
// Maintain physical-first ordering: rotate the new slot from end to insert_pos.
|
// Maintain physical-first ordering: rotate the new slot from end to insert_pos.
|
||||||
// No mixed slots -> insert_pos == total -> every rotate below is a no-op.
|
// No mixed slots -> insert_pos == total -> every rotate below is a no-op.
|
||||||
|
|||||||
@@ -2847,7 +2847,7 @@ void SelectMachineDialog::on_ok_btn(wxCommandEvent &event)
|
|||||||
});
|
});
|
||||||
|
|
||||||
// STUDIO-9580
|
// STUDIO-9580
|
||||||
/* use warning color if there are warning and normal messages* /
|
/* use warning color if there are warning and normal messages*/
|
||||||
/* use indexes if there are several messages*/
|
/* use indexes if there are several messages*/
|
||||||
/* add header and ending if there are several messages or has none block warnings*/
|
/* add header and ending if there are several messages or has none block warnings*/
|
||||||
if (confirm_text.size() > 1 || !is_printing_block)
|
if (confirm_text.size() > 1 || !is_printing_block)
|
||||||
|
|||||||
+18
-14
@@ -2174,21 +2174,25 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
|||||||
|
|
||||||
//Orca: sync filament num if it's a multi tool printer
|
//Orca: sync filament num if it's a multi tool printer
|
||||||
if (opt_key == "extruders_count" && !m_config->opt_bool("single_extruder_multi_material")){
|
if (opt_key == "extruders_count" && !m_config->opt_bool("single_extruder_multi_material")){
|
||||||
auto num_extruder = boost::any_cast<size_t>(value);
|
const size_t num_extruder = boost::any_cast<size_t>(value);
|
||||||
int old_filament_size = wxGetApp().preset_bundle->filament_presets.size();
|
auto *bundle = wxGetApp().preset_bundle;
|
||||||
std::vector<std::string> new_colors;
|
Sidebar &sidebar = wxGetApp().plater()->sidebar();
|
||||||
for (int i = old_filament_size; i < num_extruder; ++i) {
|
// A tool changer feeds filament N from nozzle N, so the extruder count sizes the physical
|
||||||
wxColour new_col = Plater::get_next_color_for_filament();
|
// run only; mixed slots are virtual and keep the tail. Go one slot at a time through the
|
||||||
std::string new_color = new_col.GetAsString(wxC2S_HTML_SYNTAX).ToStdString();
|
// sidebar's own +/- calls: they insert ahead of the mixed tail and renumber filament ids,
|
||||||
new_colors.push_back(new_color);
|
// painted facets, custom g-code and mixed components, which a bulk resize clamps away.
|
||||||
|
// Both also refresh the print tab and export the selections, so nothing to do afterwards.
|
||||||
|
size_t physical = bundle->num_physical_filaments();
|
||||||
|
while (physical != num_extruder) {
|
||||||
|
if (physical < num_extruder)
|
||||||
|
sidebar.add_custom_filament(Plater::get_next_color_for_filament());
|
||||||
|
else
|
||||||
|
sidebar.delete_filament(physical - 1); // physical > num_extruder >= 1
|
||||||
|
const size_t updated = bundle->num_physical_filaments();
|
||||||
|
if (updated == physical)
|
||||||
|
break; // the call declined, e.g. the total slot limit - do not spin
|
||||||
|
physical = updated;
|
||||||
}
|
}
|
||||||
// Mixed-color slots are virtual filaments at the tail of the list with no nozzle of their
|
|
||||||
// own, so they are carried on top of the new extruder count instead of being truncated.
|
|
||||||
const size_t total_filaments = num_extruder + wxGetApp().preset_bundle->num_mixed_filaments();
|
|
||||||
wxGetApp().preset_bundle->set_num_filaments(total_filaments, new_colors);
|
|
||||||
wxGetApp().plater()->on_filament_count_change(total_filaments);
|
|
||||||
wxGetApp().get_tab(Preset::TYPE_PRINT)->update();
|
|
||||||
wxGetApp().preset_bundle->export_selections(*wxGetApp().app_config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Orca: disable purge_in_prime_tower if single_extruder_multi_material is disabled
|
//Orca: disable purge_in_prime_tower if single_extruder_multi_material is disabled
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ public:
|
|||||||
TabButton* pageButton;
|
TabButton* pageButton;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxWindow* m_parent;
|
|
||||||
wxFlexGridSizer* m_buttons_sizer;
|
wxFlexGridSizer* m_buttons_sizer;
|
||||||
wxBoxSizer* m_sizer;
|
wxBoxSizer* m_sizer;
|
||||||
ScalableBitmap m_arrow_img;
|
ScalableBitmap m_arrow_img;
|
||||||
@@ -400,8 +399,6 @@ private:
|
|||||||
unsigned m_showTimeout,
|
unsigned m_showTimeout,
|
||||||
m_hideTimeout;
|
m_hideTimeout;
|
||||||
|
|
||||||
TabButtonsListCtrl *m_ctrl{nullptr};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
//#endif // _WIN32
|
//#endif // _WIN32
|
||||||
#endif // slic3r_Tabbook_hpp_
|
#endif // slic3r_Tabbook_hpp_
|
||||||
|
|||||||
@@ -984,7 +984,7 @@ void AMSControl::UpdateAms(const std::string &series_name,
|
|||||||
if (cans->get_ams_id() == std::to_string(VIRTUAL_TRAY_MAIN_ID) || cans->get_ams_id() == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) {
|
if (cans->get_ams_id() == std::to_string(VIRTUAL_TRAY_MAIN_ID) || cans->get_ams_id() == std::to_string(VIRTUAL_TRAY_DEPUTY_ID)) {
|
||||||
for (auto ifo : m_ext_info) {
|
for (auto ifo : m_ext_info) {
|
||||||
if (ifo.ams_id == ams_id) {
|
if (ifo.ams_id == ams_id) {
|
||||||
cans->Update(ifo);
|
cans->UpdateInfo(ifo);
|
||||||
cans->show_sn_value(m_ams_model == AMSModel::AMS_LITE ? false : true);
|
cans->show_sn_value(m_ams_model == AMSModel::AMS_LITE ? false : true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -992,7 +992,7 @@ void AMSControl::UpdateAms(const std::string &series_name,
|
|||||||
else{
|
else{
|
||||||
for (auto ifo : m_ams_info) {
|
for (auto ifo : m_ams_info) {
|
||||||
if (ifo.ams_id == ams_id) {
|
if (ifo.ams_id == ams_id) {
|
||||||
cans->Update(ifo);
|
cans->UpdateInfo(ifo);
|
||||||
cans->show_sn_value(m_ams_model == AMSModel::AMS_LITE ? false : true);
|
cans->show_sn_value(m_ams_model == AMSModel::AMS_LITE ? false : true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1015,7 +1015,7 @@ void AMSControl::UpdateAms(const std::string &series_name,
|
|||||||
std::string id = ams_prv.second->get_ams_id();
|
std::string id = ams_prv.second->get_ams_id();
|
||||||
auto item = m_ams_item_list.find(id);
|
auto item = m_ams_item_list.find(id);
|
||||||
if (item != m_ams_item_list.end())
|
if (item != m_ams_item_list.end())
|
||||||
{ ams_prv.second->Update(item->second->get_ams_info());
|
{ ams_prv.second->UpdateInfo(item->second->get_ams_info());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ AMSrefresh::AMSrefresh(wxWindow *parent, std::string ams_id, wxString can_id, Ca
|
|||||||
m_can_id = can_id.ToStdString();
|
m_can_id = can_id.ToStdString();
|
||||||
create(parent, wxID_ANY, pos, size);
|
create(parent, wxID_ANY, pos, size);
|
||||||
|
|
||||||
Update(ams_id, info);
|
UpdateInfo(ams_id, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
AMSrefresh::AMSrefresh(wxWindow *parent, std::string ams_id, int can_id, Caninfo info, const wxPoint &pos, const wxSize &size) : AMSrefresh()
|
AMSrefresh::AMSrefresh(wxWindow *parent, std::string ams_id, int can_id, Caninfo info, const wxPoint &pos, const wxSize &size) : AMSrefresh()
|
||||||
@@ -333,7 +333,7 @@ AMSrefresh::AMSrefresh(wxWindow *parent, std::string ams_id, int can_id, Caninfo
|
|||||||
m_can_id = wxString::Format("%d", can_id).ToStdString();
|
m_can_id = wxString::Format("%d", can_id).ToStdString();
|
||||||
create(parent, wxID_ANY, pos, size);
|
create(parent, wxID_ANY, pos, size);
|
||||||
|
|
||||||
Update(ams_id, info);
|
UpdateInfo(ams_id, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
AMSrefresh::~AMSrefresh()
|
AMSrefresh::~AMSrefresh()
|
||||||
@@ -482,7 +482,7 @@ void AMSrefresh::paintEvent(wxPaintEvent &evt)
|
|||||||
dc.DrawText(m_refresh_id, pot);
|
dc.DrawText(m_refresh_id, pot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMSrefresh::Update(std::string ams_id, Caninfo info)
|
void AMSrefresh::UpdateInfo(std::string ams_id, Caninfo info)
|
||||||
{
|
{
|
||||||
if (m_ams_id == ams_id && m_info == info)
|
if (m_ams_id == ams_id && m_info == info)
|
||||||
{
|
{
|
||||||
@@ -945,7 +945,7 @@ AMSLib::AMSLib(wxWindow *parent, std::string ams_idx, Caninfo info, AMSModelOrig
|
|||||||
Bind(wxEVT_LEAVE_WINDOW, &AMSLib::on_leave_window, this);
|
Bind(wxEVT_LEAVE_WINDOW, &AMSLib::on_leave_window, this);
|
||||||
Bind(wxEVT_LEFT_DOWN, &AMSLib::on_left_down, this);
|
Bind(wxEVT_LEFT_DOWN, &AMSLib::on_left_down, this);
|
||||||
|
|
||||||
Update(info, ams_idx, false);
|
UpdateInfo(info, ams_idx, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AMSLib::~AMSLib()
|
AMSLib::~AMSLib()
|
||||||
@@ -1730,7 +1730,7 @@ void AMSLib::on_pass_road(bool pass)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMSLib::Update(Caninfo info, std::string ams_idx, bool refresh)
|
void AMSLib::UpdateInfo(Caninfo info, std::string ams_idx, bool refresh)
|
||||||
{
|
{
|
||||||
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
DeviceManager* dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||||
if (!dev) return;
|
if (!dev) return;
|
||||||
@@ -1868,7 +1868,7 @@ AMSRoad::AMSRoad(wxWindow *parent, wxWindowID id, Caninfo info, int canindex, in
|
|||||||
|
|
||||||
void AMSRoad::create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size) { wxWindow::Create(parent, id, pos, size); }
|
void AMSRoad::create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size) { wxWindow::Create(parent, id, pos, size); }
|
||||||
|
|
||||||
void AMSRoad::Update(AMSinfo amsinfo, Caninfo info, int canindex, int maxcan)
|
void AMSRoad::UpdateInfo(AMSinfo amsinfo, Caninfo info, int canindex, int maxcan)
|
||||||
{
|
{
|
||||||
m_amsinfo = amsinfo;
|
m_amsinfo = amsinfo;
|
||||||
m_info = info;
|
m_info = info;
|
||||||
@@ -2083,9 +2083,6 @@ void AMSRoad::OnPassRoad(std::vector<AMSPassRoadMode> prord_list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
Description:AMSRoadUpPart
|
Description:AMSRoadUpPart
|
||||||
**************************************************/
|
**************************************************/
|
||||||
@@ -2124,7 +2121,7 @@ void AMSRoadUpPart::create(wxWindow* parent, wxWindowID id, const wxPoint& pos,
|
|||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMSRoadUpPart::Update(AMSinfo amsinfo)
|
void AMSRoadUpPart::UpdateInfo(AMSinfo amsinfo)
|
||||||
{
|
{
|
||||||
if (m_amsinfo != amsinfo)
|
if (m_amsinfo != amsinfo)
|
||||||
{
|
{
|
||||||
@@ -2616,7 +2613,7 @@ void AMSPreview::Close()
|
|||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMSPreview::Update(AMSinfo amsinfo)
|
void AMSPreview::UpdateInfo(AMSinfo amsinfo)
|
||||||
{
|
{
|
||||||
if (m_amsinfo == amsinfo)
|
if (m_amsinfo == amsinfo)
|
||||||
{
|
{
|
||||||
@@ -2954,7 +2951,7 @@ AMSHumidity::AMSHumidity(wxWindow* parent, wxWindowID id, AMSinfo info, const wx
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Update(info);
|
UpdateInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AMSHumidity::create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size) {
|
void AMSHumidity::create(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size) {
|
||||||
@@ -2963,7 +2960,7 @@ void AMSHumidity::create(wxWindow* parent, wxWindowID id, const wxPoint& pos, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AMSHumidity::Update(AMSinfo amsinfo)
|
void AMSHumidity::UpdateInfo(AMSinfo amsinfo)
|
||||||
{
|
{
|
||||||
if (m_amsinfo != amsinfo)
|
if (m_amsinfo != amsinfo)
|
||||||
{
|
{
|
||||||
@@ -3380,7 +3377,7 @@ void AmsItem::AddLiteCan(Caninfo caninfo, int canindex, wxGridSizer* sizer)
|
|||||||
//m_can_road_list[caninfo.can_id] = m_panel_road;
|
//m_can_road_list[caninfo.can_id] = m_panel_road;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsItem::Update(AMSinfo info)
|
void AmsItem::UpdateInfo(AMSinfo info)
|
||||||
{
|
{
|
||||||
if (m_info == info)
|
if (m_info == info)
|
||||||
{
|
{
|
||||||
@@ -3392,7 +3389,7 @@ void AmsItem::Update(AMSinfo info)
|
|||||||
|
|
||||||
if (m_humidity)
|
if (m_humidity)
|
||||||
{
|
{
|
||||||
m_humidity->Update(m_info);
|
m_humidity->UpdateInfo(m_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < m_can_count; i++) {
|
for (int i = 0; i < m_can_count; i++) {
|
||||||
@@ -3401,7 +3398,7 @@ void AmsItem::Update(AMSinfo info)
|
|||||||
|
|
||||||
auto refresh = it->second;
|
auto refresh = it->second;
|
||||||
if (refresh != nullptr){
|
if (refresh != nullptr){
|
||||||
refresh->Update(info.ams_id, info.cans[i]);
|
refresh->UpdateInfo(info.ams_id, info.cans[i]);
|
||||||
refresh->Show();
|
refresh->Show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3410,7 +3407,7 @@ void AmsItem::Update(AMSinfo info)
|
|||||||
AMSLib* lib = m_can_lib_list[std::to_string(i)];
|
AMSLib* lib = m_can_lib_list[std::to_string(i)];
|
||||||
if (lib != nullptr){
|
if (lib != nullptr){
|
||||||
if (i < m_can_count){
|
if (i < m_can_count){
|
||||||
lib->Update(info.cans[i], info.ams_id);
|
lib->UpdateInfo(info.cans[i], info.ams_id);
|
||||||
lib->Show();
|
lib->Show();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -3419,12 +3416,7 @@ void AmsItem::Update(AMSinfo info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_panel_road != nullptr){
|
if (m_panel_road != nullptr){
|
||||||
m_panel_road->Update(m_info);
|
m_panel_road->UpdateInfo(m_info);
|
||||||
}
|
|
||||||
|
|
||||||
if (true || m_ams_model == AMSModel::GENERIC_AMS) {
|
|
||||||
/*m_panel_road->Update(m_info, info.cans[0]);
|
|
||||||
m_panel_road->Show();*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ public:
|
|||||||
~AMSrefresh();
|
~AMSrefresh();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Update(std::string ams_id, Caninfo info);
|
void UpdateInfo(std::string ams_id, Caninfo info);
|
||||||
|
|
||||||
std::string GetCanId() const { return m_info.can_id; };
|
std::string GetCanId() const { return m_info.can_id; };
|
||||||
|
|
||||||
@@ -492,7 +492,7 @@ public:
|
|||||||
AMSModel m_ams_model;
|
AMSModel m_ams_model;
|
||||||
AMSModelOriginType m_ext_type = { AMSModelOriginType::GENERIC_EXT };
|
AMSModelOriginType m_ext_type = { AMSModelOriginType::GENERIC_EXT };
|
||||||
|
|
||||||
void Update(Caninfo info, std::string ams_idx, bool refresh = true);
|
void UpdateInfo(Caninfo info, std::string ams_idx, bool refresh = true);
|
||||||
void UnableSelected() { m_unable_selected = true; };
|
void UnableSelected() { m_unable_selected = true; };
|
||||||
void EableSelected() { m_unable_selected = false; };
|
void EableSelected() { m_unable_selected = false; };
|
||||||
void OnSelected();
|
void OnSelected();
|
||||||
@@ -581,7 +581,7 @@ public:
|
|||||||
double m_radius = {4};
|
double m_radius = {4};
|
||||||
wxColour m_road_def_color;
|
wxColour m_road_def_color;
|
||||||
wxColour m_road_color;
|
wxColour m_road_color;
|
||||||
void Update(AMSinfo amsinfo, Caninfo info, int canindex, int maxcan);
|
void UpdateInfo(AMSinfo amsinfo, Caninfo info, int canindex, int maxcan);
|
||||||
|
|
||||||
std::vector<ScalableBitmap> ams_humidity_img;
|
std::vector<ScalableBitmap> ams_humidity_img;
|
||||||
|
|
||||||
@@ -614,7 +614,7 @@ public:
|
|||||||
void create(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
|
void create(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Update(AMSinfo amsinfo);
|
void UpdateInfo(AMSinfo amsinfo);
|
||||||
|
|
||||||
void OnVamsLoading(bool load, wxColour col = AMS_CONTROL_GRAY500);
|
void OnVamsLoading(bool load, wxColour col = AMS_CONTROL_GRAY500);
|
||||||
void SetPassRoadColour(wxColour col);
|
void SetPassRoadColour(wxColour col);
|
||||||
@@ -715,7 +715,7 @@ public:
|
|||||||
void Open();
|
void Open();
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
void Update(AMSinfo amsinfo);
|
void UpdateInfo(AMSinfo amsinfo);
|
||||||
void create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size);
|
void create(wxWindow *parent, wxWindowID id, const wxPoint &pos, const wxSize &size);
|
||||||
void OnEnterWindow(wxMouseEvent &evt);
|
void OnEnterWindow(wxMouseEvent &evt);
|
||||||
void OnLeaveWindow(wxMouseEvent &evt);
|
void OnLeaveWindow(wxMouseEvent &evt);
|
||||||
@@ -768,7 +768,7 @@ public:
|
|||||||
int m_canindex = { 0 };
|
int m_canindex = { 0 };
|
||||||
bool m_selected = { false };
|
bool m_selected = { false };
|
||||||
double m_radius = { 12 };
|
double m_radius = { 12 };
|
||||||
void Update(AMSinfo amsinfo);
|
void UpdateInfo(AMSinfo amsinfo);
|
||||||
|
|
||||||
std::vector<ScalableBitmap> ams_humidity_imgs;
|
std::vector<ScalableBitmap> ams_humidity_imgs;
|
||||||
std::vector<ScalableBitmap> ams_humidity_dark_imgs;
|
std::vector<ScalableBitmap> ams_humidity_dark_imgs;
|
||||||
@@ -801,7 +801,7 @@ public:
|
|||||||
AmsItem(wxWindow *parent, AMSinfo info, AMSModel model, AMSPanelPos pos);
|
AmsItem(wxWindow *parent, AMSinfo info, AMSModel model, AMSPanelPos pos);
|
||||||
~AmsItem();
|
~AmsItem();
|
||||||
|
|
||||||
void Update(AMSinfo info);
|
void UpdateInfo(AMSinfo info);
|
||||||
void create(wxWindow *parent);
|
void create(wxWindow *parent);
|
||||||
void AddCan(Caninfo caninfo, int canindex, int maxcan, wxBoxSizer* sizer);
|
void AddCan(Caninfo caninfo, int canindex, int maxcan, wxBoxSizer* sizer);
|
||||||
void AddLiteCan(Caninfo caninfo, int canindex, wxGridSizer* sizer);
|
void AddLiteCan(Caninfo caninfo, int canindex, wxGridSizer* sizer);
|
||||||
|
|||||||
@@ -110,17 +110,6 @@ void ScrolledWindow::SetTipColor(wxColour color)
|
|||||||
if (m_bottomScrollbar) m_bottomScrollbar->SetTipColor(color);
|
if (m_bottomScrollbar) m_bottomScrollbar->SetTipColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScrolledWindow::Refresh()
|
|
||||||
{
|
|
||||||
// m_rightScrollbar->SetViewStart(0);
|
|
||||||
// m_rightScrollbar->Refresh();
|
|
||||||
// m_rightScrollbar->Update();
|
|
||||||
// m_userPanel->Refresh();
|
|
||||||
// m_bottomScrollbar->SetViewStart(0);
|
|
||||||
// m_rightScrollbar->Refresh();
|
|
||||||
// m_bottomScrollbar->Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScrolledWindow::SetBackgroundColour(wxColour color)
|
void ScrolledWindow::SetBackgroundColour(wxColour color)
|
||||||
{
|
{
|
||||||
wxWindow::SetBackgroundColour(color);
|
wxWindow::SetBackgroundColour(color);
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ public:
|
|||||||
ScrolledWindow(wxWindow *parent, wxWindowID id, wxPoint position, wxSize size, long style, int marginWidth = 0, int scrollbarWidth = 4, int tipLength = 0);
|
ScrolledWindow(wxWindow *parent, wxWindowID id, wxPoint position, wxSize size, long style, int marginWidth = 0, int scrollbarWidth = 4, int tipLength = 0);
|
||||||
void OnMouseWheel(wxMouseEvent &event);
|
void OnMouseWheel(wxMouseEvent &event);
|
||||||
void SetTipColor(wxColour color);
|
void SetTipColor(wxColour color);
|
||||||
void Refresh();
|
|
||||||
void SetBackgroundColour(wxColour color);
|
void SetBackgroundColour(wxColour color);
|
||||||
|
|
||||||
void SetMarginColor(wxColour color);
|
void SetMarginColor(wxColour color);
|
||||||
|
|||||||
@@ -736,6 +736,7 @@ TEST_CASE("Sizing the filament list to a multi-tool nozzle count keeps mixed slo
|
|||||||
CHECK(bundle.num_mixed_filaments() == 0);
|
CHECK(bundle.num_mixed_filaments() == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A "published" 3MF keeps the user's currently-selected presets and overlays only the
|
// A "published" 3MF keeps the user's currently-selected presets and overlays only the
|
||||||
// author-selected process keys onto the edited preset (mirrors the GUI load path: normalize
|
// author-selected process keys onto the edited preset (mirrors the GUI load path: normalize
|
||||||
// before load_config_model, then the overlay in load_config_file_config).
|
// before load_config_model, then the overlay in load_config_file_config).
|
||||||
@@ -2794,3 +2795,188 @@ TEST_CASE("Published 3MF overrides each extruder slot on a similar multi-extrude
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The nozzle-count top-up in update_multi_material_filament_presets() grows filament_presets on
|
||||||
|
// its own, so a physical count derived from that list reports a slot no per-filament array has
|
||||||
|
// yet. That is what made the extruder-count handler conclude there was nothing to add and leave
|
||||||
|
// the new sidebar combo with no colour to draw.
|
||||||
|
TEST_CASE("The physical filament count is not fooled by a lone filament_presets top-up", "[Preset][Bundle][FilamentMixer]")
|
||||||
|
{
|
||||||
|
PresetBundle bundle;
|
||||||
|
|
||||||
|
SECTION("no mixed slots") {
|
||||||
|
bundle.set_num_filaments(4u, std::string("#FF0000"));
|
||||||
|
bundle.printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter", true)->values =
|
||||||
|
{ 0.4, 0.4, 0.4, 0.4, 0.4 };
|
||||||
|
bundle.update_multi_material_filament_presets();
|
||||||
|
|
||||||
|
REQUIRE(bundle.filament_presets.size() == 5); // the top-up moved this list on its own
|
||||||
|
REQUIRE(bundle.project_config.option<ConfigOptionStrings>("filament_colour")->values.size() == 4);
|
||||||
|
CHECK(bundle.num_physical_filaments() == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("behind a mixed tail") {
|
||||||
|
bundle.set_num_filaments(5u, std::string("#FF0000"));
|
||||||
|
bundle.project_config.option<ConfigOptionBools>("filament_is_mixed")->values =
|
||||||
|
{ false, false, false, false, true };
|
||||||
|
bundle.printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter", true)->values =
|
||||||
|
{ 0.4, 0.4, 0.4, 0.4, 0.4, 0.4 };
|
||||||
|
bundle.update_multi_material_filament_presets();
|
||||||
|
|
||||||
|
REQUIRE(bundle.filament_presets.size() == 6);
|
||||||
|
REQUIRE(bundle.project_config.option<ConfigOptionStrings>("filament_colour")->values.size() == 5);
|
||||||
|
CHECK(bundle.num_physical_filaments() == 4);
|
||||||
|
CHECK(bundle.num_mixed_filaments() == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Which slots are new is a fact about the per-filament arrays, not about filament_presets, for the
|
||||||
|
// same reason. Keyed off the wrong one, a freshly opened slot silently keeps filament 1's colour.
|
||||||
|
TEST_CASE("New filament colours are placed by array position", "[Preset][Bundle][FilamentMixer]")
|
||||||
|
{
|
||||||
|
PresetBundle bundle;
|
||||||
|
bundle.set_num_filaments(4u, std::string("#FF0000"));
|
||||||
|
bundle.printers.get_edited_preset().config.option<ConfigOptionFloats>("nozzle_diameter", true)->values =
|
||||||
|
{ 0.4, 0.4, 0.4, 0.4, 0.4 };
|
||||||
|
bundle.update_multi_material_filament_presets();
|
||||||
|
REQUIRE(bundle.filament_presets.size() == 5);
|
||||||
|
REQUIRE(bundle.project_config.option<ConfigOptionStrings>("filament_colour")->values.size() == 4);
|
||||||
|
|
||||||
|
// The call Sidebar::add_custom_filament makes once the extruder count opens a slot.
|
||||||
|
bundle.set_num_filaments(5u, std::string("#00FF00"));
|
||||||
|
|
||||||
|
const auto &colours = bundle.project_config.option<ConfigOptionStrings>("filament_colour")->values;
|
||||||
|
REQUIRE(colours.size() == 5);
|
||||||
|
CHECK(colours[4] == "#00FF00"); // not colours[0], which resize() would have padded with
|
||||||
|
}
|
||||||
|
|
||||||
|
// The mixed-slot flags are written into the app config on exit and read back on the next start.
|
||||||
|
// If the read side loses them the slots survive as filaments but stop being mixes, so the project
|
||||||
|
// comes back with the mix showing as an ordinary physical filament.
|
||||||
|
TEST_CASE("A saved mix is still a mix after an app restart", "[Preset][Bundle][FilamentMixer]")
|
||||||
|
{
|
||||||
|
AppConfig app_config;
|
||||||
|
|
||||||
|
// Last session: a 4-tool project carrying one mix of filaments 2 and 3 at the tail.
|
||||||
|
{
|
||||||
|
PresetBundle bundle;
|
||||||
|
add_inmemory_preset(bundle.printers, "Test Printer");
|
||||||
|
bundle.printers.select_preset_by_name("Test Printer", true);
|
||||||
|
add_inmemory_preset(bundle.filaments, "Test Filament");
|
||||||
|
bundle.filaments.select_preset_by_name("Test Filament", true);
|
||||||
|
bundle.set_num_filaments(5u, std::string("#FF0000"));
|
||||||
|
bundle.filament_presets.assign(5, "Test Filament");
|
||||||
|
bundle.project_config.option<ConfigOptionBools>("filament_is_mixed")->values =
|
||||||
|
{ false, false, false, false, true };
|
||||||
|
bundle.project_config.option<ConfigOptionStrings>("filament_mixed_components")->values =
|
||||||
|
{ "", "", "", "", "2,3" };
|
||||||
|
bundle.export_selections(app_config);
|
||||||
|
|
||||||
|
REQUIRE(app_config.get_printer_setting("Test Printer", "filament_is_mixed") == "0,0,0,0,1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// This session.
|
||||||
|
PresetBundle bundle;
|
||||||
|
add_inmemory_preset(bundle.printers, "Test Printer");
|
||||||
|
add_inmemory_preset(bundle.filaments, "Test Filament");
|
||||||
|
bundle.load_selections(app_config);
|
||||||
|
|
||||||
|
CHECK(bundle.filament_presets.size() == 5);
|
||||||
|
CHECK(bundle.num_mixed_filaments() == 1);
|
||||||
|
CHECK(bundle.is_mixed_filament(4));
|
||||||
|
CHECK(bundle.project_config.option<ConfigOptionStrings>("filament_mixed_components")->values[4] == "2,3");
|
||||||
|
}
|
||||||
|
|
||||||
|
// The same restart, on the printer shape that actually shows the bug: a 4-tool changer whose
|
||||||
|
// saved filament list is one longer than its nozzle count, because the extra slot is the mix.
|
||||||
|
TEST_CASE("A saved mix survives a restart on a multi-tool printer", "[Preset][Bundle][FilamentMixer]")
|
||||||
|
{
|
||||||
|
auto make_toolchanger = [](PresetBundle &bundle) -> Preset & {
|
||||||
|
Preset &p = add_inmemory_preset(bundle.printers, "Tool Changer");
|
||||||
|
p.config.option<ConfigOptionFloats>("nozzle_diameter", true)->values = { 0.4, 0.4, 0.4, 0.4 };
|
||||||
|
p.config.option<ConfigOptionBool>("single_extruder_multi_material", true)->value = false;
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
|
AppConfig app_config;
|
||||||
|
{
|
||||||
|
PresetBundle bundle;
|
||||||
|
make_toolchanger(bundle);
|
||||||
|
bundle.printers.select_preset_by_name("Tool Changer", true);
|
||||||
|
add_inmemory_preset(bundle.filaments, "Test Filament");
|
||||||
|
bundle.filaments.select_preset_by_name("Test Filament", true);
|
||||||
|
bundle.set_num_filaments(5u, std::string("#FF0000"));
|
||||||
|
bundle.filament_presets.assign(5, "Test Filament");
|
||||||
|
bundle.project_config.option<ConfigOptionBools>("filament_is_mixed")->values =
|
||||||
|
{ false, false, false, false, true };
|
||||||
|
bundle.project_config.option<ConfigOptionStrings>("filament_mixed_components")->values =
|
||||||
|
{ "", "", "", "", "1,2" };
|
||||||
|
bundle.export_selections(app_config);
|
||||||
|
REQUIRE(app_config.get_printer_setting("Tool Changer", "filament_is_mixed") == "0,0,0,0,1");
|
||||||
|
}
|
||||||
|
|
||||||
|
PresetBundle bundle;
|
||||||
|
make_toolchanger(bundle);
|
||||||
|
add_inmemory_preset(bundle.filaments, "Test Filament");
|
||||||
|
bundle.load_selections(app_config);
|
||||||
|
|
||||||
|
CHECK(bundle.filament_presets.size() == 5);
|
||||||
|
CHECK(bundle.num_mixed_filaments() == 1);
|
||||||
|
CHECK(bundle.is_mixed_filament(4));
|
||||||
|
|
||||||
|
SECTION("and through the GUI startup calls that follow it") {
|
||||||
|
// GUI_App::load_current_presets sizes the list for a non-SEMM printer, growing only.
|
||||||
|
const size_t target = 4u + bundle.num_mixed_filaments();
|
||||||
|
if (target > bundle.filament_presets.size())
|
||||||
|
bundle.set_num_filaments(target);
|
||||||
|
CHECK(bundle.num_mixed_filaments() == 1);
|
||||||
|
|
||||||
|
// TabPrinter::extruders_count_changed.
|
||||||
|
bundle.on_extruders_count_changed(4);
|
||||||
|
CHECK(bundle.num_mixed_filaments() == 1);
|
||||||
|
|
||||||
|
// Tab::select_preset re-reads the snapshot when remember_printer_config is on.
|
||||||
|
bundle.update_selections(app_config);
|
||||||
|
CHECK(bundle.filament_presets.size() == 5);
|
||||||
|
CHECK(bundle.num_mixed_filaments() == 1);
|
||||||
|
CHECK(bundle.is_mixed_filament(4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The startup sizing in GUI_App::load_current_presets targets the nozzle count plus the mixes.
|
||||||
|
// That is a floor, never a ceiling: set_num_filaments() trims at the raw tail, which is exactly
|
||||||
|
// where the mixes live, so applying the target to a longer list deletes them. A list longer than
|
||||||
|
// the target is reachable - raising the extruder count without saving the printer preset leaves
|
||||||
|
// the extra physical slot behind on the next start - so the startup sizing must only ever grow.
|
||||||
|
TEST_CASE("Sizing down to the nozzle count plus mixes is what eats the mixed tail", "[Preset][Bundle][FilamentMixer]")
|
||||||
|
{
|
||||||
|
// 5 physical + 1 mix, on a printer preset still reporting 4 nozzles.
|
||||||
|
const size_t nozzle_count = 4;
|
||||||
|
PresetBundle bundle;
|
||||||
|
bundle.set_num_filaments(6u, std::string("#FF0000"));
|
||||||
|
bundle.project_config.option<ConfigOptionBools>("filament_is_mixed")->values =
|
||||||
|
{ false, false, false, false, false, true };
|
||||||
|
bundle.project_config.option<ConfigOptionStrings>("filament_mixed_components")->values =
|
||||||
|
{ "", "", "", "", "", "1,2" };
|
||||||
|
REQUIRE(bundle.num_physical_filaments() == 5);
|
||||||
|
|
||||||
|
const size_t target = nozzle_count + bundle.num_mixed_filaments();
|
||||||
|
REQUIRE(target < bundle.filament_presets.size());
|
||||||
|
|
||||||
|
SECTION("applied as written, the mix is gone and every slot reads physical") {
|
||||||
|
bundle.set_num_filaments(target);
|
||||||
|
|
||||||
|
CHECK(bundle.filament_presets.size() == target);
|
||||||
|
CHECK(bundle.num_mixed_filaments() == 0);
|
||||||
|
CHECK(bundle.num_physical_filaments() == target);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("applied as a floor, the mix is left alone") {
|
||||||
|
if (target > bundle.filament_presets.size())
|
||||||
|
bundle.set_num_filaments(target);
|
||||||
|
|
||||||
|
CHECK(bundle.filament_presets.size() == 6);
|
||||||
|
CHECK(bundle.num_mixed_filaments() == 1);
|
||||||
|
CHECK(bundle.is_mixed_filament(5));
|
||||||
|
CHECK(bundle.project_config.option<ConfigOptionStrings>("filament_mixed_components")->values[5] == "1,2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user