Fix preheat regression bugs (#12438)

Fix preheat regression bugs
revert 769fc137c7
This commit is contained in:
SoftFever
2026-02-23 21:48:11 +08:00
committed by GitHub
parent 872d184860
commit e7d2bbd6a9

View File

@@ -760,23 +760,11 @@ public:
}
}
const std::string& line_at(size_t idx) const
{
return m_lines[idx].line;
}
size_t lines_size() const
{
return m_lines.size();
}
// Insert the gcode lines required by the command cmd by backtracing into the cache
bool insert_lines(const Backtrace& backtrace,
void insert_lines(const Backtrace& backtrace,
const std::string& cmd,
std::function<std::string(unsigned int, const std::vector<float>&)> line_inserter,
std::function<std::string(const std::string&)> line_replacer,
std::function<bool(size_t)> allow_insert = nullptr,
bool force_insert_last = false)
std::function<std::string(const std::string&)> line_replacer)
{
// Orca: find start pos by seaching G28/G29/PRINT_START/START_PRINT commands
auto is_start_pos = [](const std::string& curr_cmd) {
@@ -787,21 +775,6 @@ public:
const float time_step = backtrace.time_step();
size_t rev_it_dist = 0; // distance from the end of the cache of the starting point of the backtrace
float last_time_insertion = 0.0f; // used to avoid inserting two lines at the same time
auto inside_toolchange_block = [this](size_t idx) -> bool {
if (m_lines.empty() || idx >= m_lines.size())
return false;
// Find last START/END marker before or at idx; inside if last marker is START.
for (size_t i = idx + 1; i-- > 0;) {
const std::string &line = m_lines[i].line;
if (line.find("CP TOOLCHANGE START") != std::string::npos)
return true;
if (line.find("CP TOOLCHANGE END") != std::string::npos)
return false;
}
return false;
};
bool inserted = false;
for (int i = 0; i < backtrace.steps; ++i) {
const float backtrace_time_i = (i + 1) * time_step;
const float time_threshold_i = m_times[Normal] - backtrace_time_i;
@@ -823,23 +796,6 @@ public:
// insert the line for the current step
if (rev_it != m_lines.rend() && rev_it != start_rev_it && rev_it->times[Normal] != last_time_insertion) {
// Avoid inserting inside wipe-tower toolchange blocks.
// If the selected point is inside a block, move to the nearest
// earlier line outside the block instead of dropping preheat.
size_t idx = m_lines.size() - 1 - size_t(std::distance(m_lines.rbegin(), rev_it));
if (inside_toolchange_block(idx)) {
size_t adjusted_idx = idx;
while (adjusted_idx > 0 && inside_toolchange_block(adjusted_idx))
--adjusted_idx;
if (inside_toolchange_block(adjusted_idx))
continue;
const size_t adjusted_rev_dist = m_lines.size() - 1 - adjusted_idx;
rev_it = m_lines.rbegin() + adjusted_rev_dist;
idx = adjusted_idx;
}
if (allow_insert && !allow_insert(idx)) {
continue;
}
last_time_insertion = rev_it->times[Normal];
std::vector<float> time_diffs;
time_diffs.push_back(m_times[Normal] - last_time_insertion);
@@ -858,39 +814,8 @@ public:
}
++m_added_lines_counter;
inserted = true;
}
}
if (!inserted && force_insert_last) {
for (size_t idx = 0; idx < m_lines.size(); ++idx) {
if (inside_toolchange_block(idx))
continue;
if (allow_insert && !allow_insert(idx))
continue;
const LineData &data = m_lines[idx];
std::vector<float> time_diffs;
time_diffs.push_back(m_times[Normal] - data.times[Normal]);
if (!m_machines[Stealth].g1_times_cache.empty())
time_diffs.push_back(m_times[Stealth] - data.times[Stealth]);
const std::string out_line = line_inserter(1, time_diffs);
const size_t rev_it_dist = m_lines.size() - idx;
m_lines.insert(m_lines.begin() + idx, {out_line, data.times});
#ifndef NDEBUG
m_statistics.add_line(out_line.length());
#endif // NDEBUG
m_size += out_line.length();
for (auto map_it = m_gcode_lines_map.rbegin(); map_it != m_gcode_lines_map.rbegin() + rev_it_dist - 1; ++map_it) {
++map_it->second;
}
++m_added_lines_counter;
inserted = true;
break;
}
}
return inserted;
}
// write to file:
@@ -1329,169 +1254,12 @@ void GCodeProcessor::run_post_process()
if (m_print != nullptr)
m_print->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, warning);
}
int override_temp = -1;
{
const size_t line_count = export_line.lines_size();
if (line_count > 0) {
size_t start_idx = 0;
bool in_block = false;
for (size_t i = line_count; i-- > 0;) {
const std::string &line = export_line.line_at(i);
if (line.find("CP TOOLCHANGE END") != std::string::npos)
break;
if (line.find("CP TOOLCHANGE START") != std::string::npos) {
start_idx = i;
in_block = true;
break;
}
}
if (in_block) {
int base_temp = int(m_layer_id != 1 ? m_filament_nozzle_temp[tool_number] :
m_filament_nozzle_temp_first_layer[tool_number]);
for (size_t i = start_idx; i < line_count; ++i) {
const std::string &line = export_line.line_at(i);
if (GCodeReader::GCodeLine::cmd_is(line, "M109")) {
GCodeReader::GCodeLine gline;
GCodeReader reader;
reader.parse_line(line, [&gline](GCodeReader& reader, const GCodeReader::GCodeLine& l) { gline = l; });
float s_val = 0.f;
if (gline.has_value('S', s_val)) {
float t_val = -1.f;
if (gline.has_value('T', t_val)) {
if (int(t_val) != tool_number)
continue;
}
int temp = int(std::round(s_val));
if (temp != base_temp)
override_temp = temp;
}
}
}
}
}
}
// Disallow inserting preheat before the last switch away from this tool.
size_t min_insert_idx = 0;
{
const size_t line_count = export_line.lines_size();
if (line_count > 0) {
for (size_t i = line_count; i-- > 0;) {
const std::string &line = export_line.line_at(i);
std::string cmd = GCodeReader::GCodeLine::extract_cmd(line);
if (cmd.empty())
continue;
if (cmd[0] == 'T') {
unsigned int id = 0;
auto ret = std::from_chars(cmd.data() + 1, cmd.data() + cmd.size(), id);
if (ret.ec == std::errc()) {
if (static_cast<int>(id) != tool_number) {
min_insert_idx = i;
break;
}
}
} else if (cmd == "M1020") {
size_t pos = line.find("S");
if (pos != std::string::npos) {
size_t start = pos + 1;
size_t end = line.find_first_not_of("0123456789", start);
const std::string val = line.substr(start, end == std::string::npos ? std::string::npos : end - start);
if (!val.empty()) {
try {
if (std::stoi(val) != tool_number) {
min_insert_idx = i;
break;
}
} catch (...) {
}
}
}
}
}
}
}
auto allow_insert = [&export_line, tool_number, min_insert_idx](size_t idx) -> bool {
if (idx <= min_insert_idx)
return false;
// Do not insert preheat for a tool that is already active at the insertion point.
const size_t line_count = export_line.lines_size();
if (idx >= line_count)
return true;
for (size_t i = idx + 1; i-- > 0;) {
const std::string &line = export_line.line_at(i);
std::string cmd = GCodeReader::GCodeLine::extract_cmd(line);
if (cmd.empty())
continue;
if (cmd[0] == 'T') {
unsigned int id = 0;
auto ret = std::from_chars(cmd.data() + 1, cmd.data() + cmd.size(), id);
if (ret.ec == std::errc()) {
return static_cast<int>(id) != tool_number;
}
} else if (cmd == "M1020") {
size_t pos = line.find("S");
if (pos != std::string::npos) {
size_t start = pos + 1;
size_t end = line.find_first_not_of("0123456789", start);
const std::string val = line.substr(start, end == std::string::npos ? std::string::npos : end - start);
if (!val.empty()) {
try {
return std::stoi(val) != tool_number;
} catch (...) {
return true;
}
}
}
}
}
return true;
};
// Skip preheat insertion if this T command doesn't change the active tool.
{
const size_t line_count = export_line.lines_size();
if (line_count > 0) {
int last_tool = -1;
for (size_t i = line_count; i-- > 0;) {
const std::string &line = export_line.line_at(i);
std::string cmd = GCodeReader::GCodeLine::extract_cmd(line);
if (cmd.empty())
continue;
if (cmd[0] == 'T') {
unsigned int id = 0;
auto ret = std::from_chars(cmd.data() + 1, cmd.data() + cmd.size(), id);
if (ret.ec == std::errc()) {
last_tool = static_cast<int>(id);
break;
}
} else if (cmd == "M1020") {
size_t pos = line.find("S");
if (pos != std::string::npos) {
size_t start = pos + 1;
size_t end = line.find_first_not_of("0123456789", start);
const std::string val = line.substr(start, end == std::string::npos ? std::string::npos : end - start);
if (!val.empty()) {
try {
last_tool = std::stoi(val);
break;
} catch (...) {
}
}
}
}
}
if (last_tool != -1 && last_tool == tool_number)
return;
}
}
export_line.insert_lines(
backtrace, cmd,
// line inserter
[tool_number, override_temp, this](unsigned int id, const std::vector<float>& time_diffs) {
const int base_temperature = int(m_layer_id != 1 ? m_filament_nozzle_temp[tool_number] :
[tool_number, this](unsigned int id, const std::vector<float>& time_diffs) {
const int temperature = int(m_layer_id != 1 ? m_filament_nozzle_temp[tool_number] :
m_filament_nozzle_temp_first_layer[tool_number]);
const int temperature = override_temp > 0 ? override_temp : base_temperature;
// Orca: M104.1 for XL printers, I can't find the documentation for this so I copied the C++ comments from
// Prusa-Firmware-Buddy here
/**
@@ -1534,11 +1302,7 @@ void GCodeProcessor::run_post_process()
}
}
return line;
},
allow_insert,
// If backtracing can't find a valid insertion point (e.g. dense recurring toolchanges),
// still force one at the earliest allowed line after the last switch-away point.
true
}
);
}
}