mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-04 14:20:58 +00:00
Apply per-variant cooling, ramming and temperature range on nozzle-rack slices
Fan speeds, multi-tool ramming, the tower interface and flush temperature fallbacks and the custom G-code placeholders now use the extruder variant a filament prints with on each layer, instead of reading by filament id.
This commit is contained in:
@@ -308,8 +308,8 @@ DynamicPrintConfig slice_config(PresetBundle &bundle)
|
||||
// type (Direct Drive + Bowden) the mismatched lookup spams [error] lines. Single-nozzle and non-BBL
|
||||
// printers keep the default map (their toolchange rides the AMS/tool-changer path unchanged).
|
||||
const bool pin_filament_map = bundle.is_bbl_vendor() && nozzles > 1;
|
||||
auto &fmap = bundle.project_config.option<ConfigOptionInts>("filament_map", true)->values;
|
||||
if (pin_filament_map) {
|
||||
auto &fmap = bundle.project_config.option<ConfigOptionInts>("filament_map", true)->values;
|
||||
for (size_t i = 0; i < fmap.size(); ++i)
|
||||
fmap[i] = int(i % nozzles) + 1;
|
||||
}
|
||||
@@ -317,9 +317,8 @@ DynamicPrintConfig slice_config(PresetBundle &bundle)
|
||||
// A fresh printer selection uses its declared nozzle volumes, just like the
|
||||
// app. Otherwise a high-flow preset is silently sliced with Standard tuning.
|
||||
bundle.reset_default_nozzle_volume_type();
|
||||
auto &filament_map = bundle.project_config.option<ConfigOptionInts>("filament_map", true)->values;
|
||||
bundle.project_config.option<ConfigOptionInts>("filament_volume_map", true)->values =
|
||||
bundle.get_default_nozzle_volume_types_for_filaments(filament_map);
|
||||
bundle.get_default_nozzle_volume_types_for_filaments(fmap);
|
||||
|
||||
DynamicPrintConfig cfg = bundle.full_config();
|
||||
cfg.set_key_value("enable_prime_tower", new ConfigOptionBool(true)); // force a purge tower so the change is detectable
|
||||
|
||||
+27
-8
@@ -1258,7 +1258,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
config.set_key_value("old_filament_temp", new ConfigOptionInt(old_filament_temp));
|
||||
int interface_temp = full_config.filament_tower_interface_print_temp.get_at(new_filament_id);
|
||||
if (interface_temp == -1)
|
||||
interface_temp = full_config.nozzle_temperature_range_high.get_at(new_filament_id);
|
||||
interface_temp = full_config.nozzle_temperature_range_high.get_at(new_fi);
|
||||
if (full_config.enable_tower_interface_features && tcr.is_contact)
|
||||
new_filament_temp = interface_temp;
|
||||
config.set_key_value("new_filament_temp", new ConfigOptionInt(new_filament_temp));
|
||||
@@ -1309,7 +1309,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
flush_temps[idx] = use_fast_flush ? m_print_config->filament_flush_temp_fast.get_at(fi)
|
||||
: m_print_config->filament_flush_temp.get_at(fi);
|
||||
if (flush_temps[idx] == 0)
|
||||
flush_temps[idx] = m_print_config->nozzle_temperature_range_high.get_at(idx);
|
||||
flush_temps[idx] = m_print_config->nozzle_temperature_range_high.get_at(fi);
|
||||
filament_cooling_before_tower[idx] = m_print_config->filament_cooling_before_tower.get_at(fi);
|
||||
}
|
||||
if (tcr.is_contact || gcodegen.m_layer_index == 0)
|
||||
@@ -1563,7 +1563,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
const bool will_go_down = !is_approx(z, current_z);
|
||||
const bool is_ramming = (gcodegen.config().single_extruder_multi_material) ||
|
||||
(!gcodegen.config().single_extruder_multi_material &&
|
||||
gcodegen.config().filament_multitool_ramming.get_at(tcr.initial_tool));
|
||||
gcodegen.config().filament_multitool_ramming.get_at(gcodegen.get_filament_config_index(tcr.initial_tool)));
|
||||
// Orca: user-facing override (Printer Settings > Wipe tower > "Tool change on wipe tower").
|
||||
// Forces the toolhead to travel over the wipe tower before issuing Tx even on multi-toolhead
|
||||
// printers without ramming, where Orca would otherwise emit Tx in place (potentially over the part).
|
||||
@@ -1620,7 +1620,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
if (gcodegen.config().enable_tower_interface_features && tcr.is_contact) {
|
||||
interface_temp = gcodegen.config().filament_tower_interface_print_temp.get_at(new_extruder_id);
|
||||
if (interface_temp == -1)
|
||||
interface_temp = gcodegen.config().nozzle_temperature_range_high.get_at(new_extruder_id);
|
||||
interface_temp = gcodegen.config().nozzle_temperature_range_high.get_at(gcodegen.get_filament_config_index(new_extruder_id));
|
||||
toolchange_temp_override = interface_temp;
|
||||
}
|
||||
toolchange_gcode_str = gcodegen.set_extruder(new_extruder_id, tcr.print_z, false, toolchange_temp_override,
|
||||
@@ -4342,6 +4342,12 @@ size_t GCode::get_filament_config_index(int filament_id) const
|
||||
return filament_id;
|
||||
}
|
||||
|
||||
size_t GCode::get_filament_config_index(int filament_id, size_t layer_id) const
|
||||
{
|
||||
// Orca: uncached, as the stages after the generator run concurrently with it.
|
||||
return m_print ? m_print->get_filament_config_indx(filament_id, (int) layer_id, false) : filament_id;
|
||||
}
|
||||
|
||||
size_t GCode::get_nozzle_config_index(int filament_id) const
|
||||
{
|
||||
if (m_print) {
|
||||
@@ -9409,10 +9415,13 @@ void GCode::update_placeholder_parser_with_variant_params()
|
||||
|
||||
// Helper: remap config arrays from variant index space to filament_id index space.
|
||||
// After remapping, gcode templates can use param[filament_id] directly.
|
||||
std::vector<size_t> config_index(num_filaments);
|
||||
for (size_t i = 0; i < num_filaments; ++i)
|
||||
config_index[i] = get_filament_config_index(i);
|
||||
auto remap_by_filament = [&](const auto &src) {
|
||||
std::decay_t<decltype(src.values)> dst(num_filaments);
|
||||
for (size_t i = 0; i < num_filaments; ++i)
|
||||
dst[i] = src.get_at(get_filament_config_index(i));
|
||||
dst[i] = src.get_at(config_index[i]);
|
||||
return dst;
|
||||
};
|
||||
|
||||
@@ -9427,6 +9436,16 @@ void GCode::update_placeholder_parser_with_variant_params()
|
||||
this->placeholder_parser().set("first_layer_temperature", new ConfigOptionInts(remap_by_filament(m_config.nozzle_temperature_initial_layer)));
|
||||
this->placeholder_parser().set("pressure_advance", new ConfigOptionFloats(remap_by_filament(m_config.pressure_advance)));
|
||||
this->placeholder_parser().set("enable_pressure_advance", new ConfigOptionBools(remap_by_filament(m_config.enable_pressure_advance)));
|
||||
this->placeholder_parser().set("fan_min_speed", new ConfigOptionFloats(remap_by_filament(m_config.fan_min_speed)));
|
||||
this->placeholder_parser().set("fan_max_speed", new ConfigOptionFloats(remap_by_filament(m_config.fan_max_speed)));
|
||||
this->placeholder_parser().set("additional_cooling_fan_speed", new ConfigOptionInts(remap_by_filament(m_config.additional_cooling_fan_speed)));
|
||||
this->placeholder_parser().set("filament_minimal_purge_on_wipe_tower", new ConfigOptionFloats(remap_by_filament(m_config.filament_minimal_purge_on_wipe_tower)));
|
||||
this->placeholder_parser().set("filament_multitool_ramming", new ConfigOptionBools(remap_by_filament(m_config.filament_multitool_ramming)));
|
||||
this->placeholder_parser().set("filament_multitool_ramming_volume", new ConfigOptionFloats(remap_by_filament(m_config.filament_multitool_ramming_volume)));
|
||||
this->placeholder_parser().set("filament_multitool_ramming_flow", new ConfigOptionFloats(remap_by_filament(m_config.filament_multitool_ramming_flow)));
|
||||
this->placeholder_parser().set("nozzle_temperature_range_low", new ConfigOptionInts(remap_by_filament(m_config.nozzle_temperature_range_low)));
|
||||
const auto nozzle_temperature_range_high = remap_by_filament(m_config.nozzle_temperature_range_high);
|
||||
this->placeholder_parser().set("nozzle_temperature_range_high", new ConfigOptionInts(nozzle_temperature_range_high));
|
||||
|
||||
// --- printer_options_with_variant_1: in m_config these are already merged as filament-indexed ---
|
||||
this->placeholder_parser().set("retraction_distances_when_cut", new ConfigOptionFloats(remap_by_filament(m_config.retraction_distances_when_cut)));
|
||||
@@ -9447,7 +9466,7 @@ void GCode::update_placeholder_parser_with_variant_params()
|
||||
if (flush_v_speed[i] == 0)
|
||||
flush_v_speed[i] = filament_max_v[i];
|
||||
if (flush_temps[i] == 0)
|
||||
flush_temps[i] = m_config.nozzle_temperature_range_high.get_at(i);
|
||||
flush_temps[i] = nozzle_temperature_range_high[i];
|
||||
}
|
||||
this->placeholder_parser().set("flush_volumetric_speeds", new ConfigOptionFloats(flush_v_speed));
|
||||
this->placeholder_parser().set("flush_temperatures", new ConfigOptionInts(flush_temps));
|
||||
@@ -9706,7 +9725,7 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
{
|
||||
int interface_temp = m_config.filament_tower_interface_print_temp.get_at(new_filament_id);
|
||||
if (interface_temp == -1)
|
||||
interface_temp = m_config.nozzle_temperature_range_high.get_at(new_filament_id);
|
||||
interface_temp = m_config.nozzle_temperature_range_high.get_at(new_fi);
|
||||
dyn_config.set_key_value("filament_tower_interface_print_temp", new ConfigOptionInt(interface_temp));
|
||||
}
|
||||
if (toolchange_temp_override > 0) {
|
||||
@@ -9745,7 +9764,7 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
|
||||
flush_temps[idx] = use_fast_flush ? m_print->config().filament_flush_temp_fast.get_at(fi)
|
||||
: m_print->config().filament_flush_temp.get_at(fi);
|
||||
if (flush_temps[idx] == 0)
|
||||
flush_temps[idx] = m_print->config().nozzle_temperature_range_high.get_at(idx);
|
||||
flush_temps[idx] = m_print->config().nozzle_temperature_range_high.get_at(fi);
|
||||
filament_cooling_before_tower[idx] = m_print->config().filament_cooling_before_tower.get_at(fi);
|
||||
}
|
||||
std::fill(filament_cooling_before_tower.begin(), filament_cooling_before_tower.end(), 0);
|
||||
|
||||
@@ -296,6 +296,9 @@ public:
|
||||
// resolver keys filament-indexed arrays, the nozzle resolver keys (extruder x volume-type)
|
||||
// slot arrays. Both degenerate to filament_id / extruder index on single-volume printers.
|
||||
size_t get_filament_config_index(int filament_id) const;
|
||||
// The filament resolver for a given layer, for the export pipeline stages after the generator,
|
||||
// which run behind the current layer and concurrently with the generator.
|
||||
size_t get_filament_config_index(int filament_id, size_t layer_id) const;
|
||||
size_t get_nozzle_config_index(int filament_id) const;
|
||||
|
||||
// Object and support extrusions of the same PrintObject at the same print_z.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_config(gcodegen.config()), m_toolchange_prefix(gcodegen.writer().toolchange_prefix()), m_current_extruder(0), m_current_nozzle(0)
|
||||
CoolingBuffer::CoolingBuffer(GCode &gcodegen) : m_config(gcodegen.config()), m_gcodegen(gcodegen), m_toolchange_prefix(gcodegen.writer().toolchange_prefix()), m_current_extruder(0), m_current_nozzle(0)
|
||||
{
|
||||
this->reset(gcodegen.writer().get_position());
|
||||
|
||||
@@ -737,10 +737,12 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
||||
&ironing_fan_control, &ironing_fan_speed
|
||||
](bool immediately_apply) {
|
||||
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
|
||||
float fan_min_speed = EXTRUDER_CONFIG(fan_min_speed);
|
||||
// The per-variant options take the extruder variant the filament prints with on this layer
|
||||
const size_t config_index = m_gcodegen.get_filament_config_index(m_current_extruder, layer_id);
|
||||
float fan_min_speed = m_config.fan_min_speed.get_at(config_index);
|
||||
float fan_speed_new = EXTRUDER_CONFIG(reduce_fan_stop_start_freq) ? fan_min_speed : 0;
|
||||
//BBS
|
||||
int additional_fan_speed_new = EXTRUDER_CONFIG(additional_cooling_fan_speed);
|
||||
int additional_fan_speed_new = m_config.additional_cooling_fan_speed.get_at(config_index);
|
||||
int close_fan_the_first_x_layers = EXTRUDER_CONFIG(close_fan_the_first_x_layers);
|
||||
// Is the fan speed ramp enabled?
|
||||
int full_fan_speed_layer = EXTRUDER_CONFIG(full_fan_speed_layer);
|
||||
@@ -776,7 +778,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
||||
// additional_fan_speed_new is left at its configured value (auxiliary fan is independent of the
|
||||
// part-cooling override).
|
||||
} else if (int(layer_id) >= close_fan_the_first_x_layers) {
|
||||
float fan_max_speed = EXTRUDER_CONFIG(fan_max_speed);
|
||||
float fan_max_speed = m_config.fan_max_speed.get_at(config_index);
|
||||
float slow_down_layer_time = float(EXTRUDER_CONFIG(slow_down_layer_time));
|
||||
float fan_cooling_layer_time = float(EXTRUDER_CONFIG(fan_cooling_layer_time));
|
||||
//BBS: always enable the fan speed interpolation according to layer time
|
||||
|
||||
@@ -54,6 +54,8 @@ private:
|
||||
// Referencs GCode::m_config, which is FullPrintConfig. While the PrintObjectConfig slice of FullPrintConfig is being modified,
|
||||
// the PrintConfig slice of FullPrintConfig is constant, thus no thread synchronization is required.
|
||||
const PrintConfig &m_config;
|
||||
// Resolves the filament config index of the per-variant options.
|
||||
const GCode &m_gcodegen;
|
||||
unsigned int m_current_extruder;
|
||||
unsigned int m_current_nozzle;
|
||||
//BBS: current fan speed
|
||||
|
||||
@@ -1230,15 +1230,21 @@ void ToolOrdering::cal_most_used_extruder(const PrintConfig &config)
|
||||
|
||||
float ToolOrdering::cal_max_additional_fan(const PrintConfig &config)
|
||||
{
|
||||
// record
|
||||
std::set<unsigned int> used_filaments;
|
||||
for (const LayerTools &layer_tools : m_layer_tools)
|
||||
used_filaments.insert(layer_tools.extruders.begin(), layer_tools.extruders.end());
|
||||
if (used_filaments.empty())
|
||||
return 0;
|
||||
|
||||
// Orca: additional_cooling_fan_speed can hold one value per extruder variant a filament prints with;
|
||||
// filament_self_index maps such a column to its filament.
|
||||
const std::vector<int> &self_index = config.filament_self_index.values;
|
||||
const size_t columns = std::max(config.additional_cooling_fan_speed.size(), size_t(*used_filaments.rbegin()) + 1);
|
||||
float max_fan = 0;
|
||||
for (LayerTools &layer_tools : m_layer_tools) {
|
||||
std::vector<unsigned int> filaments = layer_tools.extruders;
|
||||
std::set<int> layer_extruder_count;
|
||||
// count once only
|
||||
for (unsigned int &filament : filaments)
|
||||
if (max_fan < config.additional_cooling_fan_speed.get_at(filament))
|
||||
max_fan = config.additional_cooling_fan_speed.get_at(filament);
|
||||
for (size_t column = 0; column < columns; ++column) {
|
||||
const unsigned int filament_id = self_index.size() == columns ? self_index[column] - 1 : column;
|
||||
if (used_filaments.count(filament_id) && max_fan < config.additional_cooling_fan_speed.get_at(column))
|
||||
max_fan = config.additional_cooling_fan_speed.get_at(column);
|
||||
}
|
||||
return max_fan;
|
||||
}
|
||||
|
||||
+11
-8
@@ -4329,9 +4329,9 @@ bool Print::is_dynamic_group_reorder() const
|
||||
return true;
|
||||
}
|
||||
|
||||
int Print::get_filament_config_indx(int filament_id, int layer_id)
|
||||
int Print::get_filament_config_indx(int filament_id, int layer_id, bool use_cache)
|
||||
{
|
||||
return get_config_index(filament_id, layer_id, m_config.filament_extruder_variant.values, m_filament_self_index, m_filament_index_map);
|
||||
return get_config_index(filament_id, layer_id, m_config.filament_extruder_variant.values, m_filament_self_index, use_cache ? &m_filament_index_map : nullptr);
|
||||
}
|
||||
|
||||
void Print::update_filament_self_index_cache()
|
||||
@@ -4374,7 +4374,7 @@ int Print::get_nozzle_config_index(int filament_id, int layer_id)
|
||||
return get_config_index(filament_id, layer_id, m_default_region_config.print_extruder_variant.values, m_default_region_config.print_extruder_id.values, m_nozzle_index_map);
|
||||
}
|
||||
|
||||
int Print::get_config_index(int filament_id, int layer_id, const std::vector<std::string> &variant_list, const std::vector<int>& self_index_list, FilamentIndexMap &index_map)
|
||||
int Print::get_config_index(int filament_id, int layer_id, const std::vector<std::string> &variant_list, const std::vector<int>& self_index_list, FilamentIndexMap *index_map)
|
||||
{
|
||||
auto group_result = get_layered_nozzle_group_result();
|
||||
// Orca: defensive — when no grouping producer has published a result yet, fall back to the
|
||||
@@ -4385,7 +4385,8 @@ int Print::get_config_index(int filament_id, int layer_id, const std::vector<std
|
||||
if (!nozzle_info.has_value()) {
|
||||
// Orca: this fallback runs per-filament/per-layer in the g-code hot path — log once per filament
|
||||
// (reset each slice) instead of flooding thousands of identical lines that bury the real error.
|
||||
if (m_missing_nozzle_group_logged.insert(filament_id).second)
|
||||
// Without the cache, the log set is left alone too; the cached caller reports the same filament.
|
||||
if (index_map && m_missing_nozzle_group_logged.insert(filament_id).second)
|
||||
BOOST_LOG_TRIVIAL(error) << __FUNCTION__
|
||||
<< boost::format(", Line %1%: could not found group_nozzle_info corresponding to filament_id %2%, layer_id %3% (further occurrences for this filament suppressed)") % __LINE__ % filament_id %
|
||||
layer_id;
|
||||
@@ -4394,15 +4395,17 @@ int Print::get_config_index(int filament_id, int layer_id, const std::vector<std
|
||||
|
||||
ExtruderType extruder_type = ExtruderType(m_config.extruder_type.get_at(nozzle_info->extruder_id));
|
||||
NozzleVolumeType nozzle_volume_type = nozzle_info->volume_type;
|
||||
if (!index_map)
|
||||
return get_config_index_base(nozzle_volume_type, extruder_type, filament_id + 1, variant_list, self_index_list);
|
||||
|
||||
FilamentIndexKey key{filament_id, extruder_type, nozzle_volume_type};
|
||||
auto iter = index_map.find(key);
|
||||
if (iter == index_map.end()) {
|
||||
auto iter = index_map->find(key);
|
||||
if (iter == index_map->end()) {
|
||||
int index = get_config_index_base(nozzle_volume_type, extruder_type, filament_id + 1, variant_list, self_index_list);
|
||||
index_map[key] = index;
|
||||
(*index_map)[key] = index;
|
||||
return index;
|
||||
} else {
|
||||
return index_map[key];
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1222,7 +1222,9 @@ public:
|
||||
|
||||
// Post-slicing config-slot resolvers: map a (filament, layer) pair to the index of its
|
||||
// per-(extruder x volume type) column in the expanded variant arrays, cached by grouping context.
|
||||
int get_filament_config_indx(int filament_id, int layer_id);
|
||||
// Orca: without use_cache, the filament resolver leaves the cache alone, for the G-code export
|
||||
// pipeline's cooling stage, which runs concurrently with the generator stage filling it.
|
||||
int get_filament_config_indx(int filament_id, int layer_id, bool use_cache = true);
|
||||
int get_nozzle_config_index(int filament_id, int layer_id);
|
||||
|
||||
// Orca: Implement prusa's filament shrink compensation approach
|
||||
@@ -1282,7 +1284,7 @@ protected:
|
||||
};
|
||||
using FilamentIndexMap = std::unordered_map<FilamentIndexKey, int, FilamentIndexKeyHash>;
|
||||
using PrintIndexMap = std::unordered_map<PrintIndexKey, int, PrintIndexKeyHash>;
|
||||
int get_config_index(int filament_id, int layer_id, const std::vector<std::string> &variant_list, const std::vector<int>& self_index_list, FilamentIndexMap &index_map);
|
||||
int get_config_index(int filament_id, int layer_id, const std::vector<std::string> &variant_list, const std::vector<int>& self_index_list, FilamentIndexMap *index_map);
|
||||
int get_config_index(int filament_id, int layer_id, const std::vector<std::string> &variant_list, const std::vector<int>& self_index_list, PrintIndexMap &index_map);
|
||||
|
||||
// Invalidates the step, and its depending steps in Print.
|
||||
|
||||
@@ -9463,17 +9463,6 @@ std::set<std::string> print_options_with_variant = {
|
||||
std::set<std::string> filament_options_with_variant = {
|
||||
"filament_flow_ratio",
|
||||
"filament_max_volumetric_speed",
|
||||
"enable_pressure_advance",
|
||||
"pressure_advance",
|
||||
"fan_min_speed",
|
||||
"fan_max_speed",
|
||||
"additional_cooling_fan_speed",
|
||||
"filament_minimal_purge_on_wipe_tower",
|
||||
"filament_multitool_ramming",
|
||||
"filament_multitool_ramming_volume",
|
||||
"filament_multitool_ramming_flow",
|
||||
"nozzle_temperature_range_low",
|
||||
"nozzle_temperature_range_high",
|
||||
// Per-variant ramming / pre-cooling / nozzle-change filament overrides
|
||||
"filament_ramming_volumetric_speed",
|
||||
"filament_pre_cooling_temperature",
|
||||
@@ -9527,6 +9516,16 @@ std::set<std::string> filament_options_with_variant = {
|
||||
"adaptive_pressure_advance_model",
|
||||
"adaptive_pressure_advance_overhangs",
|
||||
"adaptive_pressure_advance_bridges",
|
||||
// Orca: cooling fans, multi-tool ramming and recommended nozzle temperature range
|
||||
"fan_min_speed",
|
||||
"fan_max_speed",
|
||||
"additional_cooling_fan_speed",
|
||||
"filament_minimal_purge_on_wipe_tower",
|
||||
"filament_multitool_ramming",
|
||||
"filament_multitool_ramming_volume",
|
||||
"filament_multitool_ramming_flow",
|
||||
"nozzle_temperature_range_low",
|
||||
"nozzle_temperature_range_high",
|
||||
"activate_air_filtration",
|
||||
"activate_air_filtration_during_print",
|
||||
"activate_air_filtration_on_completion",
|
||||
|
||||
Reference in New Issue
Block a user