mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-12 10:21:17 +00:00
Merge upstream main: multi-variant printers, X-Ray view, preview and startup work
The two conflicts are both places where upstream landed on top of IDEX/IQEX
code. In GCode.cpp the relocated file header block meets the IMEX placeholder
block, and the placeholders are set first: file_start_gcode is processed through
the placeholder parser now, which throws on a name it does not know, so a script
naming {imex_mode} would abort the export if the header ran first. In
test_multifilament.cpp both sides appended a case at the end of the file.
This commit is contained in:
+65
-15
@@ -509,7 +509,7 @@ void Tab::create_preset_tab()
|
||||
|
||||
if (dynamic_cast<TabPrinter *>(this) || dynamic_cast<TabPrint *>(this)) {
|
||||
m_extruder_switch = new MultiSwitchButton(panel);
|
||||
m_extruder_switch->SetMaxSize({em_unit(this) * 40, -1});
|
||||
m_extruder_switch->SetFitToOptions();
|
||||
m_extruder_switch->Bind(wxCUSTOMEVT_MULTISWITCH_SELECTION, [this](auto &evt) {
|
||||
evt.Skip();
|
||||
int selection = evt.GetInt();
|
||||
@@ -542,7 +542,8 @@ void Tab::create_preset_tab()
|
||||
auto right_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
m_variant_sizer->AddStretchSpacer(1);
|
||||
m_variant_sizer->Add(m_extruder_switch, 0, wxALIGN_CENTER, 0);
|
||||
// Orca: proportion 1 lets a narrow row squeeze the switch, which then scrolls its buttons.
|
||||
m_variant_sizer->Add(m_extruder_switch, 1, wxALIGN_CENTER, 0);
|
||||
m_variant_sizer->Add(right_sizer, 1, wxALIGN_CENTER);
|
||||
right_sizer->AddStretchSpacer(1);
|
||||
right_sizer->Add(m_extruder_sync_box, 0, wxALIGN_CENTER | wxRIGHT, m_em_unit);
|
||||
@@ -2794,7 +2795,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("is_infill_first", "quality_settings_wall_and_surfaces#print-infill-first");
|
||||
optgroup->append_single_option_line("wall_direction", "quality_settings_wall_and_surfaces#wall-loop-direction");
|
||||
optgroup->append_single_option_line("print_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("top_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("top_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio", 0);
|
||||
optgroup->append_single_option_line("bottom_solid_infill_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("set_other_flow_ratios", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
optgroup->append_single_option_line("first_layer_flow_ratio", "quality_settings_wall_and_surfaces#surface-flow-ratio");
|
||||
@@ -3072,6 +3073,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("wipe_tower_rib_width", "multimaterial_settings_prime_tower#rib-width");
|
||||
optgroup->append_single_option_line("wipe_tower_fillet_wall", "multimaterial_settings_prime_tower#fillet-wall");
|
||||
optgroup->append_single_option_line("wipe_tower_no_sparse_layers", "multimaterial_settings_prime_tower#no-sparse-layers");
|
||||
optgroup->append_single_option_line("wipe_tower_sparse_layers_combination", "multimaterial_settings_prime_tower#combine-sparse-layers");
|
||||
optgroup->append_single_option_line("single_extruder_multi_material_priming", "multimaterial_settings_prime_tower");
|
||||
|
||||
optgroup = page->new_optgroup(L("Filament for Features"), L"param_filament_for_features");
|
||||
@@ -7383,12 +7385,18 @@ void Tab::restore_last_select_item()
|
||||
|
||||
bool Tab::page_build_pending() const
|
||||
{
|
||||
return m_active_page != nullptr && m_active_page->build_pending();
|
||||
return m_active_page != nullptr && (m_active_page->build_pending() || m_active_page->visibility_pending());
|
||||
}
|
||||
|
||||
bool Tab::page_build_step()
|
||||
{
|
||||
return m_active_page != nullptr && m_active_page->build_step(m_mode);
|
||||
if (m_active_page == nullptr)
|
||||
return false;
|
||||
if (m_active_page->build_pending())
|
||||
m_active_page->build_step(m_mode);
|
||||
else
|
||||
m_active_page->update_visibility(m_mode, true);
|
||||
return page_build_pending();
|
||||
}
|
||||
|
||||
void Tab::update_description_lines()
|
||||
@@ -7402,6 +7410,14 @@ void Tab::activate_selected_page(std::function<void()> throw_if_canceled)
|
||||
if (!m_active_page)
|
||||
return;
|
||||
|
||||
#ifdef __WXGTK__
|
||||
// Builds the page off screen, since GTK crashes when it desensitizes a multiline text view
|
||||
// that was built on screen and hidden before its first size allocation.
|
||||
const bool hide_view = m_active_page->build_pending() && m_page_view->IsShown();
|
||||
if (hide_view)
|
||||
m_page_view->Hide();
|
||||
ScopeGuard show_view([this, hide_view] { if (hide_view) m_page_view->Show(); });
|
||||
#endif
|
||||
m_active_page->activate(m_mode, throw_if_canceled);
|
||||
update_changed_ui();
|
||||
update_description_lines();
|
||||
@@ -8375,7 +8391,7 @@ void Tab::update_extruder_variants(int extruder_id, bool reload)
|
||||
|
||||
// Orca: a non-Bambu dual-nozzle printer has two extruders but a single variant column, so
|
||||
// the nozzle switch and sync button have nothing to act on. Only enable with real variants.
|
||||
if (extruder_nums == 2 && m_preset_bundle->support_different_extruders()) {
|
||||
if (extruder_nums >= 2 && m_preset_bundle->support_different_extruders()) {
|
||||
auto options = generate_extruder_options();
|
||||
m_extruder_switch->SetOptions(options);
|
||||
|
||||
@@ -8422,6 +8438,25 @@ void Tab::update_extruder_variants(int extruder_id, bool reload)
|
||||
}
|
||||
}
|
||||
|
||||
// The variant switch tags are the narrowest place a volume type is named, so they abbreviate it;
|
||||
// the flow combo boxes and the Printer tab's parameter labels keep the full names.
|
||||
static wxString short_nozzle_volume_name(const std::string &volume_name)
|
||||
{
|
||||
// Hybrid has no entry on purpose: it is never a variant string, and the switch lists its two
|
||||
// sub-nozzle types as separate tags (see generate_extruder_options).
|
||||
if (volume_name == "Standard")
|
||||
return "SF";
|
||||
if (volume_name == "High Flow")
|
||||
return "HF";
|
||||
if (volume_name == "TPU High Flow")
|
||||
return "TPU HF";
|
||||
if (volume_name == "E3D High Flow")
|
||||
return "E3D HF";
|
||||
if (volume_name == "Extra High Flow")
|
||||
return "XHF";
|
||||
return from_u8(volume_name);
|
||||
}
|
||||
|
||||
std::vector<wxString> Tab::generate_extruder_options()
|
||||
{
|
||||
std::vector<wxString> options;
|
||||
@@ -8462,7 +8497,7 @@ std::vector<wxString> Tab::generate_extruder_options()
|
||||
nozzle = "";
|
||||
}
|
||||
}
|
||||
options.push_back(wxString::Format(_L("%s: %s"), _L(drive), _L(nozzle)));
|
||||
options.push_back(wxString::Format(_L("%s: %s"), _L(drive), short_nozzle_volume_name(nozzle)));
|
||||
}
|
||||
return options;
|
||||
}
|
||||
@@ -8476,18 +8511,22 @@ std::vector<wxString> Tab::generate_extruder_options()
|
||||
}
|
||||
|
||||
std::string pt = m_preset_bundle->printers.get_edited_preset().get_printer_type(m_preset_bundle);
|
||||
// Orca: the main/deputy toolhead names describe a dual-nozzle printer, where extruder 0 is the
|
||||
// left (deputy) and extruder 1 the right (main) nozzle. From three extruders on the tools are
|
||||
// interchangeable, so name them by index instead of repeating one side.
|
||||
for (int i = 0; i < extruder_nums; ++i) {
|
||||
int ext_id = (i == 0) ? DEPUTY_EXTRUDER_ID : MAIN_EXTRUDER_ID;
|
||||
wxString extruder_name = _L(DevPrinterConfigUtil::get_toolhead_display_name(
|
||||
pt, ext_id, ToolHeadComponent::Nozzle, ToolHeadNameCase::TitleCase, true));
|
||||
wxString extruder_name = extruder_nums > 2 ? wxString::Format("T%d", i + 1) :
|
||||
_L(DevPrinterConfigUtil::get_toolhead_display_name(
|
||||
pt, (i == 0) ? DEPUTY_EXTRUDER_ID : MAIN_EXTRUDER_ID,
|
||||
ToolHeadComponent::Nozzle, ToolHeadNameCase::TitleCase, true));
|
||||
NozzleVolumeType volume_type = NozzleVolumeType(nozzle_volumes->values[i]);
|
||||
|
||||
if (volume_type == NozzleVolumeType::nvtHybrid) {
|
||||
options.push_back(wxString::Format(_L("%s: %s"), extruder_name, _L("Standard")));
|
||||
options.push_back(wxString::Format(_L("%s: %s"), extruder_name, _L("High Flow")));
|
||||
options.push_back(wxString::Format(_L("%s: %s"), extruder_name, short_nozzle_volume_name(get_nozzle_volume_type_string(NozzleVolumeType::nvtStandard))));
|
||||
options.push_back(wxString::Format(_L("%s: %s"), extruder_name, short_nozzle_volume_name(get_nozzle_volume_type_string(NozzleVolumeType::nvtHighFlow))));
|
||||
} else {
|
||||
wxString volume_name = get_nozzle_volume_type_name(volume_type);
|
||||
options.push_back(wxString::Format(_L("%s: %s"), extruder_name, volume_name));
|
||||
options.push_back(wxString::Format(_L("%s: %s"), extruder_name,
|
||||
short_nozzle_volume_name(get_nozzle_volume_type_string(volume_type))));
|
||||
}
|
||||
}
|
||||
return options;
|
||||
@@ -8518,7 +8557,10 @@ bool Tab::get_extruder_sync_enable_state(int extruder_id)
|
||||
Preset& printer_preset = m_preset_bundle->printers.get_edited_preset();
|
||||
auto nozzle_volumes = m_preset_bundle->project_config.option<ConfigOptionEnumsGeneric>("nozzle_volume_type");
|
||||
auto extruders = printer_preset.config.option<ConfigOptionEnumsGeneric>("extruder_type");
|
||||
if (nozzle_volumes->values.size() < 2 || extruders->values.size() < 2) {
|
||||
// Orca: every rule below describes the two toolheads of a dual-nozzle printer as left/right.
|
||||
// A printer with any other extruder count has no single counterpart to copy to, so it gets no
|
||||
// sync button (a toolchanger would need a target to be chosen).
|
||||
if (nozzle_volumes->values.size() != 2 || extruders->values.size() != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -8659,6 +8701,10 @@ void Tab::sync_excluder()
|
||||
ExtruderType(extruders->values[extruder_id]), nozzle_type, variant_keys.second, stride);
|
||||
};
|
||||
int active_index = get_current_active_extruder();
|
||||
// The button copies to the other toolhead, so it is only offered when that other one exists;
|
||||
// without this the `1 - active_index` below would index an extruder that is not there.
|
||||
if (!get_extruder_sync_enable_state(active_index))
|
||||
return;
|
||||
auto active_nozzle = get_actual_nozzle_volume_type(active_index);
|
||||
int from_index = get_index_for_extruder(active_index, active_nozzle);
|
||||
int dest_index = get_index_for_extruder(1 - active_index, active_nozzle);
|
||||
@@ -8811,6 +8857,8 @@ void Page::update_visibility(ConfigOptionMode mode, bool update_contolls_visibil
|
||||
}
|
||||
|
||||
m_show = ret_val;
|
||||
if (update_contolls_visibility)
|
||||
m_visibility_applied = true;
|
||||
#ifdef __WXMSW__
|
||||
if (!m_show) return;
|
||||
// BBS: fix field control position
|
||||
@@ -8864,6 +8912,7 @@ bool Page::activate_group(size_t i, ConfigOptionMode mode, std::function<void()>
|
||||
auto& group = m_optgroups[i];
|
||||
if (!group->activate(throw_if_canceled))
|
||||
return false;
|
||||
m_visibility_applied = false;
|
||||
m_vsizer->Add(group->sizer, 0, wxEXPAND | (group->is_legend_line() ? (wxLEFT|wxTOP) : wxALL), m_parent->FromDIP(5)); // ORCA use less margin on parameters section
|
||||
group->update_visibility(mode);
|
||||
#if HIDE_FIRST_SPLIT_LINE
|
||||
@@ -8898,6 +8947,7 @@ void Page::clear()
|
||||
for (auto group : m_optgroups)
|
||||
group->clear();
|
||||
m_page_title = NULL;
|
||||
m_visibility_applied = false;
|
||||
}
|
||||
|
||||
void Page::msw_rescale()
|
||||
|
||||
Reference in New Issue
Block a user