Merge upstream, and index pressure advance by extruder variant

Upstream moved pressure advance onto the extruder variant: enable_pressure_advance,
pressure_advance and the four adaptive keys joined filament_options_with_variant,
the repeated inline blocks in set_extruder() became a helper, and the lookups
moved from the filament id to get_filament_config_index().

All three conflicts were the same collision, because this branch had modified two
of those same inline blocks to pass a tool qualifier so each carriage is addressed
explicitly in parallel modes. Taking either side whole would have lost something:
upstream's drops the qualifier and leaves parallel carriages with no pressure
advance, ours drops the per-variant indexing and reads the wrong column on a
multi-variant printer. The helper now takes an optional tool, defaulting to -1,
which omits the qualifier. imex_pem_tool_for() already returns -1 off IMEX and in
primary mode, so non-IMEX output is unchanged, and the three call sites that never
passed a tool keep upstream's behavior exactly.

The third conflict was two test cases appended at the same place. Both are kept.

Separately, one defect that merged cleanly and so was not flagged: the loop that
emits pressure advance for secondary carriages at the start of a print still
bounded and indexed those vectors with a raw filament id. They are variant
expanded now, so their length is columns rather than filament slots -- the value
read was the wrong column, and the bound no longer sat in slot space, letting an
out-of-slot filament through. It now bounds on filament_diameter and translates
with get_filament_config_index(), which is what the sibling second-layer
temperature loop already does.

Verified: both changed translation units compile clean under -Werror. The merge
was resolved independently twice and the two resolutions agree on every line of
code. Not yet run: the Release test suite and a parallel-mode slice sweep.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Clifford Garwood
2026-09-29 21:43:47 -04:00
co-authored by Claude Opus 5
109 changed files with 3823 additions and 1295 deletions
+150 -216
View File
@@ -1997,6 +1997,126 @@ bool MainFrame::can_reslice() const
return (m_plater != nullptr) && !m_plater->model().objects.empty();
}
namespace {
// Orca: stable key persisted by the "remember last print action" preference. Reordering PrintSelectType
// must not silently remap a saved preference, so the key never derives from the enum value.
const char* print_select_type_key(MainFrame::PrintSelectType type)
{
switch (type) {
case MainFrame::ePrintAll: return "print_all";
case MainFrame::ePrintPlate: return "print_plate";
case MainFrame::eExportSlicedFile: return "export_sliced_file";
case MainFrame::eExportAllSlicedFile: return "export_all_sliced_file";
case MainFrame::eExportGcode: return "export_gcode";
case MainFrame::eSendGcode: return "send_gcode";
case MainFrame::eSendToPrinter: return "send_to_printer";
case MainFrame::eSendToPrinterAll: return "send_to_printer_all";
case MainFrame::ePrintMultiMachine: return "print_multi_machine";
case MainFrame::eUploadGcode: break; // Orca: no dropdown entry, never selectable
}
return "";
}
// Orca: single source for the print button and print dropdown labels
wxString print_select_type_label(MainFrame::PrintSelectType type)
{
switch (type) {
case MainFrame::ePrintAll: return _L("Print all");
case MainFrame::ePrintPlate: return _L("Print plate");
case MainFrame::eExportSlicedFile: return _L("Export plate sliced file");
case MainFrame::eExportAllSlicedFile: return _L("Export all sliced file");
case MainFrame::eExportGcode: return _L("Export G-code file");
case MainFrame::eSendGcode: return _L_CONTEXT("Print", "Verb");
case MainFrame::eSendToPrinter: return _L("Send");
case MainFrame::eSendToPrinterAll: return _L("Send all");
case MainFrame::ePrintMultiMachine: return _L("Send to Multi-device");
case MainFrame::eUploadGcode: break; // Orca: no dropdown entry, never selectable
}
return _L("Print plate");
}
} // namespace
std::vector<MainFrame::PrintSelectType> MainFrame::available_print_actions() const
{
std::vector<PrintSelectType> actions;
const auto preset_bundle = wxGetApp().preset_bundle;
const bool use_printer_agents = wxGetApp().app_config->get_bool("use_printer_agents");
if (preset_bundle && !preset_bundle->is_bbl_vendor() && !use_printer_agents) {
// ThirdParty actions
actions.push_back(eSendGcode);
// Orca: when the printer accepts a .gcode.3mf (the "Support 3MF as gcode" option),
// also offer exporting the sliced .gcode.3mf bundle
const auto* use_3mf_opt = preset_bundle->printers.get_edited_preset().config.option<ConfigOptionBool>("use_3mf");
if (use_3mf_opt != nullptr && use_3mf_opt->value)
actions.push_back(eExportSlicedFile);
actions.push_back(eExportGcode);
return actions;
}
// Orca Slicer actions
bool support_send = true;
bool support_print_all = true;
if (preset_bundle && !preset_bundle->use_bbl_network() && !use_printer_agents) {
support_send = false; // All 3rd print hosts do not have the send options
const auto& cfg = preset_bundle->printers.get_edited_preset().config;
const auto* host_type_opt = cfg.option<ConfigOptionEnum<PrintHostType>>("host_type");
// Only simply print support uploading all plates
support_print_all = host_type_opt != nullptr && host_type_opt->value == PrintHostType::htSimplyPrint;
}
actions.push_back(ePrintPlate);
if (support_print_all)
actions.push_back(ePrintAll);
if (support_send) {
actions.push_back(eSendToPrinter);
actions.push_back(eSendToPrinterAll);
}
if (enable_multi_machine)
actions.push_back(ePrintMultiMachine);
actions.push_back(eExportSlicedFile);
actions.push_back(eExportAllSlicedFile);
actions.push_back(eExportGcode);
return actions;
}
void MainFrame::select_print_action(PrintSelectType select_type)
{
m_print_btn->SetLabel(print_select_type_label(select_type));
m_print_select = select_type;
remember_print_select(select_type);
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
}
void MainFrame::remember_print_select(PrintSelectType select_type)
{
if (!wxGetApp().app_config->get_bool("remember_print_action"))
return;
// AppConfig is marked dirty here and flushed by the regular autosave
wxGetApp().app_config->set("last_print_action", print_select_type_key(select_type));
}
bool MainFrame::get_remembered_print_select(PrintSelectType& out) const
{
if (!wxGetApp().app_config->get_bool("remember_print_action"))
return false;
const std::string saved = wxGetApp().app_config->get("last_print_action");
if (saved.empty())
return false;
// Orca: only restore an action the current printer actually offers in the dropdown
for (PrintSelectType type : available_print_actions()) {
if (saved == print_select_type_key(type)) {
out = type;
return true;
}
}
return false;
}
wxBoxSizer* MainFrame::create_side_tools()
{
enable_multi_machine = wxGetApp().is_enable_multi_machine();
@@ -2016,6 +2136,14 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_btn = new SideButton(print_panel, _L("Print plate"), "");
m_print_option_btn = new SideButton(print_panel, "", "sidebutton_dropdown", 0, 14);
// Orca: restore the last used print/export action if the user opted to remember it
PrintSelectType remembered_print_select;
if (get_remembered_print_select(remembered_print_select)) {
m_print_select = remembered_print_select;
m_print_btn->SetLabel(print_select_type_label(remembered_print_select));
fit_tab_labels(); // ORCA on label change
}
auto slice_sizer = new wxBoxSizer(wxHORIZONTAL);
slice_sizer->Add(m_slice_option_btn, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, FromDIP(1));
slice_sizer->Add(m_slice_btn, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, FromDIP(1));
@@ -2178,193 +2306,15 @@ wxBoxSizer* MainFrame::create_side_tools()
m_print_option_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event)
{
SidePopup* p = new SidePopup(this);
if (wxGetApp().preset_bundle
&& !wxGetApp().preset_bundle->is_bbl_vendor()
&& !wxGetApp().app_config->get_bool("use_printer_agents")) {
// ThirdParty Buttons
SideButton* export_gcode_btn = new SideButton(p, _L("Export G-code file"), "");
export_gcode_btn->SetCornerRadius(0);
export_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Export G-code file"));
m_print_select = eExportGcode;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
for (PrintSelectType type : available_print_actions()) {
SideButton* btn = new SideButton(p, print_select_type_label(type), "");
btn->SetCornerRadius(0);
btn->Bind(wxEVT_BUTTON, [this, p, type](wxCommandEvent&) {
select_print_action(type);
p->Dismiss();
});
// upload and print
SideButton* send_gcode_btn = new SideButton(p, _L_CONTEXT("Print", "Verb"), "");
send_gcode_btn->SetCornerRadius(0);
send_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L_CONTEXT("Print", "Verb"));
m_print_select = eSendGcode;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
p->append_button(send_gcode_btn);
// Orca: when the printer accepts a .gcode.3mf (the "Support 3MF as gcode" option),
// also offer exporting the sliced .gcode.3mf bundle
const auto& printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
const auto* use_3mf_opt = printer_config.option<ConfigOptionBool>("use_3mf");
if (use_3mf_opt != nullptr && use_3mf_opt->value) {
SideButton* export_sliced_file_btn = new SideButton(p, _L("Export plate sliced file"), "");
export_sliced_file_btn->SetCornerRadius(0);
export_sliced_file_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Export plate sliced file"));
m_print_select = eExportSlicedFile;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
p->append_button(export_sliced_file_btn);
}
p->append_button(export_gcode_btn);
p->append_button(btn);
}
else {
//Orca Slicer Buttons
SideButton* print_plate_btn = new SideButton(p, _L("Print plate"), "");
print_plate_btn->SetCornerRadius(0);
SideButton* send_to_printer_btn = new SideButton(p, _L("Send"), "");
send_to_printer_btn->SetCornerRadius(0);
SideButton* export_sliced_file_btn = new SideButton(p, _L("Export plate sliced file"), "");
export_sliced_file_btn->SetCornerRadius(0);
SideButton* export_all_sliced_file_btn = new SideButton(p, _L("Export all sliced file"), "");
export_all_sliced_file_btn->SetCornerRadius(0);
print_plate_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Print plate"));
m_print_select = ePrintPlate;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
SideButton* print_all_btn = new SideButton(p, _L("Print all"), "");
print_all_btn->SetCornerRadius(0);
print_all_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Print all"));
m_print_select = ePrintAll;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
send_to_printer_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Send"));
m_print_select = eSendToPrinter;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
SideButton* send_to_printer_all_btn = new SideButton(p, _L("Send all"), "");
send_to_printer_all_btn->SetCornerRadius(0);
send_to_printer_all_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Send all"));
m_print_select = eSendToPrinterAll;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
export_sliced_file_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Export plate sliced file"));
m_print_select = eExportSlicedFile;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
export_all_sliced_file_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Export all sliced file"));
m_print_select = eExportAllSlicedFile;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
bool support_send = true;
bool support_print_all = true;
const auto preset_bundle = wxGetApp().preset_bundle;
if (preset_bundle) {
if (preset_bundle->use_bbl_network() || wxGetApp().app_config->get_bool("use_printer_agents")) {
// BBL network support everything
} else {
support_send = false; // All 3rd print hosts do not have the send options
auto cfg = preset_bundle->printers.get_edited_preset().config;
const auto host_type = cfg.option<ConfigOptionEnum<PrintHostType>>("host_type")->value;
// Only simply print support uploading all plates
support_print_all = host_type == PrintHostType::htSimplyPrint;
}
}
p->append_button(print_plate_btn);
if (support_print_all) {
p->append_button(print_all_btn);
}
if (support_send) {
p->append_button(send_to_printer_btn);
p->append_button(send_to_printer_all_btn);
}
if (enable_multi_machine) {
SideButton* print_multi_machine_btn = new SideButton(p, _L("Send to Multi-device"), "");
print_multi_machine_btn->SetCornerRadius(0);
print_multi_machine_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Send to Multi-device"));
m_print_select = ePrintMultiMachine;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
p->append_button(print_multi_machine_btn);
}
p->append_button(export_sliced_file_btn);
p->append_button(export_all_sliced_file_btn);
SideButton* export_gcode_btn = new SideButton(p, _L("Export G-code file"), "");
export_gcode_btn->SetCornerRadius(0);
export_gcode_btn->Bind(wxEVT_BUTTON, [this, p](wxCommandEvent&) {
m_print_btn->SetLabel(_L("Export G-code file"));
m_print_select = eExportGcode;
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
fit_tab_labels(); // ORCA on label change
p->Dismiss();
});
p->append_button(export_gcode_btn);
}
p->Popup(m_print_btn);
}
);
@@ -4248,38 +4198,22 @@ void MainFrame::on_config_changed(DynamicPrintConfig* config) const
void MainFrame::set_print_button_to_default(PrintSelectType select_type)
{
if (select_type == PrintSelectType::ePrintPlate) {
m_print_btn->SetLabel(_L("Print plate"));
m_print_select = ePrintPlate;
if (m_print_enable)
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
} else if (select_type == PrintSelectType::eSendGcode) {
m_print_btn->SetLabel(_L_CONTEXT("Print", "Verb"));
m_print_select = eSendGcode;
if (m_print_enable)
m_print_enable = get_enable_print_status() && can_send_gcode();
m_print_btn->Enable(m_print_enable);
this->Layout();
} else if (select_type == PrintSelectType::eExportGcode) {
m_print_btn->SetLabel(_L("Export G-code file"));
m_print_select = eExportGcode;
if (m_print_enable)
m_print_enable = get_enable_print_status() && can_send_gcode();
m_print_btn->Enable(m_print_enable);
this->Layout();
} else if (select_type == PrintSelectType::eExportSlicedFile) {
m_print_btn->SetLabel(_L("Export plate sliced file"));
m_print_select = eExportSlicedFile;
if (m_print_enable)
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
} else {
// unsupport
return;
}
// Orca: keep the user's remembered print/export action instead of resetting it to the computed
// default. get_remembered_print_select() already rejects anything this printer does not offer.
PrintSelectType remembered;
if (get_remembered_print_select(remembered))
select_type = remembered;
if (select_type == eUploadGcode)
return; // unsupported: no dropdown entry exists for this action
m_print_btn->SetLabel(print_select_type_label(select_type));
m_print_select = select_type;
// get_enable_print_status() already applies can_send_gcode() to the actions that need it
if (m_print_enable)
m_print_enable = get_enable_print_status();
m_print_btn->Enable(m_print_enable);
this->Layout();
}
void MainFrame::add_to_recent_projects(const wxString& filename)