mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-06 07:11:10 +00:00
* Add Missing Includes Across src/libslic3r Every libslic3r source and header now directly includes the headers declaring what it uses, rather than relying on the precompiled header or transitive includes. Generated with clang-tidy misc-include-cleaner, with libslic3r headers spelled libslic3r/... so they resolve outside the library's private include paths. MultiMaterialSegmentation.hpp, Support/SupportParameters.hpp and Format/STEP.hpp are made self-contained by hand. * Make the libslic3r Headers Compile on Their Own Each now includes, or forward-declares, what it uses instead of relying on what its includers happened to include first. Left out: I18N.hpp, which errors on purpose when included from GUI code, and VoxelizeCSGMesh.hpp and SLA/bicubic.h, which nothing includes and which no longer compile at all. * Add the Includes Missing From the Hand-Fixed libslic3r Headers clang-tidy would not edit these headers while they failed to compile on their own, so the first pass skipped them. With the headers now self-contained, a second pass adds the rest. * Keep Windows Setup Ahead of the Added libslic3r Includes Print.cpp and Thread.cpp open with a _WIN32 block that has to come first; without the precompiled header, Print.cpp otherwise reaches windows.h through OCCT with NONLS defined and boost/regex fails. OpenVDBUtils.cpp and SLA/SupportTreeBuilder.cpp had includes inside #ifndef NOMINMAX, which libslic3r defines on Windows, so those were skipped there. .clang-tidy also ignores the MSVC STL and UCRT internals, Boost.Multiprecision's fwd.hpp and CPython's Windows include directory. * Re-Add libslic3r Includes After the Clipper2 2.0.1 Migration Rebasing onto main took main's version of the files the Clipper2 migration rewrote, so their added includes are restored here, along with includes for main's new code. Clipper2's individual headers are now ignored by clang-tidy: they only build the Z variant through clipper2_z.hpp, which defines USINGZ first, so including clipper.core.h and the like directly broke ClipperZUtils.cpp.
540 lines
24 KiB
C++
540 lines
24 KiB
C++
#include "FanMover.hpp"
|
|
|
|
#include "libslic3r/PrintConfig.hpp"
|
|
#include "libslic3r/libslic3r.h"
|
|
#include "libslic3r/ExtrusionEntity.hpp"
|
|
#include "GCodeReader.hpp"
|
|
|
|
#include <cstddef>
|
|
#include <cerrno>
|
|
#include <cstdlib>
|
|
#include <algorithm>
|
|
#include <cstdint>
|
|
#include <cmath>
|
|
#include <cassert>
|
|
#include <cctype>
|
|
#include <iomanip>
|
|
/*
|
|
#include <ios>
|
|
#include <list>
|
|
#include <iterator>
|
|
#include <memory.h>
|
|
#include <sstream>
|
|
#include <string.h>
|
|
#include <float.h>
|
|
|
|
#include "../libslic3r.h"
|
|
#include "../PrintConfig.hpp"
|
|
#include "../Utils.hpp"
|
|
#include "Print.hpp"
|
|
#include "libslic3r/PrintConfig.hpp"
|
|
#include "libslic3r/libslic3r.h"
|
|
|
|
#include <boost/log/trivial.hpp>
|
|
#include <string>
|
|
#include <string_view>
|
|
*/
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
const std::string& FanMover::process_gcode(const std::string& gcode, bool flush)
|
|
{
|
|
m_process_output = "";
|
|
|
|
// recompute buffer time to recover from rounding
|
|
m_buffer_time_size = 0;
|
|
for (auto& data : m_buffer) m_buffer_time_size += data.time;
|
|
|
|
if(!gcode.empty())
|
|
m_parser.parse_buffer(gcode,
|
|
[this](GCodeReader& reader, const GCodeReader::GCodeLine& line) { /*m_process_output += line.raw() + "\n";*/ this->_process_gcode_line(reader, line); });
|
|
|
|
if (flush) {
|
|
while (!m_buffer.empty()) {
|
|
BufferData &front = m_buffer.front();
|
|
m_process_output += front.raw + "\n";
|
|
// Orca: Keep the emitted fan state in sync when flushing buffered fan commands.
|
|
if (front.fan_speed >= 0)
|
|
m_front_buffer_fan_speed = front.fan_speed;
|
|
remove_from_buffer(m_buffer.begin());
|
|
}
|
|
}
|
|
|
|
return m_process_output;
|
|
}
|
|
|
|
bool is_end_of_word(char c) {
|
|
return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0;
|
|
}
|
|
|
|
float get_axis_value(const std::string& line, char axis)
|
|
{
|
|
char match[3] = " X";
|
|
match[1] = axis;
|
|
|
|
size_t pos = line.find(match);
|
|
if (pos == std::string::npos) {
|
|
return NAN;
|
|
}
|
|
pos += 2;
|
|
//size_t end = std::min(line.find(' ', pos + 1), line.find(';', pos + 1));
|
|
// Try to parse the numeric value.
|
|
const char* c = line.c_str();
|
|
char* pend = nullptr;
|
|
errno = 0;
|
|
double v = strtod(c + pos, &pend);
|
|
if (pend != nullptr && errno == 0 && pend != c) {
|
|
// The axis value has been parsed correctly.
|
|
return float(v);
|
|
}
|
|
return NAN;
|
|
}
|
|
|
|
void change_axis_value(std::string& line, char axis, const float new_value, const int decimal_digits)
|
|
{
|
|
|
|
std::ostringstream ss;
|
|
ss << std::fixed << std::setprecision(decimal_digits) << new_value;
|
|
|
|
char match[3] = " X";
|
|
match[1] = axis;
|
|
|
|
size_t pos = line.find(match) + 2;
|
|
size_t end = std::min(line.find(' ', pos + 1), line.find(';', pos + 1));
|
|
line = line.replace(pos, end - pos, ss.str());
|
|
}
|
|
|
|
int16_t get_fan_speed(const std::string &line, GCodeFlavor flavor) {
|
|
if (line.compare(0, 4, "M106") == 0) {
|
|
if (flavor == (gcfMach3) || flavor == (gcfMachinekit)) {
|
|
return (int16_t)get_axis_value(line, 'P');
|
|
} else {
|
|
// Bambu machines use both M106 P1(not P0!) and M106 for part cooling fan.
|
|
// Non-bambu machines usually use M106 (without P parameter) for part cooling fan.
|
|
// P2 is reserved for auxiliary fan regardless of bambu or not.
|
|
// To keep compatibility with Bambu machines, we accept M106 and M106 P1 as the only two valid form
|
|
// of gcode that control the part cooling fan. Any other command will be ignored!
|
|
const auto idx = get_axis_value(line, 'P');
|
|
if (!isnan(idx) && idx != 1.0f) {
|
|
return -1;
|
|
}
|
|
return (int16_t)get_axis_value(line, 'S');
|
|
}
|
|
} else if (line.compare(0, 4, "M127") == 0 || line.compare(0, 4, "M107") == 0) {
|
|
return 0;
|
|
} else if ((flavor == (gcfMakerWare) || flavor == (gcfSailfish)) && line.compare(0, 4, "M126") == 0) {
|
|
return (int16_t)get_axis_value(line, 'T');
|
|
} else {
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
|
|
void FanMover::_put_in_middle_G1(std::list<BufferData>::iterator item_to_split, float nb_sec_since_itemtosplit_start, BufferData &&line_to_write) {
|
|
assert(item_to_split != m_buffer.end());
|
|
if (nb_sec_since_itemtosplit_start > item_to_split->time * 0.9) {
|
|
// doesn't really need to be split, print it after
|
|
m_buffer.insert(next(item_to_split), line_to_write);
|
|
} else if (nb_sec_since_itemtosplit_start < item_to_split->time * 0.1) {
|
|
// doesn't really need to be split, print it before
|
|
//will also print before if line_to_split.time == 0
|
|
m_buffer.insert(item_to_split, line_to_write);
|
|
} else if (item_to_split->raw.size() > 2
|
|
&& item_to_split->raw[0] == 'G' && item_to_split->raw[1] == '1' && item_to_split->raw[2] == ' ') {
|
|
float percent = nb_sec_since_itemtosplit_start / item_to_split->time;
|
|
BufferData before = *item_to_split;
|
|
before.time *= percent;
|
|
item_to_split->time *= (1-percent);
|
|
if (item_to_split->dx != 0) {
|
|
before.dx = item_to_split->dx * percent;
|
|
item_to_split->x += before.dx;
|
|
item_to_split->dx = item_to_split->dx * (1-percent);
|
|
change_axis_value(before.raw, 'X', before.x + before.dx, 3);
|
|
}
|
|
if (item_to_split->dy != 0) {
|
|
before.dy = item_to_split->dy * percent;
|
|
item_to_split->y += before.dy;
|
|
item_to_split->dy = item_to_split->dy * (1 - percent);
|
|
change_axis_value(before.raw, 'Y', before.y + before.dy, 3);
|
|
}
|
|
if (item_to_split->dz != 0) {
|
|
before.dz = item_to_split->dz * percent;
|
|
item_to_split->z += before.dz;
|
|
item_to_split->dz = item_to_split->dz * (1 - percent);
|
|
change_axis_value(before.raw, 'Z', before.z + before.dz, 3);
|
|
}
|
|
if (item_to_split->de != 0) {
|
|
if (relative_e) {
|
|
before.de = item_to_split->de * percent;
|
|
change_axis_value(before.raw, 'E', before.de, 5);
|
|
item_to_split->de = item_to_split->de * (1 - percent);
|
|
change_axis_value(item_to_split->raw, 'E', item_to_split->de, 5);
|
|
} else {
|
|
before.de = item_to_split->de * percent;
|
|
item_to_split->e += before.de;
|
|
item_to_split->de = item_to_split->de * (1 - percent);
|
|
change_axis_value(before.raw, 'E', before.e + before.de, 5);
|
|
}
|
|
}
|
|
//add before then line_to_write, then there is the modified data.
|
|
m_buffer.insert(item_to_split, before);
|
|
m_buffer.insert(item_to_split, line_to_write);
|
|
|
|
} else {
|
|
//not a G1, print it before
|
|
m_buffer.insert(item_to_split, line_to_write);
|
|
}
|
|
}
|
|
|
|
void FanMover::_print_in_middle_G1(BufferData& line_to_split, float nb_sec, const std::string &line_to_write) {
|
|
if (nb_sec < line_to_split.time * 0.1) {
|
|
// Doesn't need to be split: the insertion point is at the start.
|
|
m_process_output += line_to_write + (line_to_write.back() == '\n'?"":"\n");
|
|
m_process_output += line_to_split.raw + "\n";
|
|
} else if (nb_sec > line_to_split.time * 0.9) {
|
|
// Doesn't need to be split: the insertion point is at the end.
|
|
m_process_output += line_to_split.raw + "\n";
|
|
m_process_output += line_to_write + (line_to_write.back() == '\n' ? "" : "\n");
|
|
}else if(line_to_split.raw.size() > 2
|
|
&& line_to_split.raw[0] == 'G' && line_to_split.raw[1] == '1' && line_to_split.raw[2] == ' ') {
|
|
float percent = nb_sec / line_to_split.time;
|
|
std::string before = line_to_split.raw;
|
|
std::string& after = line_to_split.raw;
|
|
if (line_to_split.dx != 0) {
|
|
change_axis_value(before, 'X', line_to_split.x + line_to_split.dx * percent, 3);
|
|
}
|
|
if (line_to_split.dy != 0) {
|
|
change_axis_value(before, 'Y', line_to_split.y + line_to_split.dy * percent, 3);
|
|
}
|
|
if (line_to_split.dz != 0) {
|
|
change_axis_value(before, 'Z', line_to_split.z + line_to_split.dz * percent, 3);
|
|
}
|
|
if (line_to_split.de != 0) {
|
|
if (relative_e) {
|
|
change_axis_value(before, 'E', line_to_split.de * percent, 5);
|
|
change_axis_value(after, 'E', line_to_split.de * (1 - percent), 5);
|
|
} else {
|
|
change_axis_value(before, 'E', line_to_split.e + line_to_split.de * percent, 5);
|
|
}
|
|
}
|
|
m_process_output += before + "\n";
|
|
m_process_output += line_to_write + (line_to_write.back() == '\n' ? "" : "\n");
|
|
m_process_output += line_to_split.raw + "\n";
|
|
|
|
} else {
|
|
//not a G1, print it before
|
|
m_process_output += line_to_write + (line_to_write.back() == '\n' ? "" : "\n");
|
|
m_process_output += line_to_split.raw + "\n";
|
|
}
|
|
}
|
|
|
|
void FanMover::_remove_slow_fan(int16_t min_speed, float past_sec) {
|
|
//erase fan in the buffer -> don't slowdown if you are in the process of step-up.
|
|
//we began at the "recent" side , and remove as long as we don't push past_sec to 0
|
|
auto it = m_buffer.begin();
|
|
while (it != m_buffer.end() && past_sec > 0) {
|
|
past_sec -= it->time;
|
|
if (it->fan_speed >= 0 && it->fan_speed < min_speed){
|
|
//found something that is lower than us
|
|
it = remove_from_buffer(it);
|
|
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
std::string FanMover::_set_fan(int16_t speed) {
|
|
//const Tool* tool = m_writer.get_tool(m_currrent_extruder < 20 ? m_currrent_extruder : 0);
|
|
// ORCA: apply the per-printer non-zero fan PWM floor so reposted fan commands respect the clamp too.
|
|
const int floor_pct = m_writer.config.part_cooling_fan_min_pwm.value;
|
|
const unsigned int part_cooling_fan_min_pwm = floor_pct > 0 ? static_cast<unsigned int>(floor_pct) : 0u;
|
|
return GCodeWriter::set_fan(m_writer.config.gcode_flavor.value, speed, part_cooling_fan_min_pwm);
|
|
}
|
|
|
|
|
|
bool parse_number(const std::string_view sv, int& out)
|
|
{
|
|
{
|
|
// Legacy conversion, which is costly due to having to make a copy of the string before conversion.
|
|
try {
|
|
assert(sv.size() < 1024);
|
|
assert(sv.data() != nullptr);
|
|
std::string str{ sv };
|
|
size_t read = 0;
|
|
out = std::stoi(str, &read);
|
|
return str.size() == read;
|
|
}
|
|
catch (...) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
//FIXME: add other firmware
|
|
// or just create that damn new gcode writer arch
|
|
void FanMover::_process_T(const std::string_view command)
|
|
{
|
|
if (command.length() > 1) {
|
|
int eid = 0;
|
|
if (!parse_number(command.substr(1), eid) || eid < 0 || eid > 255) {
|
|
GCodeFlavor flavor = m_writer.config.gcode_flavor;
|
|
// Specific to the MMU2 V2 (see https://www.help.prusa3d.com/en/article/prusa-specific-g-codes_112173):
|
|
if ((flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware) && (command == "Tx" || command == "Tc" || command == "T?"))
|
|
return;
|
|
|
|
// T-1 is a valid gcode line for RepRap Firmwares (used to deselects all tools) see https://github.com/prusa3d/PrusaSlicer/issues/5677
|
|
if ((flavor != gcfRepRapFirmware && flavor != gcfRepRapSprinter) || eid != -1)
|
|
m_currrent_extruder = static_cast<uint16_t>(0);
|
|
} else {
|
|
m_currrent_extruder = static_cast<uint16_t>(eid);
|
|
}
|
|
}
|
|
}
|
|
|
|
void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCodeLine& line)
|
|
{
|
|
// processes 'normal' gcode lines
|
|
bool need_flush = false;
|
|
std::string cmd(line.cmd());
|
|
double time = 0;
|
|
int16_t fan_speed = -1;
|
|
if (cmd.length() > 1) {
|
|
if (line.has_f())
|
|
m_current_speed = line.f() / 60.0f;
|
|
switch (::toupper(cmd[0])) {
|
|
case 'T':
|
|
case 't':
|
|
_process_T(cmd);
|
|
break;
|
|
case 'G':
|
|
{
|
|
if (::atoi(&cmd[1]) == 1 || ::atoi(&cmd[1]) == 0) {
|
|
double distx = line.dist_X(reader);
|
|
double disty = line.dist_Y(reader);
|
|
double distz = line.dist_Z(reader);
|
|
double dist = distx * distx + disty * disty + distz * distz;
|
|
if (dist > 0) {
|
|
dist = std::sqrt(dist);
|
|
time = dist / m_current_speed;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 'M':
|
|
{
|
|
fan_speed = get_fan_speed(line.raw(), m_writer.config.gcode_flavor);
|
|
if (fan_speed >= 0) {
|
|
const auto fan_baseline = 255.0;
|
|
fan_speed = 100 * fan_speed / fan_baseline;
|
|
//speed change: stop kickstart reverting if any
|
|
m_current_kickstart.time = -1;
|
|
if (!m_is_custom_gcode) {
|
|
// if slow down => put in the queue. if not =>
|
|
if (m_back_buffer_fan_speed < fan_speed) {
|
|
if (nb_seconds_delay > 0 && (!only_overhangs || current_role == ExtrusionRole::erOverhangPerimeter)) {
|
|
//don't put this command in the queue
|
|
time = -1;
|
|
// this M106 need to go in the past
|
|
//check if we have ( kickstart and not in slowdown )
|
|
if (kickstart > 0 && fan_speed > m_front_buffer_fan_speed) {
|
|
//stop current kickstart , it's not relevant anymore
|
|
if (m_current_kickstart.time > 0) {
|
|
m_current_kickstart.time = (-1);
|
|
}
|
|
|
|
//if kickstart
|
|
// first erase everything lower that that value
|
|
_remove_slow_fan(fan_speed, m_buffer_time_size + 1);
|
|
// then erase everything lower that kickstart
|
|
_remove_slow_fan(fan_baseline, kickstart);
|
|
// print me
|
|
if (!m_buffer.empty() && (m_buffer_time_size - m_buffer.front().time * 0.1) > nb_seconds_delay) {
|
|
_print_in_middle_G1(m_buffer.front(), m_buffer_time_size - nb_seconds_delay, _set_fan(100));//m_writer.set_fan(100, true)); //FIXME extruder id (or use the gcode writer, but then you have to disable the multi-thread thing
|
|
remove_from_buffer(m_buffer.begin());
|
|
} else {
|
|
m_process_output += _set_fan(100);//m_writer.set_fan(100, true)); //FIXME extruder id (or use the gcode writer, but then you have to disable the multi-thread thing
|
|
}
|
|
//write it in the queue if possible
|
|
const float kickstart_duration = kickstart * float(fan_speed - m_front_buffer_fan_speed) / 100.f;
|
|
float time_count = kickstart_duration;
|
|
auto it = m_buffer.begin();
|
|
while (it != m_buffer.end() && time_count > 0) {
|
|
time_count -= it->time;
|
|
if (time_count< 0) {
|
|
//found something that is lower than us
|
|
_put_in_middle_G1(it, it->time + time_count, BufferData(std::string(line.raw()), 0, fan_speed, true));
|
|
//found, stop
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
if (time_count > 0) {
|
|
//can't place it in the buffer, use m_current_kickstart
|
|
m_current_kickstart.fan_speed = fan_speed;
|
|
m_current_kickstart.time = time_count;
|
|
m_current_kickstart.raw = line.raw();
|
|
}
|
|
m_front_buffer_fan_speed = fan_speed;
|
|
} else {
|
|
// first erase everything lower that that value
|
|
_remove_slow_fan(fan_speed, m_buffer_time_size + 1);
|
|
// then write the fan command
|
|
if (!m_buffer.empty() && (m_buffer_time_size - m_buffer.front().time * 0.1) > nb_seconds_delay) {
|
|
_print_in_middle_G1(m_buffer.front(), m_buffer_time_size - nb_seconds_delay, line.raw());
|
|
remove_from_buffer(m_buffer.begin());
|
|
} else {
|
|
m_process_output += line.raw() + "\n";
|
|
}
|
|
m_front_buffer_fan_speed = fan_speed;
|
|
}
|
|
} else {
|
|
if (kickstart <= 0) {
|
|
//nothing to do
|
|
//we don't put time = -1; so it will printed in the buffer as other line are done
|
|
} else if (m_current_kickstart.time > 0) {
|
|
//cherry-pick this one
|
|
if (m_back_buffer_fan_speed >= fan_speed) {
|
|
//stop kickstart
|
|
m_current_kickstart.time = -1;
|
|
//this will print me just after as time >=0
|
|
} else {
|
|
// add some duration to the kickstart and use it for me.
|
|
float kickstart_duration = kickstart * float(fan_speed - m_back_buffer_fan_speed) / 100.f;
|
|
m_current_kickstart.fan_speed = fan_speed;
|
|
m_current_kickstart.time += kickstart_duration;
|
|
m_current_kickstart.raw = line.raw();
|
|
//i'm printed by the m_current_kickstart
|
|
time = -1;
|
|
}
|
|
} else if(m_back_buffer_fan_speed < fan_speed - 10){ //only kickstart if more than 10% change
|
|
//don't write this line, as it will need to be delayed
|
|
time = -1;
|
|
//get the duration of kickstart
|
|
float kickstart_duration = kickstart * float(fan_speed - m_back_buffer_fan_speed) / 100.f;
|
|
//if kickstart, write the M106 S[fan_baseline] first
|
|
//set the target speed and set the kickstart flag
|
|
put_in_buffer(BufferData(_set_fan(100)//m_writer.set_fan(100, true)); //FIXME extruder id (or use the gcode writer, but then you have to disable the multi-thread thing
|
|
, 0, fan_speed, true));
|
|
//kickstart!
|
|
//m_process_output += m_writer.set_fan(100, true);
|
|
//add the normal speed line for the future
|
|
m_current_kickstart.fan_speed = fan_speed;
|
|
m_current_kickstart.time = kickstart_duration;
|
|
m_current_kickstart.raw = line.raw();
|
|
}
|
|
}
|
|
}
|
|
//update back buffer fan speed
|
|
m_back_buffer_fan_speed = fan_speed;
|
|
} else {
|
|
// have to flush the buffer to avoid erasing a fan command.
|
|
need_flush = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
if(!line.raw().empty() && line.raw().front() == ';')
|
|
{
|
|
if (line.raw().size() > 10 && line.raw().rfind(";TYPE:", 0) == 0) {
|
|
// get the type of the next extrusions
|
|
std::string extrusion_string = line.raw().substr(6, line.raw().size() - 6);
|
|
current_role = ExtrusionEntity::string_to_role(extrusion_string);
|
|
}
|
|
if (line.raw().size() > 16) {
|
|
if (line.raw().rfind("; custom gcode", 0) != std::string::npos) {
|
|
if (line.raw().rfind("; custom gcode end", 0) != std::string::npos)
|
|
m_is_custom_gcode = false;
|
|
else
|
|
m_is_custom_gcode = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (time >= 0) {
|
|
BufferData& new_data = put_in_buffer(BufferData(line.raw(), time, fan_speed));
|
|
if (line.has(Axis::X)) {
|
|
new_data.x = reader.x();
|
|
new_data.dx = line.dist_X(reader);
|
|
}
|
|
if (line.has(Axis::Y)) {
|
|
new_data.y = reader.y();
|
|
new_data.dy = line.dist_Y(reader);
|
|
}
|
|
if (line.has(Axis::Z)) {
|
|
new_data.z = reader.z();
|
|
new_data.dz = line.dist_Z(reader);
|
|
}
|
|
if (line.has(Axis::E)) {
|
|
new_data.e = reader.e();
|
|
if (relative_e)
|
|
new_data.de = line.e();
|
|
else
|
|
new_data.de = line.dist_E(reader);
|
|
}
|
|
|
|
if (m_current_kickstart.time > 0 && time > 0) {
|
|
m_current_kickstart.time -= time;
|
|
if (m_current_kickstart.time < 0) {
|
|
//prev is possible because we just do a emplace_back.
|
|
_put_in_middle_G1(prev(m_buffer.end()), time + m_current_kickstart.time, BufferData{ m_current_kickstart.raw, 0, m_current_kickstart.fan_speed, true });
|
|
}
|
|
}
|
|
}/* else {
|
|
BufferData& new_data = put_in_buffer(BufferData("; del? "+line.raw(), 0, fan_speed));
|
|
if (line.has(Axis::X)) {
|
|
new_data.x = reader.x();
|
|
new_data.dx = line.dist_X(reader);
|
|
}
|
|
if (line.has(Axis::Y)) {
|
|
new_data.y = reader.y();
|
|
new_data.dy = line.dist_Y(reader);
|
|
}
|
|
if (line.has(Axis::Z)) {
|
|
new_data.z = reader.z();
|
|
new_data.dz = line.dist_Z(reader);
|
|
}
|
|
if (line.has(Axis::E)) {
|
|
new_data.e = reader.e();
|
|
if (relative_e)
|
|
new_data.de = line.e();
|
|
else
|
|
new_data.de = line.dist_E(reader);
|
|
}
|
|
}*/
|
|
// puts the line back into the gcode
|
|
//if buffer too big, flush it.
|
|
if (time >= 0) {
|
|
while (!m_buffer.empty() && (need_flush || m_buffer_time_size - m_buffer.front().time > nb_seconds_delay - EPSILON) ){
|
|
BufferData& frontdata = m_buffer.front();
|
|
if (frontdata.fan_speed < 0 || frontdata.fan_speed != m_front_buffer_fan_speed || frontdata.is_kickstart) {
|
|
if (frontdata.is_kickstart && frontdata.fan_speed < m_front_buffer_fan_speed) {
|
|
//you have to slow down! not kickstart! rewrite the fan speed.
|
|
m_process_output += _set_fan(frontdata.fan_speed);//m_writer.set_fan(frontdata.fan_speed,true); //FIXME extruder id (or use the gcode writer, but then you have to disable the multi-thread thing
|
|
|
|
m_front_buffer_fan_speed = frontdata.fan_speed;
|
|
} else {
|
|
m_process_output += frontdata.raw + "\n";
|
|
if (frontdata.fan_speed >= 0) {
|
|
//note that this is the only place where the fan_speed is set and we print from the buffer, as if the fan_speed >= 0 => time == 0
|
|
//and as this flush all time == 0 lines from the back of the queue...
|
|
m_front_buffer_fan_speed = frontdata.fan_speed;
|
|
}
|
|
}
|
|
}
|
|
remove_from_buffer(m_buffer.begin());
|
|
}
|
|
}
|
|
double sum = 0;
|
|
for (auto& data : m_buffer) sum += data.time;
|
|
assert( std::abs(m_buffer_time_size - sum) < 0.01);
|
|
}
|
|
|
|
} // namespace Slic3r
|
|
|