Fix of #2825 - Add the length of each filament used

This commit is contained in:
YuSanka 2021-04-21 14:57:43 +02:00 committed by Oleksandra Yushchenko
parent 56aa45fa1f
commit b9910669e8
9 changed files with 463 additions and 164 deletions

View File

@ -614,9 +614,44 @@ namespace DoExport {
static void update_print_estimated_times_stats(const GCodeProcessor& processor, PrintStatistics& print_statistics) static void update_print_estimated_times_stats(const GCodeProcessor& processor, PrintStatistics& print_statistics)
{ {
const GCodeProcessor::Result& result = processor.get_result(); const GCodeProcessor::Result& result = processor.get_result();
print_statistics.estimated_normal_print_time = get_time_dhms(result.time_statistics.modes[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Normal)].time); print_statistics.estimated_normal_print_time = get_time_dhms(result.print_statistics.modes[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].time);
print_statistics.estimated_silent_print_time = processor.is_stealth_time_estimator_enabled() ? print_statistics.estimated_silent_print_time = processor.is_stealth_time_estimator_enabled() ?
get_time_dhms(result.time_statistics.modes[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].time) : "N/A"; get_time_dhms(result.print_statistics.modes[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].time) : "N/A";
}
static void update_print_estimated_stats(const GCodeProcessor& processor, const std::vector<Extruder>& extruders, PrintStatistics& print_statistics)
{
const GCodeProcessor::Result& result = processor.get_result();
print_statistics.estimated_normal_print_time = get_time_dhms(result.print_statistics.modes[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].time);
print_statistics.estimated_silent_print_time = processor.is_stealth_time_estimator_enabled() ?
get_time_dhms(result.print_statistics.modes[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].time) : "N/A";
// update filament statictics
double total_extruded_volume = 0.0;
double total_used_filament = 0.0;
double total_weight = 0.0;
double total_cost = 0.0;
for (auto volume : result.print_statistics.volumes_per_extruder) {
total_extruded_volume += volume.second;
size_t extruder_id = volume.first;
auto extruder = std::find_if(extruders.begin(), extruders.end(), [extruder_id](const Extruder& extr) { return extr.id() == extruder_id; });
if (extruder == extruders.end())
continue;
double s = PI * sqr(0.5* extruder->filament_diameter());
double weight = volume.second * extruder->filament_density() * 0.001;
total_used_filament += volume.second/s;
total_weight += weight;
total_cost += weight * extruder->filament_cost() * 0.001;
}
print_statistics.total_extruded_volume = total_extruded_volume;
print_statistics.total_used_filament = total_used_filament;
print_statistics.total_weight = total_weight;
print_statistics.total_cost = total_cost;
print_statistics.filament_stats = result.print_statistics.volumes_per_extruder;
} }
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
@ -754,7 +789,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re
BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info(); BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info();
m_processor.process_file(path_tmp, true, [print]() { print->throw_if_canceled(); }); m_processor.process_file(path_tmp, true, [print]() { print->throw_if_canceled(); });
DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics); // DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics);
DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->m_print_statistics);
#if ENABLE_GCODE_WINDOW #if ENABLE_GCODE_WINDOW
if (result != nullptr) { if (result != nullptr) {
*result = std::move(m_processor.extract_result()); *result = std::move(m_processor.extract_result());
@ -957,7 +993,6 @@ namespace DoExport {
dst.first += buf; dst.first += buf;
++ dst.second; ++ dst.second;
}; };
print_statistics.filament_stats.insert(std::pair<size_t, float>{extruder.id(), (float)used_filament});
append(out_filament_used_mm, "%.2lf", used_filament); append(out_filament_used_mm, "%.2lf", used_filament);
append(out_filament_used_cm3, "%.2lf", extruded_volume * 0.001); append(out_filament_used_cm3, "%.2lf", extruded_volume * 0.001);
if (filament_weight > 0.) { if (filament_weight > 0.) {

View File

@ -186,6 +186,72 @@ void GCodeProcessor::TimeMachine::CustomGCodeTime::reset()
times = std::vector<std::pair<CustomGCode::Type, float>>(); times = std::vector<std::pair<CustomGCode::Type, float>>();
} }
void GCodeProcessor::UsedFilaments::reset()
{
color_change_cache = 0.0f;
volumes_per_color_change = std::vector<double>();
tool_change_cache = 0.0f;
volumes_per_extruder.clear();
role_cache = 0.0f;
filaments_per_role.clear();
}
void GCodeProcessor::UsedFilaments::increase_caches(double extruded_volume)
{
color_change_cache += extruded_volume;
tool_change_cache += extruded_volume;
role_cache += extruded_volume;
}
void GCodeProcessor::UsedFilaments::process_color_change_cache()
{
if (color_change_cache != 0.0f) {
volumes_per_color_change.push_back(color_change_cache);
color_change_cache = 0.0f;
}
}
void GCodeProcessor::UsedFilaments::process_extruder_cache(GCodeProcessor* processor)
{
size_t active_extruder_id = processor->m_extruder_id;
if (tool_change_cache != 0.0f) {
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;
}
}
void GCodeProcessor::UsedFilaments::process_role_cache(GCodeProcessor* processor)
{
if (role_cache != 0.0f) {
std::pair<double, double> filament = { 0.0f, 0.0f };
double s = PI * sqr(0.5 * processor->m_filament_diameters[processor->m_extruder_id]);
filament.first = role_cache/s * 0.001;
filament.second = role_cache * processor->m_filament_densities[processor->m_extruder_id] * 0.001;
ExtrusionRole active_role = processor->m_extrusion_role;
if (filaments_per_role.find(active_role) != filaments_per_role.end()) {
filaments_per_role[active_role].first += filament.first;
filaments_per_role[active_role].second += filament.second;
}
else
filaments_per_role[active_role] = filament;
role_cache = 0.0f;
}
}
void GCodeProcessor::UsedFilaments::process_caches(GCodeProcessor* processor)
{
process_color_change_cache();
process_extruder_cache(processor);
process_role_cache(processor);
}
void GCodeProcessor::TimeMachine::reset() void GCodeProcessor::TimeMachine::reset()
{ {
enabled = false; enabled = false;
@ -348,10 +414,10 @@ void GCodeProcessor::TimeProcessor::reset()
machine_limits = MachineEnvelopeConfig(); machine_limits = MachineEnvelopeConfig();
filament_load_times = std::vector<float>(); filament_load_times = std::vector<float>();
filament_unload_times = std::vector<float>(); filament_unload_times = std::vector<float>();
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
machines[i].reset(); machines[i].reset();
} }
machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Normal)].enabled = true; machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].enabled = true;
} }
#if ENABLE_GCODE_LINES_ID_IN_H_SLIDER #if ENABLE_GCODE_LINES_ID_IN_H_SLIDER
@ -416,19 +482,19 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
size_t g1_lines_counter = 0; size_t g1_lines_counter = 0;
// keeps track of last exported pair <percent, remaining time> // keeps track of last exported pair <percent, remaining time>
#if ENABLE_EXTENDED_M73_LINES #if ENABLE_EXTENDED_M73_LINES
std::array<std::pair<int, int>, static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count)> last_exported_main; 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>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
last_exported_main[i] = { 0, time_in_minutes(machines[i].time) }; last_exported_main[i] = { 0, time_in_minutes(machines[i].time) };
} }
// keeps track of last exported remaining time to next printer stop // keeps track of last exported remaining time to next printer stop
std::array<int, static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count)> last_exported_stop; std::array<int, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> last_exported_stop;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
last_exported_stop[i] = time_in_minutes(machines[i].time); last_exported_stop[i] = time_in_minutes(machines[i].time);
} }
#else #else
std::array<std::pair<int, int>, static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count)> last_exported; std::array<std::pair<int, int>, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> last_exported;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
last_exported[i] = { 0, time_in_minutes(machines[i].time) }; last_exported[i] = { 0, time_in_minutes(machines[i].time) };
} }
#endif // ENABLE_EXTENDED_M73_LINES #endif // ENABLE_EXTENDED_M73_LINES
@ -451,7 +517,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
line = line.substr(1); line = line.substr(1);
if (export_remaining_time_enabled && if (export_remaining_time_enabled &&
(line == reserved_tag(ETags::First_Line_M73_Placeholder) || line == reserved_tag(ETags::Last_Line_M73_Placeholder))) { (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>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
const TimeMachine& machine = machines[i]; const TimeMachine& machine = machines[i];
if (machine.enabled) { if (machine.enabled) {
#if ENABLE_EXTENDED_M73_LINES #if ENABLE_EXTENDED_M73_LINES
@ -486,7 +552,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
else if (line == reserved_tag(ETags::Estimated_Printing_Time_Placeholder)) { else if (line == reserved_tag(ETags::Estimated_Printing_Time_Placeholder)) {
#else #else
if (export_remaining_time_enabled && (line == First_Line_M73_Placeholder_Tag || line == Last_Line_M73_Placeholder_Tag)) { if (export_remaining_time_enabled && (line == First_Line_M73_Placeholder_Tag || line == Last_Line_M73_Placeholder_Tag)) {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
const TimeMachine& machine = machines[i]; const TimeMachine& machine = machines[i];
if (machine.enabled) { if (machine.enabled) {
ret += format_line_M73(machine.line_m73_mask.c_str(), ret += format_line_M73(machine.line_m73_mask.c_str(),
@ -497,13 +563,13 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
} }
else if (line == Estimated_Printing_Time_Placeholder_Tag) { else if (line == Estimated_Printing_Time_Placeholder_Tag) {
#endif // ENABLE_VALIDATE_CUSTOM_GCODE #endif // ENABLE_VALIDATE_CUSTOM_GCODE
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
const TimeMachine& machine = machines[i]; const TimeMachine& machine = machines[i];
PrintEstimatedTimeStatistics::ETimeMode mode = static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i); PrintEstimatedStatistics::ETimeMode mode = static_cast<PrintEstimatedStatistics::ETimeMode>(i);
if (mode == PrintEstimatedTimeStatistics::ETimeMode::Normal || machine.enabled) { if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
char buf[128]; char buf[128];
sprintf(buf, "; estimated printing time (%s mode) = %s\n", sprintf(buf, "; estimated printing time (%s mode) = %s\n",
(mode == PrintEstimatedTimeStatistics::ETimeMode::Normal) ? "normal" : "silent", (mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent",
get_time_dhms(machine.time).c_str()); get_time_dhms(machine.time).c_str());
ret += buf; ret += buf;
} }
@ -545,7 +611,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
unsigned int exported_lines_count = 0; unsigned int exported_lines_count = 0;
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER #endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
if (export_remaining_time_enabled) { if (export_remaining_time_enabled) {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
const TimeMachine& machine = machines[i]; const TimeMachine& machine = machines[i];
if (machine.enabled) { if (machine.enabled) {
// export pair <percent, remaining time> // export pair <percent, remaining time>
@ -789,13 +855,13 @@ GCodeProcessor::GCodeProcessor()
{ {
reset(); reset();
#if ENABLE_EXTENDED_M73_LINES #if ENABLE_EXTENDED_M73_LINES
m_time_processor.machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Normal)].line_m73_main_mask = "M73 P%s R%s\n"; m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_main_mask = "M73 P%s R%s\n";
m_time_processor.machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Normal)].line_m73_stop_mask = "M73 C%s\n"; m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_stop_mask = "M73 C%s\n";
m_time_processor.machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].line_m73_main_mask = "M73 Q%s S%s\n"; m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_main_mask = "M73 Q%s S%s\n";
m_time_processor.machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].line_m73_stop_mask = "M73 D%s\n"; m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_stop_mask = "M73 D%s\n";
#else #else
m_time_processor.machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Normal)].line_m73_mask = "M73 P%s R%s\n"; m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_mask = "M73 P%s R%s\n";
m_time_processor.machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].line_m73_mask = "M73 Q%s S%s\n"; m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_mask = "M73 Q%s S%s\n";
#endif // ENABLE_EXTENDED_M73_LINES #endif // ENABLE_EXTENDED_M73_LINES
} }
@ -826,6 +892,11 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_filament_diameters[i] = static_cast<float>(config.filament_diameter.values[i]); m_filament_diameters[i] = static_cast<float>(config.filament_diameter.values[i]);
} }
m_filament_densities.resize(config.filament_density.values.size());
for (size_t i = 0; i < config.filament_density.values.size(); ++i) {
m_filament_densities[i] = static_cast<float>(config.filament_density.values[i]);
}
if ((m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) && config.machine_limits_usage.value != MachineLimitsUsage::Ignore) { if ((m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) && config.machine_limits_usage.value != MachineLimitsUsage::Ignore) {
m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config); m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config);
if (m_flavor == gcfMarlinLegacy) { if (m_flavor == gcfMarlinLegacy) {
@ -846,7 +917,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_time_processor.filament_unload_times[i] = static_cast<float>(config.filament_unload_time.values[i]); m_time_processor.filament_unload_times[i] = static_cast<float>(config.filament_unload_time.values[i]);
} }
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i); float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i);
m_time_processor.machines[i].max_acceleration = max_acceleration; m_time_processor.machines[i].max_acceleration = max_acceleration;
m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION; m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION;
@ -896,6 +967,13 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
} }
} }
const ConfigOptionFloats* filament_densities = config.option<ConfigOptionFloats>("filament_density");
if (filament_densities != nullptr) {
for (double dens : filament_densities->values) {
m_filament_densities.push_back(static_cast<float>(dens));
}
}
m_result.extruders_count = config.option<ConfigOptionFloats>("nozzle_diameter")->values.size(); m_result.extruders_count = config.option<ConfigOptionFloats>("nozzle_diameter")->values.size();
const ConfigOptionPoints* extruder_offset = config.option<ConfigOptionPoints>("extruder_offset"); const ConfigOptionPoints* extruder_offset = config.option<ConfigOptionPoints>("extruder_offset");
@ -1026,7 +1104,7 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
m_time_processor.machine_limits.machine_min_travel_rate.values = machine_min_travel_rate->values; m_time_processor.machine_limits.machine_min_travel_rate.values = machine_min_travel_rate->values;
} }
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i); float max_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_extruding, i);
m_time_processor.machines[i].max_acceleration = max_acceleration; m_time_processor.machines[i].max_acceleration = max_acceleration;
m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION; m_time_processor.machines[i].acceleration = (max_acceleration > 0.0f) ? max_acceleration : DEFAULT_ACCELERATION;
@ -1051,7 +1129,7 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
void GCodeProcessor::enable_stealth_time_estimator(bool enabled) void GCodeProcessor::enable_stealth_time_estimator(bool enabled)
{ {
m_time_processor.machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].enabled = enabled; m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled = enabled;
} }
void GCodeProcessor::reset() void GCodeProcessor::reset()
@ -1096,6 +1174,7 @@ void GCodeProcessor::reset()
} }
m_filament_diameters = std::vector<float>(Min_Extruder_Count, 1.75f); m_filament_diameters = std::vector<float>(Min_Extruder_Count, 1.75f);
m_filament_densities = std::vector<float>(Min_Extruder_Count, 1.245f);
m_extruded_last_z = 0.0f; m_extruded_last_z = 0.0f;
#if ENABLE_START_GCODE_VISUALIZATION #if ENABLE_START_GCODE_VISUALIZATION
m_first_layer_height = 0.0f; m_first_layer_height = 0.0f;
@ -1109,6 +1188,7 @@ void GCodeProcessor::reset()
m_producers_enabled = false; m_producers_enabled = false;
m_time_processor.reset(); m_time_processor.reset();
m_used_filaments.reset();
m_result.reset(); m_result.reset();
m_result.id = ++s_result_id; m_result.id = ++s_result_id;
@ -1186,7 +1266,7 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
} }
// process the time blocks // process the time blocks
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
TimeMachine& machine = m_time_processor.machines[i]; TimeMachine& machine = m_time_processor.machines[i];
TimeMachine::CustomGCodeTime& gcode_time = machine.gcode_time; TimeMachine::CustomGCodeTime& gcode_time = machine.gcode_time;
machine.calculate_time(); machine.calculate_time();
@ -1194,6 +1274,8 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
gcode_time.times.push_back({ CustomGCode::ColorChange, gcode_time.cache }); gcode_time.times.push_back({ CustomGCode::ColorChange, gcode_time.cache });
} }
m_used_filaments.process_caches(this);
update_estimated_times_stats(); update_estimated_times_stats();
// post-process to add M73 lines into the gcode // post-process to add M73 lines into the gcode
@ -1216,20 +1298,20 @@ void GCodeProcessor::process_file(const std::string& filename, bool apply_postpr
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
} }
float GCodeProcessor::get_time(PrintEstimatedTimeStatistics::ETimeMode mode) const float GCodeProcessor::get_time(PrintEstimatedStatistics::ETimeMode mode) const
{ {
return (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) ? m_time_processor.machines[static_cast<size_t>(mode)].time : 0.0f; return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? m_time_processor.machines[static_cast<size_t>(mode)].time : 0.0f;
} }
std::string GCodeProcessor::get_time_dhm(PrintEstimatedTimeStatistics::ETimeMode mode) const std::string GCodeProcessor::get_time_dhm(PrintEstimatedStatistics::ETimeMode mode) const
{ {
return (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast<size_t>(mode)].time)) : std::string("N/A"); return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast<size_t>(mode)].time)) : std::string("N/A");
} }
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> GCodeProcessor::get_custom_gcode_times(PrintEstimatedTimeStatistics::ETimeMode mode, bool include_remaining) const std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> GCodeProcessor::get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const
{ {
std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> ret; std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> ret;
if (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) { if (mode < PrintEstimatedStatistics::ETimeMode::Count) {
const TimeMachine& machine = m_time_processor.machines[static_cast<size_t>(mode)]; const TimeMachine& machine = m_time_processor.machines[static_cast<size_t>(mode)];
float total_time = 0.0f; float total_time = 0.0f;
for (const auto& [type, time] : machine.gcode_time.times) { for (const auto& [type, time] : machine.gcode_time.times) {
@ -1241,10 +1323,10 @@ std::vector<std::pair<CustomGCode::Type, std::pair<float, float>>> GCodeProcesso
return ret; return ret;
} }
std::vector<std::pair<EMoveType, float>> GCodeProcessor::get_moves_time(PrintEstimatedTimeStatistics::ETimeMode mode) const std::vector<std::pair<EMoveType, float>> GCodeProcessor::get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const
{ {
std::vector<std::pair<EMoveType, float>> ret; std::vector<std::pair<EMoveType, float>> ret;
if (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) { if (mode < PrintEstimatedStatistics::ETimeMode::Count) {
for (size_t i = 0; i < m_time_processor.machines[static_cast<size_t>(mode)].moves_time.size(); ++i) { for (size_t i = 0; i < m_time_processor.machines[static_cast<size_t>(mode)].moves_time.size(); ++i) {
float time = m_time_processor.machines[static_cast<size_t>(mode)].moves_time[i]; float time = m_time_processor.machines[static_cast<size_t>(mode)].moves_time[i];
if (time > 0.0f) if (time > 0.0f)
@ -1254,10 +1336,10 @@ std::vector<std::pair<EMoveType, float>> GCodeProcessor::get_moves_time(PrintEst
return ret; return ret;
} }
std::vector<std::pair<ExtrusionRole, float>> GCodeProcessor::get_roles_time(PrintEstimatedTimeStatistics::ETimeMode mode) const std::vector<std::pair<ExtrusionRole, float>> GCodeProcessor::get_roles_time(PrintEstimatedStatistics::ETimeMode mode) const
{ {
std::vector<std::pair<ExtrusionRole, float>> ret; std::vector<std::pair<ExtrusionRole, float>> ret;
if (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) { if (mode < PrintEstimatedStatistics::ETimeMode::Count) {
for (size_t i = 0; i < m_time_processor.machines[static_cast<size_t>(mode)].roles_time.size(); ++i) { for (size_t i = 0; i < m_time_processor.machines[static_cast<size_t>(mode)].roles_time.size(); ++i) {
float time = m_time_processor.machines[static_cast<size_t>(mode)].roles_time[i]; float time = m_time_processor.machines[static_cast<size_t>(mode)].roles_time[i];
if (time > 0.0f) if (time > 0.0f)
@ -1267,9 +1349,9 @@ std::vector<std::pair<ExtrusionRole, float>> GCodeProcessor::get_roles_time(Prin
return ret; return ret;
} }
std::vector<float> GCodeProcessor::get_layers_time(PrintEstimatedTimeStatistics::ETimeMode mode) const std::vector<float> GCodeProcessor::get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const
{ {
return (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) ? return (mode < PrintEstimatedStatistics::ETimeMode::Count) ?
m_time_processor.machines[static_cast<size_t>(mode)].layers_time : m_time_processor.machines[static_cast<size_t>(mode)].layers_time :
std::vector<float>(); std::vector<float>();
} }
@ -1461,6 +1543,7 @@ void GCodeProcessor::process_tags(const std::string_view comment)
#if ENABLE_VALIDATE_CUSTOM_GCODE #if ENABLE_VALIDATE_CUSTOM_GCODE
// extrusion role tag // extrusion role tag
if (boost::starts_with(comment, reserved_tag(ETags::Role))) { if (boost::starts_with(comment, reserved_tag(ETags::Role))) {
m_used_filaments.process_role_cache(this);
m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length())); m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length()));
#if ENABLE_SEAMS_VISUALIZATION #if ENABLE_SEAMS_VISUALIZATION
if (m_extrusion_role == erExternalPerimeter) if (m_extrusion_role == erExternalPerimeter)
@ -1546,7 +1629,8 @@ void GCodeProcessor::process_tags(const std::string_view comment)
extruder_id = static_cast<unsigned char>(eid); 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; ++m_cp_color.counter;
if (m_cp_color.counter == UCHAR_MAX) if (m_cp_color.counter == UCHAR_MAX)
m_cp_color.counter = 0; m_cp_color.counter = 0;
@ -1557,6 +1641,7 @@ void GCodeProcessor::process_tags(const std::string_view comment)
} }
process_custom_gcode_time(CustomGCode::ColorChange); process_custom_gcode_time(CustomGCode::ColorChange);
process_filaments(CustomGCode::ColorChange);
return; return;
} }
@ -2194,6 +2279,9 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
float volume_extruded_filament = area_filament_cross_section * delta_pos[E]; float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
float area_toolpath_cross_section = volume_extruded_filament / delta_xyz; float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
// save extruded volume to the cache
m_used_filaments.increase_caches(volume_extruded_filament);
// volume extruded filament / tool displacement = area toolpath cross section // volume extruded filament / tool displacement = area toolpath cross section
m_mm3_per_mm = area_toolpath_cross_section; m_mm3_per_mm = area_toolpath_cross_section;
#if ENABLE_GCODE_VIEWER_DATA_CHECKING #if ENABLE_GCODE_VIEWER_DATA_CHECKING
@ -2254,7 +2342,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
assert(distance != 0.0f); assert(distance != 0.0f);
float inv_distance = 1.0f / distance; float inv_distance = 1.0f / distance;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
TimeMachine& machine = m_time_processor.machines[i]; TimeMachine& machine = m_time_processor.machines[i];
if (!machine.enabled) if (!machine.enabled)
continue; continue;
@ -2264,8 +2352,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
std::vector<TimeBlock>& blocks = machine.blocks; std::vector<TimeBlock>& blocks = machine.blocks;
curr.feedrate = (delta_pos[E] == 0.0f) ? curr.feedrate = (delta_pos[E] == 0.0f) ?
minimum_travel_feedrate(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), m_feedrate) : minimum_travel_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), m_feedrate) :
minimum_feedrate(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), m_feedrate); minimum_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), m_feedrate);
TimeBlock block; TimeBlock block;
block.move_type = type; block.move_type = type;
@ -2283,7 +2371,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]); curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]);
if (curr.abs_axis_feedrate[a] != 0.0f) { if (curr.abs_axis_feedrate[a] != 0.0f) {
float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), static_cast<Axis>(a)); float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
if (axis_max_feedrate != 0.0f) if (axis_max_feedrate != 0.0f)
min_feedrate_factor = std::min(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]); min_feedrate_factor = std::min(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
} }
@ -2300,13 +2388,13 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// calculates block acceleration // calculates block acceleration
float acceleration = float acceleration =
(type == EMoveType::Travel) ? get_travel_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i)) : (type == EMoveType::Travel) ? get_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)) :
(is_extrusion_only_move(delta_pos) ? (is_extrusion_only_move(delta_pos) ?
get_retract_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i)) : get_retract_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)) :
get_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i))); get_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)));
for (unsigned char a = X; a <= E; ++a) { for (unsigned char a = X; a <= E; ++a) {
float axis_max_acceleration = get_axis_max_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), static_cast<Axis>(a)); float axis_max_acceleration = get_axis_max_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
if (acceleration * std::abs(delta_pos[a]) * inv_distance > axis_max_acceleration) if (acceleration * std::abs(delta_pos[a]) * inv_distance > axis_max_acceleration)
acceleration = axis_max_acceleration; acceleration = axis_max_acceleration;
} }
@ -2317,7 +2405,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
curr.safe_feedrate = block.feedrate_profile.cruise; curr.safe_feedrate = block.feedrate_profile.cruise;
for (unsigned char a = X; a <= E; ++a) { for (unsigned char a = X; a <= E; ++a) {
float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), static_cast<Axis>(a)); float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
if (curr.abs_axis_feedrate[a] > axis_max_jerk) if (curr.abs_axis_feedrate[a] > axis_max_jerk)
curr.safe_feedrate = std::min(curr.safe_feedrate, axis_max_jerk); curr.safe_feedrate = std::min(curr.safe_feedrate, axis_max_jerk);
} }
@ -2365,7 +2453,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
// axis reversal // axis reversal
std::max(-v_exit, v_entry)); std::max(-v_exit, v_entry));
float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), static_cast<Axis>(a)); float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
if (jerk > axis_max_jerk) { if (jerk > axis_max_jerk) {
v_factor *= axis_max_jerk / jerk; v_factor *= axis_max_jerk / jerk;
limited = true; limited = true;
@ -2650,8 +2738,8 @@ void GCodeProcessor::process_M201(const GCodeReader::GCodeLine& line)
// see http://reprap.org/wiki/G-code#M201:_Set_max_printing_acceleration // see http://reprap.org/wiki/G-code#M201:_Set_max_printing_acceleration
float factor = ((m_flavor != gcfRepRapSprinter && m_flavor != gcfRepRapFirmware) && m_units == EUnits::Inches) ? INCHES_TO_MM : 1.0f; float factor = ((m_flavor != gcfRepRapSprinter && m_flavor != gcfRepRapFirmware) && m_units == EUnits::Inches) ? INCHES_TO_MM : 1.0f;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
if (static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal || if (static_cast<PrintEstimatedStatistics::ETimeMode>(i) == PrintEstimatedStatistics::ETimeMode::Normal ||
m_time_processor.machine_envelope_processing_enabled) { m_time_processor.machine_envelope_processing_enabled) {
if (line.has_x()) if (line.has_x())
set_option_value(m_time_processor.machine_limits.machine_max_acceleration_x, i, line.x() * factor); set_option_value(m_time_processor.machine_limits.machine_max_acceleration_x, i, line.x() * factor);
@ -2678,8 +2766,8 @@ void GCodeProcessor::process_M203(const GCodeReader::GCodeLine& line)
// http://smoothieware.org/supported-g-codes // http://smoothieware.org/supported-g-codes
float factor = (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfSmoothie) ? 1.0f : MMMIN_TO_MMSEC; float factor = (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfSmoothie) ? 1.0f : MMMIN_TO_MMSEC;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
if (static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal || if (static_cast<PrintEstimatedStatistics::ETimeMode>(i) == PrintEstimatedStatistics::ETimeMode::Normal ||
m_time_processor.machine_envelope_processing_enabled) { m_time_processor.machine_envelope_processing_enabled) {
if (line.has_x()) if (line.has_x())
set_option_value(m_time_processor.machine_limits.machine_max_feedrate_x, i, line.x() * factor); set_option_value(m_time_processor.machine_limits.machine_max_feedrate_x, i, line.x() * factor);
@ -2699,27 +2787,27 @@ void GCodeProcessor::process_M203(const GCodeReader::GCodeLine& line)
void GCodeProcessor::process_M204(const GCodeReader::GCodeLine& line) void GCodeProcessor::process_M204(const GCodeReader::GCodeLine& line)
{ {
float value; float value;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
if (static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal || if (static_cast<PrintEstimatedStatistics::ETimeMode>(i) == PrintEstimatedStatistics::ETimeMode::Normal ||
m_time_processor.machine_envelope_processing_enabled) { m_time_processor.machine_envelope_processing_enabled) {
if (line.has_value('S', value)) { if (line.has_value('S', value)) {
// Legacy acceleration format. This format is used by the legacy Marlin, MK2 or MK3 firmware // Legacy acceleration format. This format is used by the legacy Marlin, MK2 or MK3 firmware
// It is also generated by PrusaSlicer to control acceleration per extrusion type // It is also generated by PrusaSlicer to control acceleration per extrusion type
// (perimeters, first layer etc) when 'Marlin (legacy)' flavor is used. // (perimeters, first layer etc) when 'Marlin (legacy)' flavor is used.
set_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), value); set_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
set_travel_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), value); set_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
if (line.has_value('T', value)) if (line.has_value('T', value))
set_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i, value); set_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i, value);
} }
else { else {
// New acceleration format, compatible with the upstream Marlin. // New acceleration format, compatible with the upstream Marlin.
if (line.has_value('P', value)) if (line.has_value('P', value))
set_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), value); set_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
if (line.has_value('R', value)) if (line.has_value('R', value))
set_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i, value); set_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i, value);
if (line.has_value('T', value)) if (line.has_value('T', value))
// Interpret the T value as the travel acceleration in the new Marlin format. // Interpret the T value as the travel acceleration in the new Marlin format.
set_travel_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), value); set_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
} }
} }
} }
@ -2727,8 +2815,8 @@ void GCodeProcessor::process_M204(const GCodeReader::GCodeLine& line)
void GCodeProcessor::process_M205(const GCodeReader::GCodeLine& line) void GCodeProcessor::process_M205(const GCodeReader::GCodeLine& line)
{ {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
if (static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal || if (static_cast<PrintEstimatedStatistics::ETimeMode>(i) == PrintEstimatedStatistics::ETimeMode::Normal ||
m_time_processor.machine_envelope_processing_enabled) { m_time_processor.machine_envelope_processing_enabled) {
if (line.has_x()) { if (line.has_x()) {
float max_jerk = line.x(); float max_jerk = line.x();
@ -2761,7 +2849,7 @@ void GCodeProcessor::process_M221(const GCodeReader::GCodeLine& line)
float value_t; float value_t;
if (line.has_value('S', value_s) && !line.has_value('T', value_t)) { if (line.has_value('S', value_s) && !line.has_value('T', value_t)) {
value_s *= 0.01f; value_s *= 0.01f;
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
m_time_processor.machines[i].extrude_factor_override_percentage = value_s; m_time_processor.machines[i].extrude_factor_override_percentage = value_s;
} }
} }
@ -2812,7 +2900,7 @@ void GCodeProcessor::process_M402(const GCodeReader::GCodeLine& line)
void GCodeProcessor::process_M566(const GCodeReader::GCodeLine& line) void GCodeProcessor::process_M566(const GCodeReader::GCodeLine& line)
{ {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
if (line.has_x()) if (line.has_x())
set_option_value(m_time_processor.machine_limits.machine_max_jerk_x, i, line.x() * MMMIN_TO_MMSEC); set_option_value(m_time_processor.machine_limits.machine_max_jerk_x, i, line.x() * MMMIN_TO_MMSEC);
@ -2863,6 +2951,7 @@ void GCodeProcessor::process_T(const std::string_view command)
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange, maybe from a custom gcode."; BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid toolchange, maybe from a custom gcode.";
else { else {
unsigned char old_extruder_id = m_extruder_id; unsigned char old_extruder_id = m_extruder_id;
process_filaments(CustomGCode::ToolChange);
m_extruder_id = id; m_extruder_id = id;
m_cp_color.current = m_extruder_colors[id]; m_cp_color.current = m_extruder_colors[id];
// Specific to the MK3 MMU2: // Specific to the MK3 MMU2:
@ -2920,7 +3009,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
#if ENABLE_EXTENDED_M73_LINES #if ENABLE_EXTENDED_M73_LINES
// stores stop time placeholders for later use // stores stop time placeholders for later use
if (type == EMoveType::Color_change || type == EMoveType::Pause_Print) { if (type == EMoveType::Color_change || type == EMoveType::Pause_Print) {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
TimeMachine& machine = m_time_processor.machines[i]; TimeMachine& machine = m_time_processor.machines[i];
if (!machine.enabled) if (!machine.enabled)
continue; continue;
@ -2931,7 +3020,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
#endif // ENABLE_EXTENDED_M73_LINES #endif // ENABLE_EXTENDED_M73_LINES
} }
float GCodeProcessor::minimum_feedrate(PrintEstimatedTimeStatistics::ETimeMode mode, float feedrate) const float GCodeProcessor::minimum_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const
{ {
if (m_time_processor.machine_limits.machine_min_extruding_rate.empty()) if (m_time_processor.machine_limits.machine_min_extruding_rate.empty())
return feedrate; return feedrate;
@ -2939,7 +3028,7 @@ float GCodeProcessor::minimum_feedrate(PrintEstimatedTimeStatistics::ETimeMode m
return std::max(feedrate, get_option_value(m_time_processor.machine_limits.machine_min_extruding_rate, static_cast<size_t>(mode))); return std::max(feedrate, get_option_value(m_time_processor.machine_limits.machine_min_extruding_rate, static_cast<size_t>(mode)));
} }
float GCodeProcessor::minimum_travel_feedrate(PrintEstimatedTimeStatistics::ETimeMode mode, float feedrate) const float GCodeProcessor::minimum_travel_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const
{ {
if (m_time_processor.machine_limits.machine_min_travel_rate.empty()) if (m_time_processor.machine_limits.machine_min_travel_rate.empty())
return feedrate; return feedrate;
@ -2947,7 +3036,7 @@ float GCodeProcessor::minimum_travel_feedrate(PrintEstimatedTimeStatistics::ETim
return std::max(feedrate, get_option_value(m_time_processor.machine_limits.machine_min_travel_rate, static_cast<size_t>(mode))); return std::max(feedrate, get_option_value(m_time_processor.machine_limits.machine_min_travel_rate, static_cast<size_t>(mode)));
} }
float GCodeProcessor::get_axis_max_feedrate(PrintEstimatedTimeStatistics::ETimeMode mode, Axis axis) const float GCodeProcessor::get_axis_max_feedrate(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const
{ {
switch (axis) switch (axis)
{ {
@ -2959,7 +3048,7 @@ float GCodeProcessor::get_axis_max_feedrate(PrintEstimatedTimeStatistics::ETimeM
} }
} }
float GCodeProcessor::get_axis_max_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, Axis axis) const float GCodeProcessor::get_axis_max_acceleration(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const
{ {
switch (axis) switch (axis)
{ {
@ -2971,7 +3060,7 @@ float GCodeProcessor::get_axis_max_acceleration(PrintEstimatedTimeStatistics::ET
} }
} }
float GCodeProcessor::get_axis_max_jerk(PrintEstimatedTimeStatistics::ETimeMode mode, Axis axis) const float GCodeProcessor::get_axis_max_jerk(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const
{ {
switch (axis) switch (axis)
{ {
@ -2983,18 +3072,18 @@ float GCodeProcessor::get_axis_max_jerk(PrintEstimatedTimeStatistics::ETimeMode
} }
} }
float GCodeProcessor::get_retract_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const float GCodeProcessor::get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
{ {
return get_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, static_cast<size_t>(mode)); return get_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, static_cast<size_t>(mode));
} }
float GCodeProcessor::get_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const float GCodeProcessor::get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
{ {
size_t id = static_cast<size_t>(mode); size_t id = static_cast<size_t>(mode);
return (id < m_time_processor.machines.size()) ? m_time_processor.machines[id].acceleration : DEFAULT_ACCELERATION; return (id < m_time_processor.machines.size()) ? m_time_processor.machines[id].acceleration : DEFAULT_ACCELERATION;
} }
void GCodeProcessor::set_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, float value) void GCodeProcessor::set_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value)
{ {
size_t id = static_cast<size_t>(mode); size_t id = static_cast<size_t>(mode);
if (id < m_time_processor.machines.size()) { if (id < m_time_processor.machines.size()) {
@ -3004,13 +3093,13 @@ void GCodeProcessor::set_acceleration(PrintEstimatedTimeStatistics::ETimeMode mo
} }
} }
float GCodeProcessor::get_travel_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const float GCodeProcessor::get_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
{ {
size_t id = static_cast<size_t>(mode); size_t id = static_cast<size_t>(mode);
return (id < m_time_processor.machines.size()) ? m_time_processor.machines[id].travel_acceleration : DEFAULT_TRAVEL_ACCELERATION; return (id < m_time_processor.machines.size()) ? m_time_processor.machines[id].travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
} }
void GCodeProcessor::set_travel_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, float value) void GCodeProcessor::set_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value)
{ {
size_t id = static_cast<size_t>(mode); size_t id = static_cast<size_t>(mode);
if (id < m_time_processor.machines.size()) { if (id < m_time_processor.machines.size()) {
@ -3038,7 +3127,7 @@ float GCodeProcessor::get_filament_unload_time(size_t extruder_id)
void GCodeProcessor::process_custom_gcode_time(CustomGCode::Type code) void GCodeProcessor::process_custom_gcode_time(CustomGCode::Type code)
{ {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
TimeMachine& machine = m_time_processor.machines[i]; TimeMachine& machine = m_time_processor.machines[i];
if (!machine.enabled) if (!machine.enabled)
continue; continue;
@ -3055,17 +3144,26 @@ void GCodeProcessor::process_custom_gcode_time(CustomGCode::Type code)
} }
} }
void GCodeProcessor::process_filaments(CustomGCode::Type code)
{
if (code == CustomGCode::ColorChange)
m_used_filaments.process_color_change_cache();
if (code == CustomGCode::ToolChange)
m_used_filaments.process_extruder_cache(this);
}
void GCodeProcessor::simulate_st_synchronize(float additional_time) void GCodeProcessor::simulate_st_synchronize(float additional_time)
{ {
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
m_time_processor.machines[i].simulate_st_synchronize(additional_time); m_time_processor.machines[i].simulate_st_synchronize(additional_time);
} }
} }
void GCodeProcessor::update_estimated_times_stats() void GCodeProcessor::update_estimated_times_stats()
{ {
auto update_mode = [this](PrintEstimatedTimeStatistics::ETimeMode mode) { auto update_mode = [this](PrintEstimatedStatistics::ETimeMode mode) {
PrintEstimatedTimeStatistics::Mode& data = m_result.time_statistics.modes[static_cast<size_t>(mode)]; PrintEstimatedStatistics::Mode& data = m_result.print_statistics.modes[static_cast<size_t>(mode)];
data.time = get_time(mode); data.time = get_time(mode);
data.custom_gcode_times = get_custom_gcode_times(mode, true); data.custom_gcode_times = get_custom_gcode_times(mode, true);
data.moves_times = get_moves_time(mode); data.moves_times = get_moves_time(mode);
@ -3073,11 +3171,15 @@ void GCodeProcessor::update_estimated_times_stats()
data.layers_times = get_layers_time(mode); data.layers_times = get_layers_time(mode);
}; };
update_mode(PrintEstimatedTimeStatistics::ETimeMode::Normal); update_mode(PrintEstimatedStatistics::ETimeMode::Normal);
if (m_time_processor.machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].enabled) if (m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled)
update_mode(PrintEstimatedTimeStatistics::ETimeMode::Stealth); update_mode(PrintEstimatedStatistics::ETimeMode::Stealth);
else else
m_result.time_statistics.modes[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].reset(); m_result.print_statistics.modes[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].reset();
m_result.print_statistics.volumes_per_color_change = m_used_filaments.volumes_per_color_change;
m_result.print_statistics.volumes_per_extruder = m_used_filaments.volumes_per_extruder;
m_result.print_statistics.used_filaments_per_role = m_used_filaments.filaments_per_role;
} }
} /* namespace Slic3r */ } /* namespace Slic3r */

View File

@ -36,7 +36,7 @@ namespace Slic3r {
Count Count
}; };
struct PrintEstimatedTimeStatistics struct PrintEstimatedStatistics
{ {
enum class ETimeMode : unsigned char enum class ETimeMode : unsigned char
{ {
@ -62,14 +62,21 @@ 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;
std::array<Mode, static_cast<size_t>(ETimeMode::Count)> modes; std::array<Mode, static_cast<size_t>(ETimeMode::Count)> modes;
PrintEstimatedTimeStatistics() { reset(); } PrintEstimatedStatistics() { reset(); }
void reset() { void reset() {
for (auto m : modes) { for (auto m : modes) {
m.reset(); m.reset();
} }
volumes_per_color_change.clear();
volumes_per_extruder.clear();
used_filaments_per_role.clear();
} }
}; };
@ -314,7 +321,7 @@ namespace Slic3r {
// Additional load / unload times for a filament exchange sequence. // Additional load / unload times for a filament exchange sequence.
std::vector<float> filament_load_times; std::vector<float> filament_load_times;
std::vector<float> filament_unload_times; std::vector<float> filament_unload_times;
std::array<TimeMachine, static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count)> machines; std::array<TimeMachine, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> machines;
void reset(); void reset();
@ -327,6 +334,30 @@ namespace Slic3r {
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER #endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
}; };
struct UsedFilaments // filaments per ColorChange
{
double color_change_cache;
std::vector<double> volumes_per_color_change;
double tool_change_cache;
std::map<size_t, double> volumes_per_extruder;
double role_cache;
// ExtrusionRole : <used_filament_m, used_filament_g>
std::map<ExtrusionRole, std::pair<double, double>> filaments_per_role;
void reset();
void increase_caches(double extruded_volume);
void process_color_change_cache();
void process_extruder_cache(GCodeProcessor* processor);
void process_role_cache(GCodeProcessor* processor);
void process_caches(GCodeProcessor* processor);
friend class GCodeProcessor;
};
public: public:
#if !ENABLE_GCODE_LINES_ID_IN_H_SLIDER #if !ENABLE_GCODE_LINES_ID_IN_H_SLIDER
struct MoveVertex struct MoveVertex
@ -372,7 +403,7 @@ namespace Slic3r {
SettingsIds settings_ids; SettingsIds settings_ids;
size_t extruders_count; size_t extruders_count;
std::vector<std::string> extruder_colors; std::vector<std::string> extruder_colors;
PrintEstimatedTimeStatistics time_statistics; PrintEstimatedStatistics print_statistics;
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
int64_t time{ 0 }; int64_t time{ 0 };
@ -519,6 +550,7 @@ namespace Slic3r {
ExtruderColors m_extruder_colors; ExtruderColors m_extruder_colors;
ExtruderTemps m_extruder_temps; ExtruderTemps m_extruder_temps;
std::vector<float> m_filament_diameters; std::vector<float> m_filament_diameters;
std::vector<float> m_filament_densities;
float m_extruded_last_z; float m_extruded_last_z;
#if ENABLE_START_GCODE_VISUALIZATION #if ENABLE_START_GCODE_VISUALIZATION
float m_first_layer_height; // mm float m_first_layer_height; // mm
@ -550,6 +582,7 @@ namespace Slic3r {
bool m_producers_enabled; bool m_producers_enabled;
TimeProcessor m_time_processor; TimeProcessor m_time_processor;
UsedFilaments m_used_filaments;
Result m_result; Result m_result;
static unsigned int s_result_id; static unsigned int s_result_id;
@ -566,7 +599,7 @@ namespace Slic3r {
void apply_config(const PrintConfig& config); void apply_config(const PrintConfig& config);
void enable_stealth_time_estimator(bool enabled); void enable_stealth_time_estimator(bool enabled);
bool is_stealth_time_estimator_enabled() const { bool is_stealth_time_estimator_enabled() const {
return m_time_processor.machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].enabled; return m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled;
} }
void enable_machine_envelope_processing(bool enabled) { m_time_processor.machine_envelope_processing_enabled = enabled; } void enable_machine_envelope_processing(bool enabled) { m_time_processor.machine_envelope_processing_enabled = enabled; }
void enable_producers(bool enabled) { m_producers_enabled = enabled; } void enable_producers(bool enabled) { m_producers_enabled = enabled; }
@ -579,13 +612,13 @@ namespace Slic3r {
// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback). // throws CanceledException through print->throw_if_canceled() (sent by the caller as callback).
void process_file(const std::string& filename, bool apply_postprocess, std::function<void()> cancel_callback = nullptr); void process_file(const std::string& filename, bool apply_postprocess, std::function<void()> cancel_callback = nullptr);
float get_time(PrintEstimatedTimeStatistics::ETimeMode mode) const; float get_time(PrintEstimatedStatistics::ETimeMode mode) const;
std::string get_time_dhm(PrintEstimatedTimeStatistics::ETimeMode mode) const; std::string get_time_dhm(PrintEstimatedStatistics::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<std::pair<CustomGCode::Type, std::pair<float, float>>> get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const;
std::vector<std::pair<EMoveType, float>> get_moves_time(PrintEstimatedTimeStatistics::ETimeMode mode) const; std::vector<std::pair<EMoveType, float>> get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const;
std::vector<std::pair<ExtrusionRole, float>> get_roles_time(PrintEstimatedTimeStatistics::ETimeMode mode) const; std::vector<std::pair<ExtrusionRole, float>> get_roles_time(PrintEstimatedStatistics::ETimeMode mode) const;
std::vector<float> get_layers_time(PrintEstimatedTimeStatistics::ETimeMode mode) const; std::vector<float> get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const;
private: private:
void apply_config(const DynamicPrintConfig& config); void apply_config(const DynamicPrintConfig& config);
@ -701,20 +734,21 @@ namespace Slic3r {
void store_move_vertex(EMoveType type); void store_move_vertex(EMoveType type);
float minimum_feedrate(PrintEstimatedTimeStatistics::ETimeMode mode, float feedrate) const; float minimum_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const;
float minimum_travel_feedrate(PrintEstimatedTimeStatistics::ETimeMode mode, float feedrate) const; float minimum_travel_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const;
float get_axis_max_feedrate(PrintEstimatedTimeStatistics::ETimeMode mode, Axis axis) const; float get_axis_max_feedrate(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
float get_axis_max_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, Axis axis) const; float get_axis_max_acceleration(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
float get_axis_max_jerk(PrintEstimatedTimeStatistics::ETimeMode mode, Axis axis) const; float get_axis_max_jerk(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
float get_retract_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const; float get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
float get_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const; float get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
void set_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, float value); void set_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value);
float get_travel_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const; float get_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
void set_travel_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, float value); void set_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value);
float get_filament_load_time(size_t extruder_id); float get_filament_load_time(size_t extruder_id);
float get_filament_unload_time(size_t extruder_id); float get_filament_unload_time(size_t extruder_id);
void process_custom_gcode_time(CustomGCode::Type code); void process_custom_gcode_time(CustomGCode::Type code);
void process_filaments(CustomGCode::Type code);
// Simulates firmware st_synchronize() call // Simulates firmware st_synchronize() call
void simulate_st_synchronize(float additional_time = 0.0f); void simulate_st_synchronize(float additional_time = 0.0f);

View File

@ -407,7 +407,7 @@ struct PrintStatistics
double total_weight; double total_weight;
double total_wipe_tower_cost; double total_wipe_tower_cost;
double total_wipe_tower_filament; double total_wipe_tower_filament;
std::map<size_t, float> filament_stats; std::map<size_t, double> filament_stats;
// Config with the filled in print statistics. // Config with the filled in print statistics.
DynamicConfig config() const; DynamicConfig config() const;

View File

@ -17,6 +17,7 @@
#include "GLCanvas3D.hpp" #include "GLCanvas3D.hpp"
#include "GLToolbar.hpp" #include "GLToolbar.hpp"
#include "GUI_Preview.hpp" #include "GUI_Preview.hpp"
#include "GUI_ObjectManipulation.hpp"
#include <imgui/imgui_internal.h> #include <imgui/imgui_internal.h>
#include <GL/glew.h> #include <GL/glew.h>
@ -687,13 +688,13 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print&
wxGetApp().plater()->set_bed_shape(bed_shape, texture, model, gcode_result.bed_shape.empty()); wxGetApp().plater()->set_bed_shape(bed_shape, texture, model, gcode_result.bed_shape.empty());
} }
m_time_statistics = gcode_result.time_statistics; m_print_statistics = gcode_result.print_statistics;
if (m_time_estimate_mode != PrintEstimatedTimeStatistics::ETimeMode::Normal) { if (m_time_estimate_mode != PrintEstimatedStatistics::ETimeMode::Normal) {
float time = m_time_statistics.modes[static_cast<size_t>(m_time_estimate_mode)].time; float time = m_print_statistics.modes[static_cast<size_t>(m_time_estimate_mode)].time;
if (time == 0.0f || if (time == 0.0f ||
short_time(get_time_dhms(time)) == short_time(get_time_dhms(m_time_statistics.modes[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Normal)].time))) short_time(get_time_dhms(time)) == short_time(get_time_dhms(m_print_statistics.modes[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Normal)].time)))
m_time_estimate_mode = PrintEstimatedTimeStatistics::ETimeMode::Normal; m_time_estimate_mode = PrintEstimatedStatistics::ETimeMode::Normal;
} }
} }
@ -788,7 +789,7 @@ void GCodeViewer::reset()
m_layers.reset(); m_layers.reset();
m_layers_z_range = { 0, 0 }; m_layers_z_range = { 0, 0 };
m_roles = std::vector<ExtrusionRole>(); m_roles = std::vector<ExtrusionRole>();
m_time_statistics.reset(); m_print_statistics.reset();
#if ENABLE_GCODE_WINDOW #if ENABLE_GCODE_WINDOW
m_sequential_view.gcode_window.reset(); m_sequential_view.gcode_window.reset();
#endif // ENABLE_GCODE_WINDOW #endif // ENABLE_GCODE_WINDOW
@ -4079,7 +4080,7 @@ void GCodeViewer::render_legend() const
Line Line
}; };
const PrintEstimatedTimeStatistics::Mode& time_mode = m_time_statistics.modes[static_cast<size_t>(m_time_estimate_mode)]; const PrintEstimatedStatistics::Mode& time_mode = m_print_statistics.modes[static_cast<size_t>(m_time_estimate_mode)];
#if ENABLE_SCROLLABLE_LEGEND #if ENABLE_SCROLLABLE_LEGEND
bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType || bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType ||
(m_view_type == EViewType::ColorPrint && !time_mode.custom_gcode_times.empty())); (m_view_type == EViewType::ColorPrint && !time_mode.custom_gcode_times.empty()));
@ -4088,12 +4089,15 @@ void GCodeViewer::render_legend() const
const float icon_size = ImGui::GetTextLineHeight(); const float icon_size = ImGui::GetTextLineHeight();
const float percent_bar_size = 2.0f * ImGui::GetTextLineHeight(); const float percent_bar_size = 2.0f * ImGui::GetTextLineHeight();
bool imperial_units = wxGetApp().app_config->get("use_inches") == "1";
#if ENABLE_SCROLLABLE_LEGEND #if ENABLE_SCROLLABLE_LEGEND
auto append_item = [this, icon_size, percent_bar_size, &imgui](EItemType type, const Color& color, const std::string& label, auto append_item = [this, icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label,
#else #else
auto append_item = [this, draw_list, icon_size, percent_bar_size, &imgui](EItemType type, const Color& color, const std::string& label, auto append_item = [this, draw_list, icon_size, percent_bar_size, &imgui, imperial_units](EItemType type, const Color& color, const std::string& label,
#endif // ENABLE_SCROLLABLE_LEGEND #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 },
double used_filament_m = 0.0, double used_filament_g = 0.0,
std::function<void()> callback = nullptr) { std::function<void()> callback = nullptr) {
if (!visible) if (!visible)
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.3333f); ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.3333f);
@ -4173,10 +4177,26 @@ void GCodeViewer::render_legend() const
char buf[64]; char buf[64];
::sprintf(buf, "%.1f%%", 100.0f * percent); ::sprintf(buf, "%.1f%%", 100.0f * percent);
ImGui::TextUnformatted((percent > 0.0f) ? buf : ""); ImGui::TextUnformatted((percent > 0.0f) ? buf : "");
ImGui::SameLine(offsets[2]);
::sprintf(buf, imperial_units ? "%.2f in" : "%.2f m", used_filament_m);
imgui.text(buf);
ImGui::SameLine(offsets[3]);
::sprintf(buf, "%.2f g", used_filament_g);
imgui.text(buf);
} }
} }
else else {
imgui.text(label); imgui.text(label);
if (used_filament_m > 0.0) {
char buf[64];
ImGui::SameLine(offsets[0]);
::sprintf(buf, imperial_units ? "%.2f in" : "%.2f m", used_filament_m);
imgui.text(buf);
ImGui::SameLine(offsets[1]);
::sprintf(buf, "%.2f g", used_filament_g);
imgui.text(buf);
}
}
if (!visible) if (!visible)
ImGui::PopStyleVar(); ImGui::PopStyleVar();
@ -4204,12 +4224,13 @@ void GCodeViewer::render_legend() const
} }
}; };
auto append_headers = [&imgui](const std::array<std::string, 3>& texts, const std::array<float, 2>& offsets) { auto append_headers = [&imgui](const std::array<std::string, 5>& texts, const std::array<float, 4>& offsets) {
imgui.text(texts[0]); size_t i = 0;
ImGui::SameLine(offsets[0]); for (; i < offsets.size(); i++) {
imgui.text(texts[1]); imgui.text(texts[i]);
ImGui::SameLine(offsets[1]); ImGui::SameLine(offsets[i]);
imgui.text(texts[2]); }
imgui.text(texts[i]);
ImGui::Separator(); ImGui::Separator();
}; };
@ -4222,11 +4243,12 @@ void GCodeViewer::render_legend() const
}; };
auto calculate_offsets = [max_width](const std::vector<std::string>& labels, const std::vector<std::string>& times, 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(); 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[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; return ret;
}; };
@ -4282,11 +4304,22 @@ void GCodeViewer::render_legend() const
return (it != time_mode.roles_times.end()) ? std::make_pair(it->second, it->second / time_mode.time) : std::make_pair(0.0f, 0.0f); return (it != time_mode.roles_times.end()) ? std::make_pair(it->second, it->second / time_mode.time) : std::make_pair(0.0f, 0.0f);
}; };
auto used_filament_per_role = [this, imperial_units](ExtrusionRole role) {
auto it = m_print_statistics.used_filaments_per_role.find(role);
if (it == m_print_statistics.used_filaments_per_role.end())
return std::make_pair(0.0, 0.0);
double koef = imperial_units ? 1000.0 / ObjectManipulation::in_to_mm : 1.0;
return std::make_pair(it->second.first * koef, it->second.second);
};
// data used to properly align items in columns when showing time // data used to properly align items in columns when showing time
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> labels;
std::vector<std::string> times; std::vector<std::string> times;
std::vector<float> percents; std::vector<float> percents;
std::vector<double> used_filaments_m;
std::vector<double> used_filaments_g;
float max_percent = 0.0f; float max_percent = 0.0f;
if (m_view_type == EViewType::FeatureType) { if (m_view_type == EViewType::FeatureType) {
@ -4299,10 +4332,73 @@ void GCodeViewer::render_legend() const
times.push_back((time > 0.0f) ? short_time(get_time_dhms(time)) : ""); times.push_back((time > 0.0f) ? short_time(get_time_dhms(time)) : "");
percents.push_back(percent); percents.push_back(percent);
max_percent = std::max(max_percent, percent); max_percent = std::max(max_percent, percent);
auto [used_filament_m, used_filament_g] = used_filament_per_role(role);
used_filaments_m.push_back(used_filament_m);
used_filaments_g.push_back(used_filament_g);
} }
} }
offsets = calculate_offsets(labels, times, { _u8L("Feature type"), _u8L("Time") }, icon_size); std::string longest_percentage_string;
for (double item : percents) {
char buffer[64];
::sprintf(buffer, "%.2f %%", item);
if (::strlen(buffer) > longest_percentage_string.length())
longest_percentage_string = buffer;
}
longest_percentage_string += " ";
if (_u8L("Percentage").length() > longest_percentage_string.length())
longest_percentage_string = _u8L("Percentage");
std::string longest_used_filament_string;
for (double item : used_filaments_m) {
char buffer[64];
::sprintf(buffer, imperial_units ? "%.2f in" : "%.2f m", item);
if (::strlen(buffer) > longest_used_filament_string.length())
longest_used_filament_string = buffer;
}
offsets = calculate_offsets(labels, times, { _u8L("Feature type"), _u8L("Time"), longest_percentage_string, longest_used_filament_string }, icon_size);
}
// get used filament (meters and grams) from used volume in respect to the active extruder
auto get_used_filament_from_volume = [imperial_units](double volume, int extruder_id) {
const std::vector<std::string>& filament_presets = wxGetApp().preset_bundle->filament_presets;
const PresetCollection& filaments = wxGetApp().preset_bundle->filaments;
double koef = imperial_units ? 1.0/ObjectManipulation::in_to_mm : 0.001;
std::pair<double, double> ret = { 0.0, 0.0 };
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 * koef;
double filament_density = filament_preset->config.opt_float("filament_density", 0);
ret.second = volume * filament_density * 0.001;
}
return ret;
};
if (m_view_type == EViewType::Tool) {
// calculate used filaments data
for (size_t extruder_id : m_extruder_ids) {
if (m_print_statistics.volumes_per_extruder.find(extruder_id) == m_print_statistics.volumes_per_extruder.end())
continue;
double volume = m_print_statistics.volumes_per_extruder.at(extruder_id);
auto [used_filament_m, used_filament_g] = get_used_filament_from_volume(volume, extruder_id);
used_filaments_m.push_back(used_filament_m);
used_filaments_g.push_back(used_filament_g);
}
std::string longest_used_filament_string;
for (double item : used_filaments_m) {
char buffer[64];
::sprintf(buffer, imperial_units ? "%.2f in" : "%.2f m", item);
if (::strlen(buffer) > longest_used_filament_string.length())
longest_used_filament_string = buffer;
}
offsets = calculate_offsets(labels, times, { "Extruder NNN", longest_used_filament_string }, icon_size);
} }
// extrusion paths section -> title // extrusion paths section -> title
@ -4310,7 +4406,7 @@ void GCodeViewer::render_legend() const
{ {
case EViewType::FeatureType: case EViewType::FeatureType:
{ {
append_headers({ _u8L("Feature type"), _u8L("Time"), _u8L("Percentage") }, offsets); append_headers({ _u8L("Feature type"), _u8L("Time"), _u8L("Percentage"), _u8L("Used filament") }, offsets);
break; break;
} }
case EViewType::Height: { imgui.title(_u8L("Height (mm)")); break; } case EViewType::Height: { imgui.title(_u8L("Height (mm)")); break; }
@ -4319,7 +4415,11 @@ void GCodeViewer::render_legend() const
case EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; } case EViewType::FanSpeed: { imgui.title(_u8L("Fan Speed (%)")); break; }
case EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; } case EViewType::Temperature: { imgui.title(_u8L("Temperature (°C)")); break; }
case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; } case EViewType::VolumetricRate: { imgui.title(_u8L("Volumetric flow rate (mm³/s)")); break; }
case EViewType::Tool: { imgui.title(_u8L("Tool")); break; } case EViewType::Tool:
{
append_headers({ _u8L("Tool"), _u8L("Used filament") }, offsets);
break;
}
case EViewType::ColorPrint: { imgui.title(_u8L("Color Print")); break; } case EViewType::ColorPrint: { imgui.title(_u8L("Color Print")); break; }
default: { break; } default: { break; }
} }
@ -4335,7 +4435,7 @@ void GCodeViewer::render_legend() const
continue; continue;
const bool visible = is_visible(role); const bool visible = is_visible(role);
append_item(EItemType::Rect, Extrusion_Role_Colors[static_cast<unsigned int>(role)], labels[i], append_item(EItemType::Rect, Extrusion_Role_Colors[static_cast<unsigned int>(role)], labels[i],
visible, times[i], percents[i], max_percent, offsets, [this, role, visible]() { visible, times[i], percents[i], max_percent, offsets, used_filaments_m[i], used_filaments_g[i], [this, role, visible]() {
Extrusions* extrusions = const_cast<Extrusions*>(&m_extrusions); Extrusions* extrusions = const_cast<Extrusions*>(&m_extrusions);
extrusions->role_visibility_flags = visible ? extrusions->role_visibility_flags & ~(1 << role) : extrusions->role_visibility_flags | (1 << role); extrusions->role_visibility_flags = visible ? extrusions->role_visibility_flags & ~(1 << role) : extrusions->role_visibility_flags | (1 << role);
// update buffers' render paths // update buffers' render paths
@ -4357,8 +4457,11 @@ void GCodeViewer::render_legend() const
case EViewType::Tool: case EViewType::Tool:
{ {
// shows only extruders actually used // shows only extruders actually used
for (unsigned char i : m_extruder_ids) { size_t i = 0;
append_item(EItemType::Rect, m_tool_colors[i], _u8L("Extruder") + " " + std::to_string(i + 1)); for (unsigned char extruder_id : m_extruder_ids) {
append_item(EItemType::Rect, m_tool_colors[extruder_id], _u8L("Extruder") + " " + std::to_string(extruder_id + 1),
true, "", 0.0f, 0.0f, offsets, used_filaments_m[i], used_filaments_g[i]);
i++;
} }
break; break;
} }
@ -4458,10 +4561,11 @@ void GCodeViewer::render_legend() const
Color color1; Color color1;
Color color2; Color color2;
Times times; Times times;
std::pair<double, double> used_filament {0.0f, 0.0f};
}; };
using PartialTimes = std::vector<PartialTime>; using PartialTimes = std::vector<PartialTime>;
auto generate_partial_times = [this](const TimesList& times) { auto generate_partial_times = [this, get_used_filament_from_volume](const TimesList& times, const std::vector<double>& used_filaments) {
PartialTimes items; PartialTimes items;
std::vector<CustomGCode::Item> custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes; std::vector<CustomGCode::Item> custom_gcode_per_print_z = wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes;
@ -4471,6 +4575,7 @@ void GCodeViewer::render_legend() const
last_color[i] = m_tool_colors[i]; last_color[i] = m_tool_colors[i];
} }
int last_extruder_id = 1; int last_extruder_id = 1;
int color_change_idx = 0;
for (const auto& time_rec : times) { for (const auto& time_rec : times) {
switch (time_rec.first) switch (time_rec.first)
{ {
@ -4486,14 +4591,14 @@ void GCodeViewer::render_legend() const
case CustomGCode::ColorChange: { 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; }); 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()) { 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_from_volume(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 }); 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_color[it->extruder - 1] = decode_color(it->color);
last_extruder_id = it->extruder; last_extruder_id = it->extruder;
custom_gcode_per_print_z.erase(it); custom_gcode_per_print_z.erase(it);
} }
else 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_from_volume(used_filaments[color_change_idx++], last_extruder_id -1) });
break; break;
} }
@ -4504,7 +4609,7 @@ void GCodeViewer::render_legend() const
return items; 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, 4>& offsets, const Times& times) {
imgui.text(_u8L("Color change")); imgui.text(_u8L("Color change"));
ImGui::SameLine(); ImGui::SameLine();
@ -4523,7 +4628,7 @@ void GCodeViewer::render_legend() const
imgui.text(short_time(get_time_dhms(times.second - times.first))); 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, imperial_units](const Color& color, const std::array<float, 4>& offsets, const Times& times, std::pair<double, double> used_filament) {
imgui.text(_u8L("Print")); imgui.text(_u8L("Print"));
ImGui::SameLine(); ImGui::SameLine();
@ -4539,9 +4644,19 @@ void GCodeViewer::render_legend() const
imgui.text(short_time(get_time_dhms(times.second))); imgui.text(short_time(get_time_dhms(times.second)));
ImGui::SameLine(offsets[1]); ImGui::SameLine(offsets[1]);
imgui.text(short_time(get_time_dhms(times.first))); imgui.text(short_time(get_time_dhms(times.first)));
if (used_filament.first > 0.0f) {
char buffer[64];
ImGui::SameLine(offsets[2]);
::sprintf(buffer, imperial_units ? "%.2f in" : "%.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, m_print_statistics.volumes_per_color_change);
if (!partial_times.empty()) { if (!partial_times.empty()) {
labels.clear(); labels.clear();
times.clear(); times.clear();
@ -4555,10 +4670,22 @@ void GCodeViewer::render_legend() const
} }
times.push_back(short_time(get_time_dhms(item.times.second))); 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);
std::string longest_used_filament_string;
for (const PartialTime& item : partial_times) {
if (item.used_filament.first > 0.0f) {
char buffer[64];
::sprintf(buffer, imperial_units ? "%.2f in" : "%.2f m", item.used_filament.first);
if (::strlen(buffer) > longest_used_filament_string.length())
longest_used_filament_string = buffer;
}
}
offsets = calculate_offsets(labels, times, { _u8L("Event"), _u8L("Remaining time"), _u8L("Duration"), longest_used_filament_string }, 2.0f * icon_size);
ImGui::Spacing(); ImGui::Spacing();
append_headers({ _u8L("Event"), _u8L("Remaining time"), _u8L("Duration") }, offsets); append_headers({ _u8L("Event"), _u8L("Remaining time"), _u8L("Duration"), _u8L("Used filament") }, offsets);
#if ENABLE_SCROLLABLE_LEGEND #if ENABLE_SCROLLABLE_LEGEND
const bool need_scrollable = static_cast<float>(partial_times.size()) * (icon_size + ImGui::GetStyle().ItemSpacing.y) > child_height; const bool need_scrollable = static_cast<float>(partial_times.size()) * (icon_size + ImGui::GetStyle().ItemSpacing.y) > child_height;
if (need_scrollable) if (need_scrollable)
@ -4570,7 +4697,7 @@ void GCodeViewer::render_legend() const
switch (item.type) switch (item.type)
{ {
case PartialTime::EType::Print: { case PartialTime::EType::Print: {
append_print(item.color1, offsets, item.times); append_print(item.color1, offsets, item.times, item.used_filament);
break; break;
} }
case PartialTime::EType::Pause: { case PartialTime::EType::Pause: {
@ -4750,12 +4877,12 @@ void GCodeViewer::render_legend() const
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
switch (m_time_estimate_mode) switch (m_time_estimate_mode)
{ {
case PrintEstimatedTimeStatistics::ETimeMode::Normal: case PrintEstimatedStatistics::ETimeMode::Normal:
{ {
imgui.text(_u8L("Estimated printing time") + " [" + _u8L("Normal mode") + "]:"); imgui.text(_u8L("Estimated printing time") + " [" + _u8L("Normal mode") + "]:");
break; break;
} }
case PrintEstimatedTimeStatistics::ETimeMode::Stealth: case PrintEstimatedStatistics::ETimeMode::Stealth:
{ {
imgui.text(_u8L("Estimated printing time") + " [" + _u8L("Stealth mode") + "]:"); imgui.text(_u8L("Estimated printing time") + " [" + _u8L("Stealth mode") + "]:");
break; break;
@ -4765,18 +4892,18 @@ void GCodeViewer::render_legend() const
ImGui::SameLine(); ImGui::SameLine();
imgui.text(short_time(get_time_dhms(time_mode.time))); imgui.text(short_time(get_time_dhms(time_mode.time)));
auto show_mode_button = [this, &imgui](const wxString& label, PrintEstimatedTimeStatistics::ETimeMode mode) { auto show_mode_button = [this, &imgui](const wxString& label, PrintEstimatedStatistics::ETimeMode mode) {
bool show = false; bool show = false;
for (size_t i = 0; i < m_time_statistics.modes.size(); ++i) { for (size_t i = 0; i < m_print_statistics.modes.size(); ++i) {
if (i != static_cast<size_t>(mode) && if (i != static_cast<size_t>(mode) &&
short_time(get_time_dhms(m_time_statistics.modes[static_cast<size_t>(mode)].time)) != short_time(get_time_dhms(m_time_statistics.modes[i].time))) { short_time(get_time_dhms(m_print_statistics.modes[static_cast<size_t>(mode)].time)) != short_time(get_time_dhms(m_print_statistics.modes[i].time))) {
show = true; show = true;
break; break;
} }
} }
if (show && m_time_statistics.modes[static_cast<size_t>(mode)].roles_times.size() > 0) { if (show && m_print_statistics.modes[static_cast<size_t>(mode)].roles_times.size() > 0) {
if (imgui.button(label)) { if (imgui.button(label)) {
*const_cast<PrintEstimatedTimeStatistics::ETimeMode*>(&m_time_estimate_mode) = mode; *const_cast<PrintEstimatedStatistics::ETimeMode*>(&m_time_estimate_mode) = mode;
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame(); wxGetApp().plater()->get_current_canvas3D()->request_extra_frame();
} }
@ -4784,12 +4911,12 @@ void GCodeViewer::render_legend() const
}; };
switch (m_time_estimate_mode) { switch (m_time_estimate_mode) {
case PrintEstimatedTimeStatistics::ETimeMode::Normal: { case PrintEstimatedStatistics::ETimeMode::Normal: {
show_mode_button(_L("Show stealth mode"), PrintEstimatedTimeStatistics::ETimeMode::Stealth); show_mode_button(_L("Show stealth mode"), PrintEstimatedStatistics::ETimeMode::Stealth);
break; break;
} }
case PrintEstimatedTimeStatistics::ETimeMode::Stealth: { case PrintEstimatedStatistics::ETimeMode::Stealth: {
show_mode_button(_L("Show normal mode"), PrintEstimatedTimeStatistics::ETimeMode::Normal); show_mode_button(_L("Show normal mode"), PrintEstimatedStatistics::ETimeMode::Normal);
break; break;
} }
default : { assert(false); break; } default : { assert(false); break; }

View File

@ -696,8 +696,8 @@ private:
Shells m_shells; Shells m_shells;
EViewType m_view_type{ EViewType::FeatureType }; EViewType m_view_type{ EViewType::FeatureType };
bool m_legend_enabled{ true }; bool m_legend_enabled{ true };
PrintEstimatedTimeStatistics m_time_statistics; PrintEstimatedStatistics m_print_statistics;
PrintEstimatedTimeStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedTimeStatistics::ETimeMode::Normal }; PrintEstimatedStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedStatistics::ETimeMode::Normal };
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
Statistics m_statistics; Statistics m_statistics;
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS

View File

@ -643,7 +643,7 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
if (sla_print_technology) if (sla_print_technology)
m_layers_slider->SetLayersTimes(plater->sla_print().print_statistics().layers_times); m_layers_slider->SetLayersTimes(plater->sla_print().print_statistics().layers_times);
else { else {
auto print_mode_stat = m_gcode_result->time_statistics.modes.front(); auto print_mode_stat = m_gcode_result->print_statistics.modes.front();
m_layers_slider->SetLayersTimes(print_mode_stat.layers_times, print_mode_stat.time); m_layers_slider->SetLayersTimes(print_mode_stat.layers_times, print_mode_stat.time);
} }

View File

@ -1172,10 +1172,10 @@ void Sidebar::update_sliced_info_sizer()
new_label += format_wxstr(":\n - %1%\n - %2%", _L("objects"), _L("wipe tower")); new_label += format_wxstr(":\n - %1%\n - %2%", _L("objects"), _L("wipe tower"));
wxString info_text = is_wipe_tower ? wxString info_text = is_wipe_tower ?
wxString::Format("%.2f \n%.2f \n%.2f", ps.total_used_filament / /*1000*/koef, wxString::Format("%.2f \n%.2f \n%.2f", ps.total_used_filament / koef,
(ps.total_used_filament - ps.total_wipe_tower_filament) / /*1000*/koef, (ps.total_used_filament - ps.total_wipe_tower_filament) / koef,
ps.total_wipe_tower_filament / /*1000*/koef) : ps.total_wipe_tower_filament / koef) :
wxString::Format("%.2f", ps.total_used_filament / /*1000*/koef); wxString::Format("%.2f", ps.total_used_filament / koef);
p->sliced_info->SetTextAndShow(siFilament_m, info_text, new_label); p->sliced_info->SetTextAndShow(siFilament_m, info_text, new_label);
koef = imperial_units ? pow(ObjectManipulation::mm_to_in, 3) : 1.0f; koef = imperial_units ? pow(ObjectManipulation::mm_to_in, 3) : 1.0f;
@ -1203,7 +1203,7 @@ void Sidebar::update_sliced_info_sizer()
filament_weight = ps.total_weight; filament_weight = ps.total_weight;
else { else {
double filament_density = filament_preset->config.opt_float("filament_density", 0); double filament_density = filament_preset->config.opt_float("filament_density", 0);
filament_weight = filament.second * filament_density * 2.4052f * 0.001; // assumes 1.75mm filament diameter; filament_weight = filament.second * filament_density/* *2.4052f*/ * 0.001; // assumes 1.75mm filament diameter;
new_label += "\n - " + format_wxstr(_L("Filament at extruder %1%"), filament.first + 1); new_label += "\n - " + format_wxstr(_L("Filament at extruder %1%"), filament.first + 1);
info_text += wxString::Format("\n%.2f", filament_weight); info_text += wxString::Format("\n%.2f", filament_weight);
@ -1357,7 +1357,8 @@ void Sidebar::update_ui_from_settings()
update_sliced_info_sizer(); update_sliced_info_sizer();
// update Cut gizmo, if it's open // update Cut gizmo, if it's open
p->plater->canvas3D()->update_gizmos_on_off_state(); p->plater->canvas3D()->update_gizmos_on_off_state();
p->plater->canvas3D()->request_extra_frame(); p->plater->set_current_canvas_as_dirty();
p->plater->get_current_canvas3D()->request_extra_frame();
} }
std::vector<PlaterPresetComboBox*>& Sidebar::combos_filament() std::vector<PlaterPresetComboBox*>& Sidebar::combos_filament()

View File

@ -105,7 +105,7 @@ _constant()
SV* filament_stats() SV* filament_stats()
%code%{ %code%{
HV* hv = newHV(); HV* hv = newHV();
for (std::map<size_t,float>::const_iterator it = THIS->print_statistics().filament_stats.begin(); it != THIS->print_statistics().filament_stats.end(); ++it) { for (std::map<size_t,double>::const_iterator it = THIS->print_statistics().filament_stats.begin(); it != THIS->print_statistics().filament_stats.end(); ++it) {
// stringify extruder_id // stringify extruder_id
std::ostringstream ss; std::ostringstream ss;
ss << it->first; ss << it->first;