#8176 - Tech ENABLE_USED_FILAMENT_POST_PROCESS - Fixes used filament data exported to gcode file not taking in account custom gcode

This commit is contained in:
enricoturri1966 2022-04-13 15:27:46 +02:00
parent 7dc4a57d63
commit 3ce2d3a700
4 changed files with 9712 additions and 9291 deletions

View file

@ -34,6 +34,9 @@ static const float DEFAULT_TRAVEL_ACCELERATION = 1250.0f;
static const size_t MIN_EXTRUDERS_COUNT = 5;
static const float DEFAULT_FILAMENT_DIAMETER = 1.75f;
static const float DEFAULT_FILAMENT_DENSITY = 1.245f;
#if ENABLE_USED_FILAMENT_POST_PROCESS
static const float DEFAULT_FILAMENT_COST = 0.0f;
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero();
#if ENABLE_PROCESS_G2_G3_LINES
@ -358,6 +361,7 @@ void GCodeProcessor::TimeProcessor::reset()
machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].enabled = true;
}
#if !ENABLE_USED_FILAMENT_POST_PROCESS
void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, std::vector<GCodeProcessorResult::MoveVertex>& moves, std::vector<size_t>& lines_ends)
{
FilePtr in{ boost::nowide::fopen(filename.c_str(), "rb") };
@ -663,16 +667,17 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
throw Slic3r::RuntimeError(std::string("Failed to rename the output G-code file from ") + out_path + " to " + filename + '\n' +
"Is " + out_path + " locked?" + '\n');
}
#endif // !ENABLE_USED_FILAMENT_POST_PROCESS
void GCodeProcessor::UsedFilaments::reset()
{
color_change_cache = 0.0f;
color_change_cache = 0.0;
volumes_per_color_change = std::vector<double>();
tool_change_cache = 0.0f;
tool_change_cache = 0.0;
volumes_per_extruder.clear();
role_cache = 0.0f;
role_cache = 0.0;
filaments_per_role.clear();
}
@ -694,21 +699,21 @@ void GCodeProcessor::UsedFilaments::process_color_change_cache()
void GCodeProcessor::UsedFilaments::process_extruder_cache(GCodeProcessor* processor)
{
size_t active_extruder_id = processor->m_extruder_id;
if (tool_change_cache != 0.0f) {
if (tool_change_cache != 0.0) {
if (volumes_per_extruder.find(active_extruder_id) != volumes_per_extruder.end())
volumes_per_extruder[active_extruder_id] += tool_change_cache;
else
volumes_per_extruder[active_extruder_id] = tool_change_cache;
tool_change_cache = 0.0f;
tool_change_cache = 0.0;
}
}
void GCodeProcessor::UsedFilaments::process_role_cache(GCodeProcessor* processor)
{
if (role_cache != 0.0f) {
if (role_cache != 0.0) {
std::pair<double, double> filament = { 0.0f, 0.0f };
double s = PI * sqr(0.5 * processor->m_result.filament_diameters[processor->m_extruder_id]);
const double s = PI * sqr(0.5 * processor->m_result.filament_diameters[processor->m_extruder_id]);
filament.first = role_cache / s * 0.001;
filament.second = role_cache * processor->m_result.filament_densities[processor->m_extruder_id] * 0.001;
@ -719,7 +724,7 @@ void GCodeProcessor::UsedFilaments::process_role_cache(GCodeProcessor* processor
}
else
filaments_per_role[active_role] = filament;
role_cache = 0.0f;
role_cache = 0.0;
}
}
@ -740,6 +745,9 @@ void GCodeProcessorResult::reset() {
extruder_colors = std::vector<std::string>();
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
#if ENABLE_USED_FILAMENT_POST_PROCESS
filament_cost = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_COST);
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
spiral_vase_layers = std::vector<std::pair<float, std::pair<size_t, size_t>>>();
time = 0;
@ -756,6 +764,9 @@ void GCodeProcessorResult::reset() {
extruder_colors = std::vector<std::string>();
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
#if ENABLE_USED_FILAMENT_POST_PROCESS
filament_cost = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_COST);
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
spiral_vase_layers = std::vector<std::pair<float, std::pair<size_t, size_t>>>();
}
@ -850,6 +861,9 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_extruder_colors.resize(extruders_count);
m_result.filament_diameters.resize(extruders_count);
m_result.filament_densities.resize(extruders_count);
#if ENABLE_USED_FILAMENT_POST_PROCESS
m_result.filament_cost.resize(extruders_count);
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
m_extruder_temps.resize(extruders_count);
for (size_t i = 0; i < extruders_count; ++ i) {
@ -857,6 +871,9 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_extruder_colors[i] = static_cast<unsigned char>(i);
m_result.filament_diameters[i] = static_cast<float>(config.filament_diameter.get_at(i));
m_result.filament_densities[i] = static_cast<float>(config.filament_density.get_at(i));
#if ENABLE_USED_FILAMENT_POST_PROCESS
m_result.filament_cost[i] = static_cast<float>(config.filament_cost.get_at(i));
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
}
if ((m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfRepRapFirmware) && config.machine_limits_usage.value != MachineLimitsUsage::Ignore) {
@ -970,6 +987,23 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
}
}
#if ENABLE_USED_FILAMENT_POST_PROCESS
const ConfigOptionFloats* filament_cost = config.option<ConfigOptionFloats>("filament_cost");
if (filament_cost != nullptr) {
m_result.filament_cost.clear();
m_result.filament_cost.resize(filament_cost->values.size());
for (size_t i = 0; i < filament_cost->values.size(); ++i) {
m_result.filament_cost[i] = static_cast<float>(filament_cost->values[i]);
}
}
if (m_result.filament_cost.size() < m_result.extruders_count) {
for (size_t i = m_result.filament_cost.size(); i < m_result.extruders_count; ++i) {
m_result.filament_cost.emplace_back(DEFAULT_FILAMENT_COST);
}
}
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
const ConfigOptionPoints* extruder_offset = config.option<ConfigOptionPoints>("extruder_offset");
if (extruder_offset != nullptr) {
m_extruder_offsets.resize(extruder_offset->values.size());
@ -1331,7 +1365,7 @@ void GCodeProcessor::process_buffer(const std::string &buffer)
});
}
void GCodeProcessor::finalize(bool post_process)
void GCodeProcessor::finalize(bool perform_post_process)
{
// update width/height of wipe moves
for (GCodeProcessorResult::MoveVertex& move : m_result.moves) {
@ -1361,8 +1395,12 @@ void GCodeProcessor::finalize(bool post_process)
m_width_compare.output();
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
if (post_process)
if (perform_post_process)
#if ENABLE_USED_FILAMENT_POST_PROCESS
post_process();
#else
m_time_processor.post_process(m_result.filename, m_result.moves, m_result.lines_ends);
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
#if ENABLE_GCODE_VIEWER_STATISTICS
m_result.time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - m_start_time).count();
#endif // ENABLE_GCODE_VIEWER_STATISTICS
@ -1534,6 +1572,12 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename)
} else if (comment.find("filamentDensities") != comment.npos) {
m_result.filament_densities.clear();
extract_floats(comment, "filamentDensities", m_result.filament_densities);
#if ENABLE_USED_FILAMENT_POST_PROCESS
}
else if (comment.find("filamentPricesPerKg") != comment.npos) {
m_result.filament_cost.clear();
extract_floats(comment, "filamentPricesPerKg", m_result.filament_cost);
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
} else if (comment.find("extruderDiameter") != comment.npos) {
std::vector<float> extruder_diameters;
extract_floats(comment, "extruderDiameter", extruder_diameters);
@ -1549,8 +1593,14 @@ void GCodeProcessor::apply_config_simplify3d(const std::string& filename)
}
});
#if ENABLE_USED_FILAMENT_POST_PROCESS
if (m_result.extruders_count == 0)
m_result.extruders_count = std::max<size_t>(1, std::min(m_result.filament_diameters.size(),
std::min(m_result.filament_densities.size(), m_result.filament_cost.size())));
#else
if (m_result.extruders_count == 0)
m_result.extruders_count = std::max<size_t>(1, std::min(m_result.filament_diameters.size(), m_result.filament_densities.size()));
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
if (bed_size.is_defined()) {
m_result.bed_shape = {
@ -3493,6 +3543,354 @@ void GCodeProcessor::process_T(const std::string_view command)
}
}
#if ENABLE_USED_FILAMENT_POST_PROCESS
void GCodeProcessor::post_process()
{
FilePtr in{ boost::nowide::fopen(m_result.filename.c_str(), "rb") };
if (in.f == nullptr)
throw Slic3r::RuntimeError(std::string("GCode processor post process export failed.\nCannot open file for reading.\n"));
// temporary file to contain modified gcode
std::string out_path = m_result.filename + ".postprocess";
FilePtr out{ boost::nowide::fopen(out_path.c_str(), "wb") };
if (out.f == nullptr) {
throw Slic3r::RuntimeError(std::string("GCode processor post process export failed.\nCannot open file for writing.\n"));
}
auto time_in_minutes = [](float time_in_seconds) {
assert(time_in_seconds >= 0.f);
return int((time_in_seconds + 0.5f) / 60.0f);
};
auto time_in_last_minute = [](float time_in_seconds) {
assert(time_in_seconds <= 60.0f);
return time_in_seconds / 60.0f;
};
auto format_line_M73_main = [](const std::string& mask, int percent, int time) {
char line_M73[64];
sprintf(line_M73, mask.c_str(),
std::to_string(percent).c_str(),
std::to_string(time).c_str());
return std::string(line_M73);
};
auto format_line_M73_stop_int = [](const std::string& mask, int time) {
char line_M73[64];
sprintf(line_M73, mask.c_str(), std::to_string(time).c_str());
return std::string(line_M73);
};
auto format_time_float = [](float time) {
return Slic3r::float_to_string_decimal_point(time, 2);
};
auto format_line_M73_stop_float = [format_time_float](const std::string& mask, float time) {
char line_M73[64];
sprintf(line_M73, mask.c_str(), format_time_float(time).c_str());
return std::string(line_M73);
};
std::string gcode_line;
size_t g1_lines_counter = 0;
// keeps track of last exported pair <percent, remaining time>
std::array<std::pair<int, int>, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> last_exported_main;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
last_exported_main[i] = { 0, time_in_minutes(m_time_processor.machines[i].time) };
}
// keeps track of last exported remaining time to next printer stop
std::array<int, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> last_exported_stop;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
last_exported_stop[i] = time_in_minutes(m_time_processor.machines[i].time);
}
// buffer line to export only when greater than 64K to reduce writing calls
std::string export_line;
// replace placeholder lines with the proper final value
// gcode_line is in/out parameter, to reduce expensive memory allocation
auto process_placeholders = [&](std::string& gcode_line) {
unsigned int extra_lines_count = 0;
// remove trailing '\n'
auto line = std::string_view(gcode_line).substr(0, gcode_line.length() - 1);
std::string ret;
if (line.length() > 1) {
line = line.substr(1);
if (m_time_processor.export_remaining_time_enabled &&
(line == reserved_tag(ETags::First_Line_M73_Placeholder) || line == reserved_tag(ETags::Last_Line_M73_Placeholder))) {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
const TimeMachine& machine = m_time_processor.machines[i];
if (machine.enabled) {
// export pair <percent, remaining time>
ret += format_line_M73_main(machine.line_m73_main_mask.c_str(),
(line == reserved_tag(ETags::First_Line_M73_Placeholder)) ? 0 : 100,
(line == reserved_tag(ETags::First_Line_M73_Placeholder)) ? time_in_minutes(machine.time) : 0);
++extra_lines_count;
// export remaining time to next printer stop
if (line == reserved_tag(ETags::First_Line_M73_Placeholder) && !machine.stop_times.empty()) {
int to_export_stop = time_in_minutes(machine.stop_times.front().elapsed_time);
ret += format_line_M73_stop_int(machine.line_m73_stop_mask.c_str(), to_export_stop);
last_exported_stop[i] = to_export_stop;
++extra_lines_count;
}
}
}
}
else if (line == reserved_tag(ETags::Estimated_Printing_Time_Placeholder)) {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
const TimeMachine& machine = m_time_processor.machines[i];
PrintEstimatedStatistics::ETimeMode mode = static_cast<PrintEstimatedStatistics::ETimeMode>(i);
if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
char buf[128];
sprintf(buf, "; estimated printing time (%s mode) = %s\n",
(mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent",
get_time_dhms(machine.time).c_str());
ret += buf;
}
}
}
}
if (!ret.empty())
// Not moving the move operator on purpose, so that the gcode_line allocation will grow and it will not be reallocated after handful of lines are processed.
gcode_line = ret;
return std::tuple(!ret.empty(), (extra_lines_count == 0) ? extra_lines_count : extra_lines_count - 1);
};
struct FilamentData
{
double mm{ 0.0 };
double cm3{ 0.0 };
double g{ 0.0 };
double cost{ 0.0 };
};
FilamentData filament_data;
for (const auto& [role, used] : m_result.print_statistics.used_filaments_per_role) {
filament_data.mm += used.first;
filament_data.g += used.second;
}
for (const auto& [id, volume] : m_result.print_statistics.volumes_per_extruder) {
filament_data.cm3 += volume;
filament_data.cost += volume * double(m_result.filament_densities[id]) * double(m_result.filament_cost[id]) * 0.000001;
}
auto process_used_filament = [&filament_data](std::string& gcode_line) {
auto process_tag = [](std::string& gcode_line, const std::string& tag, double value) {
if (boost::algorithm::istarts_with(gcode_line, tag)) {
char buf[128];
sprintf(buf, "%s %.2lf\n", tag.c_str(), value);
gcode_line = buf;
return true;
}
return false;
};
bool ret = false;
ret |= process_tag(gcode_line, "; filament used [mm] =", filament_data.mm * 1000.0);
ret |= process_tag(gcode_line, "; filament used [g] =", filament_data.g);
ret |= process_tag(gcode_line, "; total filament used [g] =", filament_data.g);
ret |= process_tag(gcode_line, "; filament used [cm3] =", filament_data.cm3 / 1000.0);
ret |= process_tag(gcode_line, "; filament cost =", filament_data.cost);
ret |= process_tag(gcode_line, "; total filament cost =", filament_data.cost);
return ret;
};
// check for temporary lines
auto is_temporary_decoration = [](const std::string_view gcode_line) {
// remove trailing '\n'
assert(!gcode_line.empty());
assert(gcode_line.back() == '\n');
// return true for decorations which are used in processing the gcode but that should not be exported into the final gcode
// i.e.:
// bool ret = gcode_line.substr(0, gcode_line.length() - 1) == ";" + Layer_Change_Tag;
// ...
// return ret;
return false;
};
// Iterators for the normal and silent cached time estimate entry recently processed, used by process_line_G1.
auto g1_times_cache_it = Slic3r::reserve_vector<std::vector<TimeMachine::G1LinesCacheItem>::const_iterator>(m_time_processor.machines.size());
for (const auto& machine : m_time_processor.machines)
g1_times_cache_it.emplace_back(machine.g1_times_cache.begin());
// add lines M73 to exported gcode
auto process_line_G1 = [this,
// Lambdas, mostly for string formatting, all with an empty capture block.
time_in_minutes, format_time_float, format_line_M73_main, format_line_M73_stop_int, format_line_M73_stop_float, time_in_last_minute,
// Caches, to be modified
&g1_times_cache_it, &last_exported_main, &last_exported_stop,
// String output
&export_line]
(const size_t g1_lines_counter) {
unsigned int exported_lines_count = 0;
if (m_time_processor.export_remaining_time_enabled) {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
const TimeMachine& machine = m_time_processor.machines[i];
if (machine.enabled) {
// export pair <percent, remaining time>
// Skip all machine.g1_times_cache below g1_lines_counter.
auto& it = g1_times_cache_it[i];
while (it != machine.g1_times_cache.end() && it->id < g1_lines_counter)
++it;
if (it != machine.g1_times_cache.end() && it->id == g1_lines_counter) {
std::pair<int, int> to_export_main = { int(100.0f * it->elapsed_time / machine.time),
time_in_minutes(machine.time - it->elapsed_time) };
if (last_exported_main[i] != to_export_main) {
export_line += format_line_M73_main(machine.line_m73_main_mask.c_str(),
to_export_main.first, to_export_main.second);
last_exported_main[i] = to_export_main;
++exported_lines_count;
}
// export remaining time to next printer stop
auto it_stop = std::upper_bound(machine.stop_times.begin(), machine.stop_times.end(), it->elapsed_time,
[](float value, const TimeMachine::StopTime& t) { return value < t.elapsed_time; });
if (it_stop != machine.stop_times.end()) {
int to_export_stop = time_in_minutes(it_stop->elapsed_time - it->elapsed_time);
if (last_exported_stop[i] != to_export_stop) {
if (to_export_stop > 0) {
if (last_exported_stop[i] != to_export_stop) {
export_line += format_line_M73_stop_int(machine.line_m73_stop_mask.c_str(), to_export_stop);
last_exported_stop[i] = to_export_stop;
++exported_lines_count;
}
}
else {
bool is_last = false;
auto next_it = it + 1;
is_last |= (next_it == machine.g1_times_cache.end());
if (next_it != machine.g1_times_cache.end()) {
auto next_it_stop = std::upper_bound(machine.stop_times.begin(), machine.stop_times.end(), next_it->elapsed_time,
[](float value, const TimeMachine::StopTime& t) { return value < t.elapsed_time; });
is_last |= (next_it_stop != it_stop);
std::string time_float_str = format_time_float(time_in_last_minute(it_stop->elapsed_time - it->elapsed_time));
std::string next_time_float_str = format_time_float(time_in_last_minute(it_stop->elapsed_time - next_it->elapsed_time));
is_last |= (string_to_double_decimal_point(time_float_str) > 0. && string_to_double_decimal_point(next_time_float_str) == 0.);
}
if (is_last) {
if (std::distance(machine.stop_times.begin(), it_stop) == static_cast<ptrdiff_t>(machine.stop_times.size() - 1))
export_line += format_line_M73_stop_int(machine.line_m73_stop_mask.c_str(), to_export_stop);
else
export_line += format_line_M73_stop_float(machine.line_m73_stop_mask.c_str(), time_in_last_minute(it_stop->elapsed_time - it->elapsed_time));
last_exported_stop[i] = to_export_stop;
++exported_lines_count;
}
}
}
}
}
}
}
}
return exported_lines_count;
};
// helper function to write to disk
size_t out_file_pos = 0;
m_result.lines_ends.clear();
auto write_string = [this, &export_line, &out, &out_path, &out_file_pos](const std::string& str) {
fwrite((const void*)export_line.c_str(), 1, export_line.length(), out.f);
if (ferror(out.f)) {
out.close();
boost::nowide::remove(out_path.c_str());
throw Slic3r::RuntimeError(std::string("GCode processor post process export failed.\nIs the disk full?\n"));
}
for (size_t i = 0; i < export_line.size(); ++i)
if (export_line[i] == '\n')
m_result.lines_ends.emplace_back(out_file_pos + i + 1);
out_file_pos += export_line.size();
export_line.clear();
};
unsigned int line_id = 0;
std::vector<std::pair<unsigned int, unsigned int>> offsets;
{
// Read the input stream 64kB at a time, extract lines and process them.
std::vector<char> buffer(65536 * 10, 0);
// Line buffer.
assert(gcode_line.empty());
for (;;) {
size_t cnt_read = ::fread(buffer.data(), 1, buffer.size(), in.f);
if (::ferror(in.f))
throw Slic3r::RuntimeError(std::string("GCode processor post process export failed.\nError while reading from file.\n"));
bool eof = cnt_read == 0;
auto it = buffer.begin();
auto it_bufend = buffer.begin() + cnt_read;
while (it != it_bufend || (eof && !gcode_line.empty())) {
// Find end of line.
bool eol = false;
auto it_end = it;
for (; it_end != it_bufend && !(eol = *it_end == '\r' || *it_end == '\n'); ++it_end);
// End of line is indicated also if end of file was reached.
eol |= eof && it_end == it_bufend;
gcode_line.insert(gcode_line.end(), it, it_end);
if (eol) {
++line_id;
gcode_line += "\n";
// replace placeholder lines
auto [processed, lines_added_count] = process_placeholders(gcode_line);
if (processed && lines_added_count > 0)
offsets.push_back({ line_id, lines_added_count });
if (!processed)
processed = process_used_filament(gcode_line);
if (!processed && !is_temporary_decoration(gcode_line) && GCodeReader::GCodeLine::cmd_is(gcode_line, "G1")) {
// remove temporary lines, add lines M73 where needed
unsigned int extra_lines_count = process_line_G1(g1_lines_counter++);
if (extra_lines_count > 0)
offsets.push_back({ line_id, extra_lines_count });
}
export_line += gcode_line;
if (export_line.length() > 65535)
write_string(export_line);
gcode_line.clear();
}
// Skip EOL.
it = it_end;
if (it != it_bufend && *it == '\r')
++it;
if (it != it_bufend && *it == '\n')
++it;
}
if (eof)
break;
}
}
if (!export_line.empty())
write_string(export_line);
out.close();
in.close();
// updates moves' gcode ids which have been modified by the insertion of the M73 lines
unsigned int curr_offset_id = 0;
unsigned int total_offset = 0;
for (GCodeProcessorResult::MoveVertex& move : m_result.moves) {
while (curr_offset_id < static_cast<unsigned int>(offsets.size()) && offsets[curr_offset_id].first <= move.gcode_id) {
total_offset += offsets[curr_offset_id].second;
++curr_offset_id;
}
move.gcode_id += total_offset;
}
if (rename_file(out_path, m_result.filename))
throw Slic3r::RuntimeError(std::string("Failed to rename the output G-code file from ") + out_path + " to " + m_result.filename + '\n' +
"Is " + out_path + " locked?" + '\n');
}
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
#if ENABLE_PROCESS_G2_G3_LINES
void GCodeProcessor::store_move_vertex(EMoveType type, bool internal_only)
#else

View file

@ -67,6 +67,9 @@ namespace Slic3r {
std::vector<double> volumes_per_color_change;
std::map<size_t, double> volumes_per_extruder;
std::map<ExtrusionRole, std::pair<double, double>> used_filaments_per_role;
#if ENABLE_USED_FILAMENT_POST_PROCESS
std::map<size_t, double> cost_per_extruder;
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
std::array<Mode, static_cast<size_t>(ETimeMode::Count)> modes;
@ -79,6 +82,9 @@ namespace Slic3r {
volumes_per_color_change.clear();
volumes_per_extruder.clear();
used_filaments_per_role.clear();
#if ENABLE_USED_FILAMENT_POST_PROCESS
cost_per_extruder.clear();
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
}
};
@ -132,6 +138,10 @@ namespace Slic3r {
std::vector<std::string> extruder_colors;
std::vector<float> filament_diameters;
std::vector<float> filament_densities;
#if ENABLE_USED_FILAMENT_POST_PROCESS
std::vector<float> filament_cost;
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
PrintEstimatedStatistics print_statistics;
std::vector<CustomGCode::Item> custom_gcode_per_print_z;
std::vector<std::pair<float, std::pair<size_t, size_t>>> spiral_vase_layers;
@ -352,9 +362,13 @@ namespace Slic3r {
void reset();
#if ENABLE_USED_FILAMENT_POST_PROCESS
friend class GCodeProcessor;
#else
// post process the file with the given filename to add remaining time lines M73
// and updates moves' gcode ids accordingly
void post_process(const std::string& filename, std::vector<GCodeProcessorResult::MoveVertex>& moves, std::vector<size_t>& lines_ends);
#endif // !ENABLE_USED_FILAMENT_POST_PROCESS
};
struct UsedFilaments // filaments per ColorChange
@ -753,6 +767,13 @@ namespace Slic3r {
void process_T(const GCodeReader::GCodeLine& line);
void process_T(const std::string_view command);
#if ENABLE_USED_FILAMENT_POST_PROCESS
// post process the file with the given filename to:
// 1) add remaining time lines M73 and update moves' gcode ids accordingly
// 2) update used filament data
void post_process();
#endif // ENABLE_USED_FILAMENT_POST_PROCESS
#if ENABLE_PROCESS_G2_G3_LINES
void store_move_vertex(EMoveType type, bool internal_only = false);
#else

View file

@ -77,6 +77,8 @@
#define ENABLE_ALTERNATIVE_FILE_WILDCARDS_GENERATOR (1 && ENABLE_2_5_0_ALPHA1)
// Enable processing of gcode G2 and G3 lines
#define ENABLE_PROCESS_G2_G3_LINES (1 && ENABLE_2_5_0_ALPHA1)
// Enable fix of used filament data exported to gcode file
#define ENABLE_USED_FILAMENT_POST_PROCESS (1 && ENABLE_2_5_0_ALPHA1)
#endif // _prusaslicer_technologies_h_