Skip to content

Commit

Permalink
Fix of #2825 - Add the length of each filament used
Browse files Browse the repository at this point in the history
  • Loading branch information
YuSanka committed May 5, 2021
1 parent 34f8488 commit cb7d2c9
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 21 deletions.
42 changes: 41 additions & 1 deletion src/libslic3r/GCode/GCodeProcessor.cpp
Expand Up @@ -186,6 +186,13 @@ void GCodeProcessor::TimeMachine::CustomGCodeTime::reset()
times = std::vector<std::pair<CustomGCode::Type, float>>();
}

void GCodeProcessor::TimeMachine::UsedFilaments::reset()
{
needed = false;
cache = 0.0f;
distances = std::vector<float>();
}

void GCodeProcessor::TimeMachine::reset()
{
enabled = false;
Expand All @@ -201,6 +208,7 @@ void GCodeProcessor::TimeMachine::reset()
curr.reset();
prev.reset();
gcode_time.reset();
used_filaments.reset();
blocks = std::vector<TimeBlock>();
g1_times_cache = std::vector<G1LinesCacheItem>();
std::fill(moves_time.begin(), moves_time.end(), 0.0f);
Expand Down Expand Up @@ -309,6 +317,13 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks)
size_t n_blocks_process = blocks.size() - keep_last_n_blocks;
for (size_t i = 0; i < n_blocks_process; ++i) {
const TimeBlock& block = blocks[i];
if (block.move_type == EMoveType::Extrude ||
block.move_type == EMoveType::Retract ||
block.move_type == EMoveType::Unretract ||
block.move_type == EMoveType::Color_change ||
block.move_type == EMoveType::Wipe ) {
used_filaments.cache += block.distance;
}
float block_time = block.time();
time += block_time;
gcode_time.cache += block_time;
Expand Down Expand Up @@ -1170,9 +1185,12 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
TimeMachine& machine = m_time_processor.machines[i];
TimeMachine::CustomGCodeTime& gcode_time = machine.gcode_time;
TimeMachine::UsedFilaments& used_filaments = machine.used_filaments;
machine.calculate_time();
if (gcode_time.needed && gcode_time.cache != 0.0f)
gcode_time.times.push_back({ CustomGCode::ColorChange, gcode_time.cache });
if (used_filaments.needed && used_filaments.cache != 0.0f)
used_filaments.distances.push_back({ used_filaments.cache });
}

update_estimated_times_stats();
Expand Down Expand Up @@ -1222,6 +1240,18 @@ std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> GCodeProcesso
return ret;
}

std::vector<float> GCodeProcessor::get_used_filaments(PrintEstimatedTimeStatistics::ETimeMode mode) const
{
std::vector<float> ret;
if (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) {
const TimeMachine& machine = m_time_processor.machines[static_cast<size_t>(mode)];
for (const auto& distance : machine.used_filaments.distances) {
ret.push_back(distance * m_mm3_per_mm);
}
}
return ret;
}

std::vector<std::pair<EMoveType, float>> GCodeProcessor::get_moves_time(PrintEstimatedTimeStatistics::ETimeMode mode) const
{
std::vector<std::pair<EMoveType, float>> ret;
Expand Down Expand Up @@ -1520,7 +1550,8 @@ void GCodeProcessor::process_tags(const std::string_view comment)
extruder_id = static_cast<unsigned char>(eid);
}

m_extruder_colors[extruder_id] = static_cast<unsigned char>(m_extruder_offsets.size()) + m_cp_color.counter; // color_change position in list of color for preview
if (extruder_id < m_extruder_colors.size())
m_extruder_colors[extruder_id] = static_cast<unsigned char>(m_extruder_offsets.size()) + m_cp_color.counter; // color_change position in list of color for preview
++m_cp_color.counter;
if (m_cp_color.counter == UCHAR_MAX)
m_cp_color.counter = 0;
Expand Down Expand Up @@ -2962,6 +2993,13 @@ void GCodeProcessor::process_custom_gcode_time(CustomGCode::Type code)
gcode_time.times.push_back({ code, gcode_time.cache });
gcode_time.cache = 0.0f;
}

TimeMachine::UsedFilaments& used_filaments = machine.used_filaments;
used_filaments.needed = true;
if (used_filaments.cache != 0.0f && code == CustomGCode::ColorChange) {
used_filaments.distances.push_back({ used_filaments.cache });
used_filaments.cache = 0.0f;
}
}
}

Expand All @@ -2981,6 +3019,8 @@ void GCodeProcessor::update_estimated_times_stats()
data.moves_times = get_moves_time(mode);
data.roles_times = get_roles_time(mode);
data.layers_times = get_layers_time(mode);

data.used_filaments = get_used_filaments(mode);
};

update_mode(PrintEstimatedTimeStatistics::ETimeMode::Normal);
Expand Down
13 changes: 13 additions & 0 deletions src/libslic3r/GCode/GCodeProcessor.hpp
Expand Up @@ -46,13 +46,15 @@ namespace Slic3r {
std::vector<std::pair<EMoveType, float>> moves_times;
std::vector<std::pair<ExtrusionRole, float>> roles_times;
std::vector<float> layers_times;
std::vector<float> used_filaments;

void reset() {
time = 0.0f;
custom_gcode_times.clear();
moves_times.clear();
roles_times.clear();
layers_times.clear();
used_filaments.clear();
}
};

Expand Down Expand Up @@ -241,6 +243,15 @@ namespace Slic3r {
void reset();
};

struct UsedFilaments // filaments per ColorChange
{
bool needed;
float cache;
std::vector<float> distances;

void reset();
};

struct G1LinesCacheItem
{
unsigned int id;
Expand Down Expand Up @@ -271,6 +282,7 @@ namespace Slic3r {
State curr;
State prev;
CustomGCodeTime gcode_time;
UsedFilaments used_filaments;
std::vector<TimeBlock> blocks;
std::vector<G1LinesCacheItem> g1_times_cache;
std::array<float, static_cast<size_t>(EMoveType::Count)> moves_time;
Expand Down Expand Up @@ -545,6 +557,7 @@ namespace Slic3r {
float get_time(PrintEstimatedTimeStatistics::ETimeMode mode) const;
std::string get_time_dhm(PrintEstimatedTimeStatistics::ETimeMode mode) const;
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> get_custom_gcode_times(PrintEstimatedTimeStatistics::ETimeMode mode, bool include_remaining) const;
std::vector<float> get_used_filaments(PrintEstimatedTimeStatistics::ETimeMode mode) const;

std::vector<std::pair<EMoveType, float>> get_moves_time(PrintEstimatedTimeStatistics::ETimeMode mode) const;
std::vector<std::pair<ExtrusionRole, float>> get_roles_time(PrintEstimatedTimeStatistics::ETimeMode mode) const;
Expand Down
89 changes: 69 additions & 20 deletions src/slic3r/GUI/GCodeViewer.cpp
Expand Up @@ -4055,7 +4055,7 @@ void GCodeViewer::render_legend() const
#else
auto append_item = [this, draw_list, icon_size, percent_bar_size, &imgui](EItemType type, const Color& color, const std::string& label,
#endif // ENABLE_SCROLLABLE_LEGEND
bool visible = true, const std::string& time = "", float percent = 0.0f, float max_percent = 0.0f, const std::array<float, 2>& offsets = { 0.0f, 0.0f },
bool visible = true, const std::string& time = "", float percent = 0.0f, float max_percent = 0.0f, const std::array<float, 4>& offsets = { 0.0f, 0.0f, 0.0f, 0.0f },
std::function<void()> callback = nullptr) {
if (!visible)
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.3333f);
Expand Down Expand Up @@ -4166,12 +4166,21 @@ void GCodeViewer::render_legend() const
}
};

auto append_headers = [&imgui](const std::array<std::string, 3>& texts, const std::array<float, 2>& offsets) {
imgui.text(texts[0]);
ImGui::SameLine(offsets[0]);
imgui.text(texts[1]);
ImGui::SameLine(offsets[1]);
imgui.text(texts[2]);
//auto append_headers = [&imgui](const std::array<std::string, 3>& texts, const std::array<float, 2>& offsets) {
// imgui.text(texts[0]);
// ImGui::SameLine(offsets[0]);
// imgui.text(texts[1]);
// ImGui::SameLine(offsets[1]);
// imgui.text(texts[2]);
// ImGui::Separator();
//};
auto append_headers = [&imgui](const std::array<std::string, 5>& texts, const std::array<float, 4>& offsets) {
size_t i = 0;
for (; i < offsets.size(); i++) {
imgui.text(texts[i]);
ImGui::SameLine(offsets[i]);
}
imgui.text(texts[i]);
ImGui::Separator();
};

Expand All @@ -4183,12 +4192,21 @@ void GCodeViewer::render_legend() const
return ret;
};

//auto calculate_offsets = [max_width](const std::vector<std::string>& labels, const std::vector<std::string>& times,
// const std::array<std::string, 2>& titles, float extra_size = 0.0f) {
// const ImGuiStyle& style = ImGui::GetStyle();
// std::array<float, 2> ret = { 0.0f, 0.0f };
// ret[0] = max_width(labels, titles[0], extra_size) + 3.0f * style.ItemSpacing.x;
// ret[1] = ret[0] + max_width(times, titles[1]) + style.ItemSpacing.x;
// return ret;
//};
auto calculate_offsets = [max_width](const std::vector<std::string>& labels, const std::vector<std::string>& times,
const std::array<std::string, 2>& titles, float extra_size = 0.0f) {
const std::array<std::string, 4>& titles, float extra_size = 0.0f) {
const ImGuiStyle& style = ImGui::GetStyle();
std::array<float, 2> ret = { 0.0f, 0.0f };
std::array<float, 4> ret = { 0.0f, 0.0f, 0.0f, 0.0f };
ret[0] = max_width(labels, titles[0], extra_size) + 3.0f * style.ItemSpacing.x;
ret[1] = ret[0] + max_width(times, titles[1]) + style.ItemSpacing.x;
for (size_t i = 1; i < titles.size(); i++)
ret[i] = ret[i-1] + max_width(times, titles[i]) + style.ItemSpacing.x;
return ret;
};

Expand Down Expand Up @@ -4245,7 +4263,8 @@ void GCodeViewer::render_legend() const
};

// data used to properly align items in columns when showing time
std::array<float, 2> offsets = { 0.0f, 0.0f };
// std::array<float, 2> offsets = { 0.0f, 0.0f };
std::array<float, 4> offsets = { 0.0f, 0.0f, 0.0f, 0.0f };
std::vector<std::string> labels;
std::vector<std::string> times;
std::vector<float> percents;
Expand Down Expand Up @@ -4420,19 +4439,35 @@ void GCodeViewer::render_legend() const
Color color1;
Color color2;
Times times;
std::pair<double, double> used_filament {0.0f, 0.0f};
};
using PartialTimes = std::vector<PartialTime>;

auto generate_partial_times = [this](const TimesList& times) {
auto generate_partial_times = [this](const TimesList& times, const std::vector<float>& used_filaments) {
PartialTimes items;

auto get_used_filament = [](float volume, int extruder_id) {
const std::vector<std::string>& filament_presets = wxGetApp().preset_bundle->filament_presets;
const PresetCollection& filaments = wxGetApp().preset_bundle->filaments;
std::pair<double, double> ret = { 0.0f, 0.0f };
if (const Preset* filament_preset = filaments.find_preset(filament_presets[extruder_id], false)) {
double filament_radius = 0.5*filament_preset->config.opt_float("filament_diameter", 0);
double s = PI * sqr(filament_radius);
ret.first = volume / s * 0.001;
double filament_density = filament_preset->config.opt_float("filament_density", 0);
ret.second = volume * filament_density * 0.001;
}
return ret;
};

std::vector<CustomGCode::Item> custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
int extruders_count = wxGetApp().extruders_edited_cnt();
std::vector<Color> last_color(extruders_count);
for (int i = 0; i < extruders_count; ++i) {
last_color[i] = m_tool_colors[i];
}
int last_extruder_id = 1;
int color_change_idx = 0;
for (const auto& time_rec : times) {
switch (time_rec.first)
{
Expand All @@ -4448,14 +4483,14 @@ void GCodeViewer::render_legend() const
case CustomGCode::ColorChange: {
auto it = std::find_if(custom_gcode_per_print_z.begin(), custom_gcode_per_print_z.end(), [time_rec](const CustomGCode::Item& item) { return item.type == time_rec.first; });
if (it != custom_gcode_per_print_z.end()) {
items.push_back({ PartialTime::EType::Print, it->extruder, last_color[it->extruder - 1], Color(), time_rec.second });
items.push_back({ PartialTime::EType::Print, it->extruder, last_color[it->extruder - 1], Color(), time_rec.second, get_used_filament(used_filaments[color_change_idx++], it->extruder-1) });
items.push_back({ PartialTime::EType::ColorChange, it->extruder, last_color[it->extruder - 1], decode_color(it->color), time_rec.second });
last_color[it->extruder - 1] = decode_color(it->color);
last_extruder_id = it->extruder;
custom_gcode_per_print_z.erase(it);
}
else
items.push_back({ PartialTime::EType::Print, last_extruder_id, last_color[last_extruder_id - 1], Color(), time_rec.second });
items.push_back({ PartialTime::EType::Print, last_extruder_id, last_color[last_extruder_id - 1], Color(), time_rec.second, get_used_filament(used_filaments[color_change_idx++], last_extruder_id -1) });

break;
}
Expand All @@ -4466,7 +4501,8 @@ void GCodeViewer::render_legend() const
return items;
};

auto append_color_change = [&imgui](const Color& color1, const Color& color2, const std::array<float, 2>& offsets, const Times& times) {
// auto append_color_change = [&imgui](const Color& color1, const Color& color2, const std::array<float, 2>& offsets, const Times& times) {
auto append_color_change = [&imgui](const Color& color1, const Color& color2, const std::array<float, 4>& offsets, const Times& times) {
imgui.text(_u8L("Color change"));
ImGui::SameLine();

Expand All @@ -4485,7 +4521,8 @@ void GCodeViewer::render_legend() const
imgui.text(short_time(get_time_dhms(times.second - times.first)));
};

auto append_print = [&imgui](const Color& color, const std::array<float, 2>& offsets, const Times& times) {
// auto append_print = [&imgui](const Color& color, const std::array<float, 2>& offsets, const Times& times) {
auto append_print = [&imgui](const Color& color, const std::array<float, 4>& offsets, const Times& times, std::pair<double, double> used_filament) {
imgui.text(_u8L("Print"));
ImGui::SameLine();

Expand All @@ -4501,9 +4538,19 @@ void GCodeViewer::render_legend() const
imgui.text(short_time(get_time_dhms(times.second)));
ImGui::SameLine(offsets[1]);
imgui.text(short_time(get_time_dhms(times.first)));
if (used_filament.first > 0.0f) {
char buffer[64];
ImGui::SameLine(offsets[2]);
::sprintf(buffer, "%.2f m", used_filament.first);
imgui.text(buffer);

ImGui::SameLine(offsets[3]);
::sprintf(buffer, "%.2f g", used_filament.second);
imgui.text(buffer);
}
};

PartialTimes partial_times = generate_partial_times(time_mode.custom_gcode_times);
PartialTimes partial_times = generate_partial_times(time_mode.custom_gcode_times, time_mode.used_filaments);
if (!partial_times.empty()) {
labels.clear();
times.clear();
Expand All @@ -4517,10 +4564,12 @@ void GCodeViewer::render_legend() const
}
times.push_back(short_time(get_time_dhms(item.times.second)));
}
offsets = calculate_offsets(labels, times, { _u8L("Event"), _u8L("Remaining time") }, 2.0f * icon_size);
// offsets = calculate_offsets(labels, times, { _u8L("Event"), _u8L("Remaining time") }, 2.0f * icon_size);
offsets = calculate_offsets(labels, times, { _u8L("Event"), _u8L("Remaining time"), _u8L("Duration"), /*_u8L("Filament (m)")*/_u8L("Used filament") }, 2.0f * icon_size);

ImGui::Spacing();
append_headers({ _u8L("Event"), _u8L("Remaining time"), _u8L("Duration") }, offsets);
// append_headers({ _u8L("Event"), _u8L("Remaining time"), _u8L("Duration") }, offsets);
append_headers({ _u8L("Event"), _u8L("Remaining time"), _u8L("Duration"), /*_u8L("Filament (m)"), _u8L("Filament (g)")*/_u8L("Used filament") }, offsets);
#if ENABLE_SCROLLABLE_LEGEND
const bool need_scrollable = static_cast<float>(partial_times.size()) * (icon_size + ImGui::GetStyle().ItemSpacing.y) > child_height;
if (need_scrollable)
Expand All @@ -4532,7 +4581,7 @@ void GCodeViewer::render_legend() const
switch (item.type)
{
case PartialTime::EType::Print: {
append_print(item.color1, offsets, item.times);
append_print(item.color1, offsets, item.times, item.used_filament);
break;
}
case PartialTime::EType::Pause: {
Expand Down

0 comments on commit cb7d2c9

Please sign in to comment.