mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-06-10 14:02:47 +00:00
Fix crash on printer switch from stale filament/extruder indices (#14103)
Switching to a printer with fewer filaments (e.g. H2D -> X2D) threw std::out_of_range in check_filament_printable. Clear stale per-volume extruder config on count shrink and bound-check filament indices at the read sites.
This commit is contained in:
@@ -2573,6 +2573,12 @@ void ModelVolume::update_extruder_count(size_t extruder_count)
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Clear a stale per-volume filament assignment that no longer exists after the extruder count
|
||||
// shrank (e.g. printer switch to one with fewer filaments), so downstream readers never index
|
||||
// per-filament config vectors out of range. Ported from BambuStudio (STUDIO-15763).
|
||||
if (extruder_id() > extruder_count) {
|
||||
this->config.erase("extruder");
|
||||
}
|
||||
}
|
||||
|
||||
void ModelVolume::update_extruder_count_when_delete_filament(size_t extruder_count, size_t filament_id, int replace_filament_id)
|
||||
@@ -2584,6 +2590,11 @@ void ModelVolume::update_extruder_count_when_delete_filament(size_t extruder_cou
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Same stale-assignment cleanup as update_extruder_count, for the filament-delete path.
|
||||
// Ported from BambuStudio (STUDIO-15763).
|
||||
if (extruder_id() > extruder_count) {
|
||||
this->config.erase("extruder");
|
||||
}
|
||||
}
|
||||
|
||||
void ModelVolume::center_geometry_after_creation(bool update_source_offset)
|
||||
|
||||
@@ -2639,8 +2639,14 @@ void GCodeViewer::render_all_plates_stats(const std::vector<const GCodeProcessor
|
||||
{
|
||||
auto plate_print_statistics = plate->get_slice_result()->print_statistics;
|
||||
auto plate_extruders = plate->get_extruders(true);
|
||||
auto max_extruders_colors = wxGetApp().plater()->get_extruders_colors().size();
|
||||
for (size_t extruder_id : plate_extruders) {
|
||||
extruder_id -= 1;
|
||||
// Skip stale/overflow extruder indices (e.g. from object assignments that outlived a
|
||||
// filament-count change) so downstream per-extruder lookups stay in range. Ported
|
||||
// from BambuStudio (STUDIO-15763).
|
||||
if (extruder_id >= max_extruders_colors)
|
||||
continue;
|
||||
if (plate_print_statistics.model_volumes_per_extruder.find(extruder_id) == plate_print_statistics.model_volumes_per_extruder.end())
|
||||
model_volume_of_extruders_all_plates[extruder_id] += 0;
|
||||
else {
|
||||
|
||||
@@ -764,6 +764,10 @@ void ObjectList::update_filament_values_for_items(const size_t filaments_count)
|
||||
if (!object->volumes[id]->config.has("extruder") ||
|
||||
size_t(object->volumes[id]->config.extruder()) > filaments_count) {
|
||||
extruder = wxString::Format("%d", object->config.extruder());
|
||||
// Clear the stale per-volume assignment so it falls back to the object's
|
||||
// extruder; otherwise the out-of-range index survives. Ported from
|
||||
// BambuStudio (STUDIO-15763).
|
||||
object->volumes[id]->config.erase("extruder");
|
||||
}
|
||||
else {
|
||||
extruder = wxString::Format("%d", object->volumes[id]->config.extruder());
|
||||
|
||||
@@ -1931,11 +1931,20 @@ bool PartPlate::check_filament_printable(const DynamicPrintConfig &config, wxStr
|
||||
|
||||
std::vector<int> used_filaments = get_extruders(true); // 1 base
|
||||
if (!used_filaments.empty()) {
|
||||
const std::vector<std::string>& filament_types = config.option<ConfigOptionStrings>("filament_type")->values;
|
||||
const std::vector<int>& filament_printables = config.option<ConfigOptionInts>("filament_printable")->values;
|
||||
const std::vector<int>& filament_map = get_real_filament_maps(config);
|
||||
// This runs synchronously mid printer-switch (load_current_preset -> reload_scene), before the
|
||||
// filament-count reconciliation clears stale per-object assignments, so the plate objects can
|
||||
// still reference filament indices beyond the freshly selected printer config. Skip those to
|
||||
// avoid an out-of-range access. Matches BambuStudio's guards in the same function.
|
||||
const int filament_count = std::min({(int) filament_types.size(), (int) filament_printables.size(), (int) filament_map.size()});
|
||||
for (auto filament_idx : used_filaments) {
|
||||
int filament_id = filament_idx - 1;
|
||||
std::string filament_type = config.option<ConfigOptionStrings>("filament_type")->values.at(filament_id);
|
||||
int filament_printable_status = config.option<ConfigOptionInts>("filament_printable")->values.at(filament_id);
|
||||
std::vector<int> filament_map = get_real_filament_maps(config);
|
||||
if (filament_id < 0 || filament_id >= filament_count)
|
||||
continue;
|
||||
std::string filament_type = filament_types[filament_id];
|
||||
int filament_printable_status = filament_printables[filament_id];
|
||||
int extruder_idx = filament_map[filament_id] - 1;
|
||||
if (!(filament_printable_status >> extruder_idx & 1)) {
|
||||
wxString extruder_name = extruder_idx == 0 ? _L("left") : _L("right");
|
||||
|
||||
Reference in New Issue
Block a user