Sync upstream main

Includes nozzle-diameter guards for printers without nozzle info (#13255,
now landed upstream) and manual-calibration nozzle mismatch fix (#13882).

# Conflicts:
#	src/slic3r/GUI/GCodeViewer.cpp
#	src/slic3r/GUI/GLCanvas3D.hpp
#	src/slic3r/GUI/Tab.cpp
This commit is contained in:
Clifford Garwood
2026-05-29 01:49:42 -04:00
725 changed files with 23746 additions and 9117 deletions
+79 -47
View File
@@ -2406,13 +2406,23 @@ void Sidebar::init_filament_combo(PlaterPresetComboBox **combo, const int filame
edit_btn->SetToolTip(_L("Click to edit preset"));
PlaterPresetComboBox* combobox = (*combo);
edit_btn->Bind(wxEVT_BUTTON, [this, edit_btn, filament_idx](wxCommandEvent) {
auto menu = p->plater->filament_action_menu(filament_idx);
wxPoint pt { 0, edit_btn->GetSize().GetHeight() + 10 };
pt = edit_btn->ClientToScreen(pt);
pt = wxGetApp().mainframe->ScreenToClient(pt);
p->m_menu_filament_id = filament_idx;
p->plater->PopupMenu(menu, (int) pt.x, pt.y);
edit_btn->Bind(wxEVT_BUTTON, [this, edit_btn, combobox, filament_idx](wxCommandEvent) {
bool single_or_bbl = should_show_SEMM_buttons();
bool is_multi_material = p->combos_filament.size() > 1;
if(single_or_bbl && is_multi_material) {
// MULTI MATERIAL Show menu
auto menu = p->plater->filament_action_menu(filament_idx);
wxPoint pt { 0, edit_btn->GetSize().GetHeight() + FromDIP(2) };
pt = edit_btn->ClientToScreen(pt);
pt = wxGetApp().mainframe->ScreenToClient(pt);
p->m_menu_filament_id = filament_idx;
p->plater->PopupMenu(menu, (int) pt.x, pt.y);
}
else {
// SINGLE MATERIAL / MULTI EXTRUDER / TOOLCHANGER / IDEX Opens Dialog directly
p->editing_filament = filament_idx;
combobox->switch_to_tab();
}
});
combobox->edit_btn = edit_btn;
@@ -2513,7 +2523,7 @@ void Sidebar::update_all_preset_comboboxes()
p->m_filament_icon->SetBitmap_("filament");
}
show_SEMM_buttons(should_show_SEMM_buttons());
show_SEMM_buttons();
//p->m_staticText_filament_settings->Update();
@@ -3115,16 +3125,7 @@ void Sidebar::on_filament_count_change(size_t num_filaments)
// remove unused choices if any
remove_unused_filament_combos(num_filaments);
auto sizer = p->m_panel_filament_title->GetSizer();
if (p->m_flushing_volume_btn != nullptr && sizer != nullptr) {
if (num_filaments > 1) {
sizer->Show(p->m_flushing_volume_btn);
sizer->Show(p->m_bpButton_del_filament); // ORCA: Show delete filament button if multiple filaments
} else {
sizer->Hide(p->m_flushing_volume_btn);
sizer->Hide(p->m_bpButton_del_filament); // ORCA: Hide delete filament button if there is only one filament
}
}
show_SEMM_buttons(); // ORCA
update_filaments_area_height(); // ORCA
@@ -3171,16 +3172,7 @@ void Sidebar::on_filaments_delete(size_t filament_id)
}
}
auto sizer = p->m_panel_filament_title->GetSizer();
if (p->m_flushing_volume_btn != nullptr && sizer != nullptr) {
if (p->combos_filament.size() > 1) {
sizer->Show(p->m_flushing_volume_btn);
sizer->Show(p->m_bpButton_del_filament); // ORCA: Show delete filament button if multiple filaments
} else {
sizer->Hide(p->m_flushing_volume_btn);
sizer->Hide(p->m_bpButton_del_filament); // ORCA: Hide delete filament button if there is only one filament
}
}
show_SEMM_buttons(); // ORCA
for (size_t idx = filament_id ; idx < p->combos_filament.size(); ++idx) {
p->combos_filament[idx]->update();
@@ -3739,14 +3731,31 @@ bool Sidebar::should_show_SEMM_buttons()
return cfg.opt_bool("single_extruder_multi_material") || is_bbl_vendor;
}
void Sidebar::show_SEMM_buttons(bool bshow)
void Sidebar::show_SEMM_buttons()
{
if(p->m_bpButton_add_filament)
p->m_bpButton_add_filament->Show(bshow);
if (p->m_bpButton_del_filament && p->combos_filament.size() > 1) // ORCA add filament count as condition to prevent showing Flushing volumes and Del Filament icon visible while only 1 filament exist
p->m_bpButton_del_filament->Show(bshow);
if (p->m_flushing_volume_btn && p->combos_filament.size() > 1) // ORCA add filament count as condition to prevent showing Flushing volumes and Del Filament icon visible while only 1 filament exist
p->m_flushing_volume_btn->Show(bshow);
// ORCA
if (!p || p->combos_filament.empty() || !p->m_bpButton_add_filament || !p->m_bpButton_del_filament || !p->m_flushing_volume_btn)
return;
bool is_multi_material = p->combos_filament.size() > 1;
bool single_or_bbl = should_show_SEMM_buttons();
bool is_single = single_or_bbl && !is_multi_material; // SINGLE EXTRUDER / BBL WITH 1 MATERIAL
bool is_multi = single_or_bbl && is_multi_material; // MULTI MATERIAL WITH SINGLE EXTRUDER
bool is_fixed = !is_single && !is_multi; // MULTI EXTRUDER / TOOLCHANGER / IDEX WITH FIXED MATERIAL
p->m_bpButton_add_filament->Show(single_or_bbl);
p->m_bpButton_del_filament->Show(is_multi);
p->m_flushing_volume_btn->Show( is_multi);
if (is_multi) {
for (auto &c : p->combos_filament)
c->edit_btn->SetBitmap_("menu_filament");
}
else if (is_single || is_fixed) {
for (auto &c : p->combos_filament)
c->edit_btn->SetBitmap_("edit");
}
Layout();
}
@@ -6845,12 +6854,12 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
double preset_nozzle_diameter = 0.4;
const ConfigOption *opt = printer_preset.config.option("nozzle_diameter");
if (opt) preset_nozzle_diameter = static_cast<const ConfigOptionFloats *>(opt)->values[0];
float machine_nozzle_diameter = obj->GetExtderSystem()->GetNozzleDiameter(0);
std::string machine_type = obj->printer_type;
if (obj->is_support_upgrade_kit && obj->installed_upgrade_kit) machine_type = "C12";
if (printer_preset.get_current_printer_type(preset_bundle) != machine_type || !is_approx((float) preset_nozzle_diameter, machine_nozzle_diameter)) {
bool nozzle_mismatch = !obj->GetExtderSystem()->NozzleDiameterMatchesOrUnknown(0, (float) preset_nozzle_diameter);
if (printer_preset.get_current_printer_type(preset_bundle) != machine_type || nozzle_mismatch) {
Preset *machine_preset = get_printer_preset(obj);
if (machine_preset != nullptr) {
std::string printer_model = machine_preset->config.option<ConfigOptionString>("printer_model")->value;
@@ -7631,7 +7640,7 @@ void Plater::priv::split_object(int obj_idx, bool auto_drop /* = true */)
wxBusyCursor wait;
ModelObjectPtrs new_objects;
current_model_object->split(&new_objects);
current_model_object->split(&new_objects, wxGetApp().app_config->get_bool("keep_painting"));
if (new_objects.size() == 1)
// #ysFIXME use notification
Slic3r::GUI::warning_catcher(q, _L("The selected object couldn't be split."));
@@ -8395,10 +8404,20 @@ bool Plater::priv::replace_volume_with_stl(int object_idx, int volume_idx, const
new_volume->convert_from_imperial_units();
else if (old_volume->source.is_converted_from_meters)
new_volume->convert_from_meters();
new_volume->supported_facets.assign(old_volume->supported_facets);
new_volume->seam_facets.assign(old_volume->seam_facets);
new_volume->mmu_segmentation_facets.assign(old_volume->mmu_segmentation_facets);
new_volume->fuzzy_skin_facets.assign(old_volume->fuzzy_skin_facets);
if (wxGetApp().app_config->get_bool("keep_painting")) {
// Proper paint remapping
auto saved_painting = old_volume->save_painting();
if (saved_painting) {
saved_painting->mesh.transform(Geometry::translation_transform(new_volume->mesh().get_init_shift()));
new_volume->restore_painting(saved_painting);
}
} else {
// Won't work well if mesh changed, but kept for old behavior
new_volume->supported_facets.assign(old_volume->supported_facets);
new_volume->seam_facets.assign(old_volume->seam_facets);
new_volume->mmu_segmentation_facets.assign(old_volume->mmu_segmentation_facets);
new_volume->fuzzy_skin_facets.assign(old_volume->fuzzy_skin_facets);
}
std::swap(old_model_object->volumes[volume_idx], old_model_object->volumes.back());
old_model_object->delete_volume(old_model_object->volumes.size() - 1);
if (!sinking)
@@ -8924,6 +8943,16 @@ void Plater::priv::reload_from_disk()
new_volume->convert_from_imperial_units();
else if (old_volume->source.is_converted_from_meters)
new_volume->convert_from_meters();
// Remap paint
if (wxGetApp().app_config->get_bool("keep_painting")) {
auto saved_painting = old_volume->save_painting();
if (saved_painting) {
saved_painting->mesh.transform(Geometry::translation_transform(new_volume->mesh().get_init_shift()));
new_volume->restore_painting(saved_painting);
}
}
std::swap(old_model_object->volumes[vol_idx], old_model_object->volumes.back());
old_model_object->delete_volume(old_model_object->volumes.size() - 1);
if (!sinking) old_model_object->ensure_on_bed();
@@ -9557,7 +9586,7 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt)
const auto& extruders = obj->GetExtderSystem()->GetExtruders();
for (const DevExtder &extruder : extruders) {
if (!is_approx(extruder.GetNozzleDiameter(), float(preset_nozzle_diameter))) {
if (!obj->GetExtderSystem()->NozzleDiameterMatchesOrUnknown(extruder.GetExtId(), float(preset_nozzle_diameter))) {
same_nozzle_diameter = false;
}
}
@@ -15026,7 +15055,8 @@ void Plater::export_gcode(bool prefer_removable)
unsigned int state = this->p->update_restart_background_process(false, false);
if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID)
return;
default_output_file = this->p->background_process.output_filepath_for_project("");
default_output_file = this->p->background_process.output_filepath_for_project(
into_path(this->p->get_project_filename(".3mf")));
} catch (const Slic3r::PlaceholderParserError &ex) {
// Show the error with monospaced font.
show_error(this, ex.what(), true);
@@ -15129,7 +15159,8 @@ void Plater::export_gcode_3mf(bool export_all)
unsigned int state = this->p->update_restart_background_process(false, false);
if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID)
return;
default_output_file = this->p->background_process.output_filepath_for_project("");
default_output_file = this->p->background_process.output_filepath_for_project(
into_path(this->p->get_project_filename(".3mf")));
}
catch (const Slic3r::PlaceholderParserError& ex) {
// Show the error with monospaced font.
@@ -15327,7 +15358,7 @@ TriangleMesh Plater::combine_mesh_fff(const ModelObject& mo, int instance_id, st
}
if (instance_id == -1) {
TriangleMesh vols_mesh(mesh);
TriangleMesh vols_mesh(std::move(mesh));
mesh = TriangleMesh();
for (const ModelInstance* i : mo.instances) {
TriangleMesh m = vols_mesh;
@@ -16276,7 +16307,8 @@ void Plater::send_gcode_legacy(int plate_idx, Export3mfProgressFn proFn, bool us
unsigned int state = this->p->update_restart_background_process(false, false);
if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID)
return;
default_output_file = this->p->background_process.output_filepath_for_project("");
default_output_file = this->p->background_process.output_filepath_for_project(
into_path(this->p->get_project_filename(".3mf")));
} catch (const Slic3r::PlaceholderParserError& ex) {
// Show the error with monospaced font.
show_error(this, ex.what(), true);