mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-13 19:01:21 +00:00
Merge upstream main: belt printing, texture displacement color mixing, 3MF component cycle checks, undo blocked during background jobs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+170
-1
@@ -4,6 +4,7 @@
|
||||
#include "libslic3r/IMEXHelpers.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/BeltTransform.hpp"
|
||||
#include "libslic3r/FilamentMixer.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
@@ -1654,6 +1655,13 @@ void Tab::update_mode()
|
||||
{
|
||||
m_mode = wxGetApp().get_mode();
|
||||
|
||||
// toggle_options reads m_mode to gate Lines whose contents are mode-mixed
|
||||
// (e.g., a multi-option row where some options are Advanced and some Expert):
|
||||
// when all of a Line's options would be hidden, we hide the Line itself.
|
||||
// Without refreshing here, the toggle_visible state stays stale across mode
|
||||
// switches and Lines stay hidden.
|
||||
toggle_options();
|
||||
|
||||
update_visibility();
|
||||
|
||||
update_changed_tree_ui();
|
||||
@@ -3145,6 +3153,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("enable_tower_interface_cooldown_during_tower", "multimaterial_settings_prime_tower");
|
||||
optgroup->append_single_option_line("prime_tower_enable_framework", "multimaterial_settings_prime_tower");
|
||||
optgroup->append_single_option_line("prime_tower_width", "multimaterial_settings_prime_tower#width");
|
||||
optgroup->append_single_option_line("belt_purge_tower_width", "multimaterial_settings_prime_tower#belt-purge-tower-width");
|
||||
optgroup->append_single_option_line("prime_volume", "multimaterial_settings_prime_tower");
|
||||
optgroup->append_single_option_line("prime_tower_brim_width", "multimaterial_settings_prime_tower#brim-width");
|
||||
optgroup->append_single_option_line("prime_tower_infill_gap", "multimaterial_settings_prime_tower");
|
||||
@@ -3210,6 +3219,8 @@ void TabPrint::build()
|
||||
optgroup = page->new_optgroup(L("Brim"), L"param_adhension");
|
||||
optgroup->append_single_option_line("brim_type", "others_settings_brim#type");
|
||||
optgroup->append_single_option_line("brim_width", "others_settings_brim#width");
|
||||
optgroup->append_single_option_line("leading_brim_length", "others_settings_brim#leading-length");
|
||||
optgroup->append_single_option_line("extra_brim_width", "others_settings_brim#extra-width");
|
||||
optgroup->append_single_option_line("brim_object_gap", "others_settings_brim#brim-object-gap");
|
||||
optgroup->append_single_option_line("brim_flow_ratio", "others_settings_brim#brim-flow-ratio");
|
||||
optgroup->append_single_option_line("brim_use_efc_outline", "others_settings_brim#brim-use-efc-outline");
|
||||
@@ -3370,6 +3381,42 @@ void TabPrint::toggle_options()
|
||||
cb->SetValue(n);
|
||||
}
|
||||
|
||||
// "Leading edge only" describes where a part meets a moving belt, so it is offered only
|
||||
// on belt printers. Same pattern as support_style above: the field owns a copy of the
|
||||
// option definition, and Choice maps the combobox selection straight onto that copy's
|
||||
// enum_values, so rewriting both together keeps the mapping correct.
|
||||
field = m_active_page->get_field("brim_type");
|
||||
if (auto choice = dynamic_cast<Choice *>(field)) {
|
||||
bool is_belt_printer = false;
|
||||
if (m_preset_bundle) {
|
||||
const auto *belt_opt = m_preset_bundle->printers.get_edited_preset().config.option<ConfigOptionBool>("belt_printer");
|
||||
if (belt_opt)
|
||||
is_belt_printer = belt_opt->value;
|
||||
}
|
||||
auto def = print_config_def.get("brim_type");
|
||||
const auto current = m_config->opt_enum<BrimType>("brim_type");
|
||||
auto &opt = const_cast<ConfigOptionDef &>(field->m_opt);
|
||||
auto cb = dynamic_cast<ComboBox *>(choice->window);
|
||||
// Keep the entry if it is already selected, so switching to a non-belt
|
||||
// printer cannot leave the control showing a value it does not offer.
|
||||
const bool offer_leading_edge = is_belt_printer || current == btLeadingEdgeOnly;
|
||||
const bool offered = std::find(opt.enum_values.begin(), opt.enum_values.end(), "leading_edge_only") != opt.enum_values.end();
|
||||
if (cb != nullptr && offer_leading_edge != offered) {
|
||||
auto n = cb->GetValue();
|
||||
opt.enum_values.clear();
|
||||
opt.enum_labels.clear();
|
||||
cb->Clear();
|
||||
for (size_t i = 0; i < def->enum_values.size(); ++ i) {
|
||||
if (def->enum_values[i] == "leading_edge_only" && ! offer_leading_edge)
|
||||
continue;
|
||||
opt.enum_values.push_back(def->enum_values[i]);
|
||||
opt.enum_labels.push_back(def->enum_labels[i]);
|
||||
cb->Append(_(def->enum_labels[i]));
|
||||
}
|
||||
cb->SetValue(n);
|
||||
}
|
||||
}
|
||||
|
||||
// BBL printers do not support cone wipe tower
|
||||
field = m_active_page->get_field("wipe_tower_wall_type");
|
||||
if (auto choice = dynamic_cast<Choice*>(field)) {
|
||||
@@ -5234,6 +5281,35 @@ void TabPrinter::build_fff()
|
||||
//option.opt.full_width = true;
|
||||
//optgroup->append_single_option_line(option);
|
||||
optgroup->append_single_option_line("disable_m73", "printer_basic_information_advanced#disable-set-remaining-print-time");
|
||||
|
||||
// Belt printer: dedicated section. Everything except the "Enable belt printing"
|
||||
// checkbox is hidden when belt_printer is off (see TabPrinter::toggle_options).
|
||||
auto belt_og = page->new_optgroup(L("Belt printer"), L"param_advanced");
|
||||
belt_og->append_single_option_line("belt_printer", "printer_basic_information_belt_printer#enable-belt-printing");
|
||||
belt_og->append_single_option_line("belt_printer_infinite_y", "printer_basic_information_belt_printer#infinite-y-axis");
|
||||
// Belt tilt: the sole mesh-side transform and the single source of truth for
|
||||
// the physical tilt (drives bed rendering and support gravity tilt too).
|
||||
// Isometric rotation, no distortion; the back-transform inverts it before the
|
||||
// machine-frame remap. The angle is what a user checks against the machine;
|
||||
// the axis is a profile-level kinematics choice, so it is Develop-only. They
|
||||
// are separate rows because a shared line is shown by its first option's mode.
|
||||
belt_og->append_single_option_line("belt_slice_rotation_angle", "printer_basic_information_belt_printer#tilt-angle");
|
||||
belt_og->append_single_option_line("belt_slice_rotation", "printer_basic_information_belt_printer#tilt-axis");
|
||||
belt_og->append_single_option_line("belt_support_floor_offset", "printer_basic_information_belt_printer#support-floor-z-offset");
|
||||
|
||||
// Machine-frame transform: the shear (cot) + scale (1/sin) that map
|
||||
// Cartesian G-code into the printer's physical machine frame are derived
|
||||
// from the belt tilt angle. Only the post-slice axis remap and the expert
|
||||
// decouple override are exposed here, one option per row.
|
||||
{
|
||||
auto mf = page->new_optgroup(L("Machine frame transforms"), L"param_advanced");
|
||||
mf->append_single_option_line("gcode_remap_x", "printer_basic_information_machine_frame_transforms#g-code-axis-remap");
|
||||
mf->append_single_option_line("gcode_remap_y", "printer_basic_information_machine_frame_transforms#g-code-axis-remap");
|
||||
mf->append_single_option_line("gcode_remap_z", "printer_basic_information_machine_frame_transforms#g-code-axis-remap");
|
||||
mf->append_single_option_line("belt_frame_tilt_decouple", "printer_basic_information_machine_frame_transforms#machine-frame-tilt");
|
||||
mf->append_single_option_line("belt_frame_tilt_angle", "printer_basic_information_machine_frame_transforms#machine-frame-tilt");
|
||||
}
|
||||
|
||||
option = optgroup->get_option("thumbnails");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option, "printer_basic_information_advanced#g-code-thumbnails");
|
||||
@@ -5278,6 +5354,8 @@ void TabPrinter::build_fff()
|
||||
optgroup->append_single_option_line("use_firmware_retraction", "printer_basic_information_advanced#use-firmware-retraction");
|
||||
// optgroup->append_single_option_line("spaghetti_detector");
|
||||
optgroup->append_single_option_line("time_cost", "printer_basic_information_advanced#time-cost");
|
||||
optgroup->append_single_option_line("build_plate_tilt_x", "printer_basic_information_advanced#build-plate-tilt");
|
||||
optgroup->append_single_option_line("build_plate_tilt_y", "printer_basic_information_advanced#build-plate-tilt");
|
||||
|
||||
optgroup = page->new_optgroup(L("Plugin Configuration"), L"param_gcode");
|
||||
optgroup->append_single_option_line("printer_plugin_config_overrides");
|
||||
@@ -5810,6 +5888,12 @@ if (is_marlin_flavor)
|
||||
optgroup->append_single_option_line("tool_change_on_wipe_tower", "printer_multimaterial_wipe_tower#tool-change-on-wipe-tower");
|
||||
optgroup->append_single_option_line("wait_for_temp_on_wipe_tower", "printer_multimaterial_wipe_tower#wait-for-temperature-on-wipe-tower");
|
||||
|
||||
// Orca-Belt: belt printers replace the classic wipe tower with an
|
||||
// auto-generated purge prism; this is its enable (gated to belt printers
|
||||
// in toggle_options()).
|
||||
optgroup = page->new_optgroup(L("Belt purge tower"), "param_tower");
|
||||
optgroup->append_single_option_line("enable_belt_purge_tower", "printer_multimaterial_wipe_tower#belt-purge-tower");
|
||||
|
||||
|
||||
optgroup = page->new_optgroup(L("Single extruder multi-material parameters"), "param_settings");
|
||||
optgroup->append_single_option_line("cooling_tube_retraction", "printer_multimaterial_semm_parameters#cooling-tube-position");
|
||||
@@ -6110,6 +6194,18 @@ if (is_marlin_flavor)
|
||||
// this gets executed after preset is loaded and before GUI fields are updated
|
||||
void TabPrinter::on_preset_loaded()
|
||||
{
|
||||
// R8: reset the belt-tilt transition tracking to reflect the freshly loaded preset WITHOUT
|
||||
// running update_fff()'s reset logic. on_preset_loaded() is called from Tab::load_current_preset()
|
||||
// on every printer preset load, right before update()->update_fff(). Seeding m_was_belt_printer
|
||||
// from the loaded preset's belt_printer flag means a preset switch (belt preset -> non-belt preset)
|
||||
// enters update_fff() with m_was_belt_printer==false, so the belt->off clear branch is skipped and
|
||||
// the newly loaded preset's manual tilt is preserved. An in-place belt toggle does NOT go through
|
||||
// here (only through on_value_change->update), so m_was_belt_printer stays true there and the clear
|
||||
// still fires. Seed m_belt_synced_tilt from the loaded tilt as a safeguard.
|
||||
m_was_belt_printer = m_config->opt_bool("belt_printer");
|
||||
m_belt_synced_tilt_x = m_config->opt_float("build_plate_tilt_x");
|
||||
m_belt_synced_tilt_y = m_config->opt_float("build_plate_tilt_y");
|
||||
|
||||
// Orca
|
||||
//update nozzle_volume_type
|
||||
const Preset& current_printer = m_preset_bundle->printers.get_selected_preset();
|
||||
@@ -6407,6 +6503,39 @@ void TabPrinter::toggle_options()
|
||||
bool gcf_is_marlin_firmware = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == GCodeFlavor::gcfMarlinFirmware;
|
||||
toggle_line("enable_power_loss_recovery", is_BBL_printer || gcf_is_marlin_firmware);
|
||||
|
||||
// Belt printer: show belt-specific settings only when belt_printer is enabled.
|
||||
bool is_belt = m_config->opt_bool("belt_printer");
|
||||
// update_fff() derives build_plate_tilt_{x,y} from the belt tilt on a belt
|
||||
// printer, so an edit here would be overwritten; keep them read-only there.
|
||||
toggle_option("build_plate_tilt_x", !is_belt);
|
||||
toggle_option("build_plate_tilt_y", !is_belt);
|
||||
bool expert_or_above = (m_mode >= comExpert);
|
||||
toggle_line("belt_printer_infinite_y", is_belt);
|
||||
// Belt tilt: the sole mesh-side belt transform (visible by default in belt mode).
|
||||
toggle_line("belt_slice_rotation_angle", is_belt);
|
||||
toggle_line("belt_slice_rotation", is_belt);
|
||||
|
||||
// Remap, back-transform, and global mesh-transforms toggles are gated by belt
|
||||
// mode here; finer mode-based visibility is handled by each option's
|
||||
// ConfigOptionMode in PrintConfig.cpp. The axis remap is Develop-only: a
|
||||
// printer profile sets it once for its kinematics, and a wrong value sends
|
||||
// the gantry outside the machine.
|
||||
for (auto el : {"gcode_remap_x", "gcode_remap_y", "gcode_remap_z"})
|
||||
toggle_line(el, is_belt);
|
||||
|
||||
// Rotation is the only mesh-side belt transform. Gray out its angle when no
|
||||
// rotation axis is selected.
|
||||
auto rot_axis = m_config->option<ConfigOptionEnum<BeltRotationAxis>>("belt_slice_rotation")->value;
|
||||
toggle_option("belt_slice_rotation_angle", is_belt && rot_axis != BeltRotationAxis::None);
|
||||
|
||||
// Machine-frame transform: derived from the belt tilt. Only the expert
|
||||
// decouple override is exposed; its angle is shown only when decoupled.
|
||||
toggle_line("belt_frame_tilt_decouple", is_belt && expert_or_above);
|
||||
toggle_line("belt_frame_tilt_angle",
|
||||
is_belt && expert_or_above && m_config->opt_bool("belt_frame_tilt_decouple"));
|
||||
|
||||
|
||||
toggle_line("belt_support_floor_offset", is_belt);
|
||||
const bool support_parallel_printheads = printer_cfg.opt_bool("support_parallel_printheads");
|
||||
toggle_line("parallel_printheads_count", support_parallel_printheads);
|
||||
|
||||
@@ -6425,8 +6554,14 @@ void TabPrinter::toggle_options()
|
||||
}
|
||||
|
||||
if (m_active_page->title() == L("Multimaterial")) {
|
||||
// Orca-Belt: belt printers use the belt purge tower instead of the classic
|
||||
// wipe tower — show its enable only on belt printers, and hide the classic
|
||||
// wipe-tower fields there (the classic tower's G-code bypasses the belt transform).
|
||||
const bool is_belt_printer = m_config->opt_bool("belt_printer");
|
||||
toggle_line("enable_belt_purge_tower", is_belt_printer);
|
||||
|
||||
const bool supports_wipe_tower_2 = !is_BBL_printer && m_config->opt_enum<WipeTowerType>("wipe_tower_type") == WipeTowerType::Type2;
|
||||
toggle_line("wipe_tower_type", !is_BBL_printer);
|
||||
toggle_line("wipe_tower_type", !is_BBL_printer && !is_belt_printer);
|
||||
// SoftFever: hide specific settings for BBL printer
|
||||
for (auto el : {
|
||||
"enable_filament_ramming",
|
||||
@@ -6759,6 +6894,40 @@ void TabPrinter::update_fff()
|
||||
m_imex_modes_ctrl->load_from_config(*m_config);
|
||||
}
|
||||
|
||||
// Belt printer: auto-sync build_plate_tilt_{x,y} (which drives support gravity tilt)
|
||||
// from the belt slicing rotation, the single source of truth for the physical tilt.
|
||||
// Tilt about X drives tilt_x, tilt about Y drives tilt_y.
|
||||
//
|
||||
// R8: value-guessing (zeroing any tilt matching the dormant belt-derived tilt) wiped a
|
||||
// legitimate manual build_plate_tilt on a non-belt tilted-bed printer, because the belt
|
||||
// defaults (rotation=X, angle=45) make a manual tilt of 45 look belt-derived. Instead we
|
||||
// track the belt->non-belt transition and the exact values belt-sync wrote, and clear the
|
||||
// tilt only on a genuine in-place belt-off toggle, and only if the value is still what
|
||||
// belt-sync last wrote. Preset switches reset the tracking in on_preset_loaded(), so they
|
||||
// never trip the reset.
|
||||
if (m_config->opt_bool("belt_printer")) {
|
||||
auto rot_axis = m_config->option<ConfigOptionEnum<BeltRotationAxis>>("belt_slice_rotation")->value;
|
||||
const auto tilt = BeltTransformPipeline::physical_tilt(
|
||||
rot_axis, m_config->opt_float("belt_slice_rotation_angle"));
|
||||
if (m_config->opt_float("build_plate_tilt_x") != tilt.tilt_x_deg)
|
||||
m_config->set_key_value("build_plate_tilt_x", new ConfigOptionFloat(tilt.tilt_x_deg));
|
||||
if (m_config->opt_float("build_plate_tilt_y") != tilt.tilt_y_deg)
|
||||
m_config->set_key_value("build_plate_tilt_y", new ConfigOptionFloat(tilt.tilt_y_deg));
|
||||
// Remember exactly what belt-sync wrote, so an in-place belt-off toggle can distinguish
|
||||
// a still-belt-derived tilt (safe to clear) from a since-edited manual one (keep).
|
||||
m_belt_synced_tilt_x = tilt.tilt_x_deg;
|
||||
m_belt_synced_tilt_y = tilt.tilt_y_deg;
|
||||
} else if (m_was_belt_printer) {
|
||||
// Genuine in-place belt->off toggle on the same preset (on_preset_loaded() was not called
|
||||
// since the last update, so m_was_belt_printer still reflects belt mode). Clear each axis
|
||||
// only if it still holds the value belt-sync last wrote; a manual override is preserved.
|
||||
if (m_config->opt_float("build_plate_tilt_x") == m_belt_synced_tilt_x)
|
||||
m_config->set_key_value("build_plate_tilt_x", new ConfigOptionFloat(0.));
|
||||
if (m_config->opt_float("build_plate_tilt_y") == m_belt_synced_tilt_y)
|
||||
m_config->set_key_value("build_plate_tilt_y", new ConfigOptionFloat(0.));
|
||||
}
|
||||
m_was_belt_printer = m_config->opt_bool("belt_printer");
|
||||
|
||||
toggle_options();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user