Fix of #2825 - Add the length of each filament used
This commit is contained in:
parent
56aa45fa1f
commit
b9910669e8
@ -614,9 +614,44 @@ namespace DoExport {
|
||||
static void update_print_estimated_times_stats(const GCodeProcessor& processor, PrintStatistics& print_statistics)
|
||||
{
|
||||
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() ?
|
||||
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
|
||||
@ -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();
|
||||
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 (result != nullptr) {
|
||||
*result = std::move(m_processor.extract_result());
|
||||
@ -957,7 +993,6 @@ namespace DoExport {
|
||||
dst.first += buf;
|
||||
++ 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_cm3, "%.2lf", extruded_volume * 0.001);
|
||||
if (filament_weight > 0.) {
|
||||
|
@ -186,6 +186,72 @@ void GCodeProcessor::TimeMachine::CustomGCodeTime::reset()
|
||||
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()
|
||||
{
|
||||
enabled = false;
|
||||
@ -348,10 +414,10 @@ void GCodeProcessor::TimeProcessor::reset()
|
||||
machine_limits = MachineEnvelopeConfig();
|
||||
filament_load_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[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
|
||||
@ -416,19 +482,19 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
size_t g1_lines_counter = 0;
|
||||
// keeps track of last exported pair <percent, remaining time>
|
||||
#if ENABLE_EXTENDED_M73_LINES
|
||||
std::array<std::pair<int, int>, static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count)> last_exported_main;
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
|
||||
std::array<std::pair<int, int>, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> last_exported_main;
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
last_exported_main[i] = { 0, time_in_minutes(machines[i].time) };
|
||||
}
|
||||
|
||||
// keeps track of last exported remaining time to next printer stop
|
||||
std::array<int, static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count)> last_exported_stop;
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
|
||||
std::array<int, static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count)> last_exported_stop;
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
last_exported_stop[i] = time_in_minutes(machines[i].time);
|
||||
}
|
||||
#else
|
||||
std::array<std::pair<int, int>, static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count)> last_exported;
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
|
||||
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>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
last_exported[i] = { 0, time_in_minutes(machines[i].time) };
|
||||
}
|
||||
#endif // ENABLE_EXTENDED_M73_LINES
|
||||
@ -451,7 +517,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
line = line.substr(1);
|
||||
if (export_remaining_time_enabled &&
|
||||
(line == reserved_tag(ETags::First_Line_M73_Placeholder) || line == reserved_tag(ETags::Last_Line_M73_Placeholder))) {
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
const TimeMachine& machine = machines[i];
|
||||
if (machine.enabled) {
|
||||
#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 (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];
|
||||
if (machine.enabled) {
|
||||
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) {
|
||||
#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];
|
||||
PrintEstimatedTimeStatistics::ETimeMode mode = static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i);
|
||||
if (mode == PrintEstimatedTimeStatistics::ETimeMode::Normal || machine.enabled) {
|
||||
PrintEstimatedStatistics::ETimeMode mode = static_cast<PrintEstimatedStatistics::ETimeMode>(i);
|
||||
if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
|
||||
char buf[128];
|
||||
sprintf(buf, "; estimated printing time (%s mode) = %s\n",
|
||||
(mode == PrintEstimatedTimeStatistics::ETimeMode::Normal) ? "normal" : "silent",
|
||||
(mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent",
|
||||
get_time_dhms(machine.time).c_str());
|
||||
ret += buf;
|
||||
}
|
||||
@ -545,7 +611,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
|
||||
unsigned int exported_lines_count = 0;
|
||||
#endif // ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
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];
|
||||
if (machine.enabled) {
|
||||
// export pair <percent, remaining time>
|
||||
@ -789,13 +855,13 @@ GCodeProcessor::GCodeProcessor()
|
||||
{
|
||||
reset();
|
||||
#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>(PrintEstimatedTimeStatistics::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>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].line_m73_stop_mask = "M73 D%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>(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_stop_mask = "M73 C%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>(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_stop_mask = "M73 D%s\n";
|
||||
#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>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].line_m73_mask = "M73 Q%s S%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>(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_mask = "M73 Q%s S%s\n";
|
||||
#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_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) {
|
||||
m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config);
|
||||
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]);
|
||||
}
|
||||
|
||||
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);
|
||||
m_time_processor.machines[i].max_acceleration = max_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();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
m_time_processor.machines[i].max_acceleration = max_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)
|
||||
{
|
||||
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()
|
||||
@ -1096,6 +1174,7 @@ void GCodeProcessor::reset()
|
||||
}
|
||||
|
||||
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;
|
||||
#if ENABLE_START_GCODE_VISUALIZATION
|
||||
m_first_layer_height = 0.0f;
|
||||
@ -1109,6 +1188,7 @@ void GCodeProcessor::reset()
|
||||
m_producers_enabled = false;
|
||||
|
||||
m_time_processor.reset();
|
||||
m_used_filaments.reset();
|
||||
|
||||
m_result.reset();
|
||||
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
|
||||
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::CustomGCodeTime& gcode_time = machine.gcode_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 });
|
||||
}
|
||||
|
||||
m_used_filaments.process_caches(this);
|
||||
|
||||
update_estimated_times_stats();
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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;
|
||||
if (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) {
|
||||
if (mode < PrintEstimatedStatistics::ETimeMode::Count) {
|
||||
const TimeMachine& machine = m_time_processor.machines[static_cast<size_t>(mode)];
|
||||
float total_time = 0.0f;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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) {
|
||||
float time = m_time_processor.machines[static_cast<size_t>(mode)].moves_time[i];
|
||||
if (time > 0.0f)
|
||||
@ -1254,10 +1336,10 @@ std::vector<std::pair<EMoveType, float>> GCodeProcessor::get_moves_time(PrintEst
|
||||
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;
|
||||
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) {
|
||||
float time = m_time_processor.machines[static_cast<size_t>(mode)].roles_time[i];
|
||||
if (time > 0.0f)
|
||||
@ -1267,9 +1349,9 @@ std::vector<std::pair<ExtrusionRole, float>> GCodeProcessor::get_roles_time(Prin
|
||||
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 :
|
||||
std::vector<float>();
|
||||
}
|
||||
@ -1461,6 +1543,7 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
// extrusion role tag
|
||||
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()));
|
||||
#if ENABLE_SEAMS_VISUALIZATION
|
||||
if (m_extrusion_role == erExternalPerimeter)
|
||||
@ -1546,6 +1629,7 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
||||
extruder_id = static_cast<unsigned char>(eid);
|
||||
}
|
||||
|
||||
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)
|
||||
@ -1557,6 +1641,7 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
||||
}
|
||||
|
||||
process_custom_gcode_time(CustomGCode::ColorChange);
|
||||
process_filaments(CustomGCode::ColorChange);
|
||||
|
||||
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 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
|
||||
m_mm3_per_mm = area_toolpath_cross_section;
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
@ -2254,7 +2342,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||
assert(distance != 0.0f);
|
||||
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];
|
||||
if (!machine.enabled)
|
||||
continue;
|
||||
@ -2264,8 +2352,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||
std::vector<TimeBlock>& blocks = machine.blocks;
|
||||
|
||||
curr.feedrate = (delta_pos[E] == 0.0f) ?
|
||||
minimum_travel_feedrate(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), m_feedrate) :
|
||||
minimum_feedrate(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), m_feedrate);
|
||||
minimum_travel_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), m_feedrate) :
|
||||
minimum_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), m_feedrate);
|
||||
|
||||
TimeBlock block;
|
||||
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]);
|
||||
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)
|
||||
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
|
||||
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) ?
|
||||
get_retract_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i)) :
|
||||
get_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i)));
|
||||
get_retract_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)) :
|
||||
get_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)));
|
||||
|
||||
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)
|
||||
acceleration = axis_max_acceleration;
|
||||
}
|
||||
@ -2317,7 +2405,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||
curr.safe_feedrate = block.feedrate_profile.cruise;
|
||||
|
||||
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)
|
||||
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
|
||||
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) {
|
||||
v_factor *= axis_max_jerk / jerk;
|
||||
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
|
||||
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) {
|
||||
if (static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal ||
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
if (static_cast<PrintEstimatedStatistics::ETimeMode>(i) == PrintEstimatedStatistics::ETimeMode::Normal ||
|
||||
m_time_processor.machine_envelope_processing_enabled) {
|
||||
if (line.has_x())
|
||||
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
|
||||
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) {
|
||||
if (static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal ||
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
if (static_cast<PrintEstimatedStatistics::ETimeMode>(i) == PrintEstimatedStatistics::ETimeMode::Normal ||
|
||||
m_time_processor.machine_envelope_processing_enabled) {
|
||||
if (line.has_x())
|
||||
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)
|
||||
{
|
||||
float value;
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
|
||||
if (static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal ||
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
if (static_cast<PrintEstimatedStatistics::ETimeMode>(i) == PrintEstimatedStatistics::ETimeMode::Normal ||
|
||||
m_time_processor.machine_envelope_processing_enabled) {
|
||||
if (line.has_value('S', value)) {
|
||||
// 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
|
||||
// (perimeters, first layer etc) when 'Marlin (legacy)' flavor is used.
|
||||
set_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), value);
|
||||
set_travel_acceleration(static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i), value);
|
||||
set_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
|
||||
set_travel_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), value);
|
||||
if (line.has_value('T', value))
|
||||
set_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i, value);
|
||||
}
|
||||
else {
|
||||
// New acceleration format, compatible with the upstream Marlin.
|
||||
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))
|
||||
set_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i, value);
|
||||
if (line.has_value('T', value))
|
||||
// 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)
|
||||
{
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) {
|
||||
if (static_cast<PrintEstimatedTimeStatistics::ETimeMode>(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal ||
|
||||
for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
|
||||
if (static_cast<PrintEstimatedStatistics::ETimeMode>(i) == PrintEstimatedStatistics::ETimeMode::Normal ||
|
||||
m_time_processor.machine_envelope_processing_enabled) {
|
||||
if (line.has_x()) {
|
||||
float max_jerk = line.x();
|
||||
@ -2761,7 +2849,7 @@ void GCodeProcessor::process_M221(const GCodeReader::GCodeLine& line)
|
||||
float value_t;
|
||||
if (line.has_value('S', value_s) && !line.has_value('T', value_t)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -2812,7 +2900,7 @@ void GCodeProcessor::process_M402(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())
|
||||
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.";
|
||||
else {
|
||||
unsigned char old_extruder_id = m_extruder_id;
|
||||
process_filaments(CustomGCode::ToolChange);
|
||||
m_extruder_id = id;
|
||||
m_cp_color.current = m_extruder_colors[id];
|
||||
// Specific to the MK3 MMU2:
|
||||
@ -2920,7 +3009,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
|
||||
#if ENABLE_EXTENDED_M73_LINES
|
||||
// stores stop time placeholders for later use
|
||||
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];
|
||||
if (!machine.enabled)
|
||||
continue;
|
||||
@ -2931,7 +3020,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
|
||||
#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())
|
||||
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)));
|
||||
}
|
||||
|
||||
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())
|
||||
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)));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
@ -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));
|
||||
}
|
||||
|
||||
float GCodeProcessor::get_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const
|
||||
float GCodeProcessor::get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
|
||||
{
|
||||
size_t id = static_cast<size_t>(mode);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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)
|
||||
{
|
||||
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];
|
||||
if (!machine.enabled)
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeProcessor::update_estimated_times_stats()
|
||||
{
|
||||
auto update_mode = [this](PrintEstimatedTimeStatistics::ETimeMode mode) {
|
||||
PrintEstimatedTimeStatistics::Mode& data = m_result.time_statistics.modes[static_cast<size_t>(mode)];
|
||||
auto update_mode = [this](PrintEstimatedStatistics::ETimeMode mode) {
|
||||
PrintEstimatedStatistics::Mode& data = m_result.print_statistics.modes[static_cast<size_t>(mode)];
|
||||
data.time = get_time(mode);
|
||||
data.custom_gcode_times = get_custom_gcode_times(mode, true);
|
||||
data.moves_times = get_moves_time(mode);
|
||||
@ -3073,11 +3171,15 @@ void GCodeProcessor::update_estimated_times_stats()
|
||||
data.layers_times = get_layers_time(mode);
|
||||
};
|
||||
|
||||
update_mode(PrintEstimatedTimeStatistics::ETimeMode::Normal);
|
||||
if (m_time_processor.machines[static_cast<size_t>(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].enabled)
|
||||
update_mode(PrintEstimatedTimeStatistics::ETimeMode::Stealth);
|
||||
update_mode(PrintEstimatedStatistics::ETimeMode::Normal);
|
||||
if (m_time_processor.machines[static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled)
|
||||
update_mode(PrintEstimatedStatistics::ETimeMode::Stealth);
|
||||
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 */
|
||||
|
@ -36,7 +36,7 @@ namespace Slic3r {
|
||||
Count
|
||||
};
|
||||
|
||||
struct PrintEstimatedTimeStatistics
|
||||
struct PrintEstimatedStatistics
|
||||
{
|
||||
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;
|
||||
|
||||
PrintEstimatedTimeStatistics() { reset(); }
|
||||
PrintEstimatedStatistics() { reset(); }
|
||||
|
||||
void reset() {
|
||||
for (auto m : modes) {
|
||||
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.
|
||||
std::vector<float> filament_load_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();
|
||||
|
||||
@ -327,6 +334,30 @@ namespace Slic3r {
|
||||
#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:
|
||||
#if !ENABLE_GCODE_LINES_ID_IN_H_SLIDER
|
||||
struct MoveVertex
|
||||
@ -372,7 +403,7 @@ namespace Slic3r {
|
||||
SettingsIds settings_ids;
|
||||
size_t extruders_count;
|
||||
std::vector<std::string> extruder_colors;
|
||||
PrintEstimatedTimeStatistics time_statistics;
|
||||
PrintEstimatedStatistics print_statistics;
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
int64_t time{ 0 };
|
||||
@ -519,6 +550,7 @@ namespace Slic3r {
|
||||
ExtruderColors m_extruder_colors;
|
||||
ExtruderTemps m_extruder_temps;
|
||||
std::vector<float> m_filament_diameters;
|
||||
std::vector<float> m_filament_densities;
|
||||
float m_extruded_last_z;
|
||||
#if ENABLE_START_GCODE_VISUALIZATION
|
||||
float m_first_layer_height; // mm
|
||||
@ -550,6 +582,7 @@ namespace Slic3r {
|
||||
bool m_producers_enabled;
|
||||
|
||||
TimeProcessor m_time_processor;
|
||||
UsedFilaments m_used_filaments;
|
||||
|
||||
Result m_result;
|
||||
static unsigned int s_result_id;
|
||||
@ -566,7 +599,7 @@ namespace Slic3r {
|
||||
void apply_config(const PrintConfig& config);
|
||||
void enable_stealth_time_estimator(bool enabled);
|
||||
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_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).
|
||||
void process_file(const std::string& filename, bool apply_postprocess, std::function<void()> cancel_callback = nullptr);
|
||||
|
||||
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;
|
||||
float get_time(PrintEstimatedStatistics::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(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) 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;
|
||||
std::vector<float> get_layers_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(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||
std::vector<float> get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||
|
||||
private:
|
||||
void apply_config(const DynamicPrintConfig& config);
|
||||
@ -701,20 +734,21 @@ namespace Slic3r {
|
||||
|
||||
void store_move_vertex(EMoveType type);
|
||||
|
||||
float minimum_feedrate(PrintEstimatedTimeStatistics::ETimeMode mode, float feedrate) const;
|
||||
float minimum_travel_feedrate(PrintEstimatedTimeStatistics::ETimeMode mode, float feedrate) const;
|
||||
float get_axis_max_feedrate(PrintEstimatedTimeStatistics::ETimeMode mode, Axis axis) const;
|
||||
float get_axis_max_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, Axis axis) const;
|
||||
float get_axis_max_jerk(PrintEstimatedTimeStatistics::ETimeMode mode, Axis axis) const;
|
||||
float get_retract_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const;
|
||||
float get_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const;
|
||||
void set_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, float value);
|
||||
float get_travel_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const;
|
||||
void set_travel_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode, float value);
|
||||
float minimum_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const;
|
||||
float minimum_travel_feedrate(PrintEstimatedStatistics::ETimeMode mode, float feedrate) const;
|
||||
float get_axis_max_feedrate(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
|
||||
float get_axis_max_acceleration(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
|
||||
float get_axis_max_jerk(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
|
||||
float get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||
float get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||
void set_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value);
|
||||
float get_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||
void set_travel_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value);
|
||||
float get_filament_load_time(size_t extruder_id);
|
||||
float get_filament_unload_time(size_t extruder_id);
|
||||
|
||||
void process_custom_gcode_time(CustomGCode::Type code);
|
||||
void process_filaments(CustomGCode::Type code);
|
||||
|
||||
// Simulates firmware st_synchronize() call
|
||||
void simulate_st_synchronize(float additional_time = 0.0f);
|
||||
|
@ -407,7 +407,7 @@ struct PrintStatistics
|
||||
double total_weight;
|
||||
double total_wipe_tower_cost;
|
||||
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.
|
||||
DynamicConfig config() const;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "GLCanvas3D.hpp"
|
||||
#include "GLToolbar.hpp"
|
||||
#include "GUI_Preview.hpp"
|
||||
#include "GUI_ObjectManipulation.hpp"
|
||||
#include <imgui/imgui_internal.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());
|
||||
}
|
||||
|
||||
m_time_statistics = gcode_result.time_statistics;
|
||||
m_print_statistics = gcode_result.print_statistics;
|
||||
|
||||
if (m_time_estimate_mode != PrintEstimatedTimeStatistics::ETimeMode::Normal) {
|
||||
float time = m_time_statistics.modes[static_cast<size_t>(m_time_estimate_mode)].time;
|
||||
if (m_time_estimate_mode != PrintEstimatedStatistics::ETimeMode::Normal) {
|
||||
float time = m_print_statistics.modes[static_cast<size_t>(m_time_estimate_mode)].time;
|
||||
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)))
|
||||
m_time_estimate_mode = PrintEstimatedTimeStatistics::ETimeMode::Normal;
|
||||
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 = PrintEstimatedStatistics::ETimeMode::Normal;
|
||||
}
|
||||
}
|
||||
|
||||
@ -788,7 +789,7 @@ void GCodeViewer::reset()
|
||||
m_layers.reset();
|
||||
m_layers_z_range = { 0, 0 };
|
||||
m_roles = std::vector<ExtrusionRole>();
|
||||
m_time_statistics.reset();
|
||||
m_print_statistics.reset();
|
||||
#if ENABLE_GCODE_WINDOW
|
||||
m_sequential_view.gcode_window.reset();
|
||||
#endif // ENABLE_GCODE_WINDOW
|
||||
@ -4079,7 +4080,7 @@ void GCodeViewer::render_legend() const
|
||||
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
|
||||
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()));
|
||||
@ -4088,12 +4089,15 @@ void GCodeViewer::render_legend() const
|
||||
const float icon_size = 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
|
||||
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
|
||||
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
|
||||
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) {
|
||||
if (!visible)
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.3333f);
|
||||
@ -4173,10 +4177,26 @@ void GCodeViewer::render_legend() const
|
||||
char buf[64];
|
||||
::sprintf(buf, "%.1f%%", 100.0f * percent);
|
||||
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);
|
||||
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)
|
||||
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) {
|
||||
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, 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();
|
||||
};
|
||||
|
||||
@ -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,
|
||||
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;
|
||||
};
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
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
|
||||
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;
|
||||
std::vector<double> used_filaments_m;
|
||||
std::vector<double> used_filaments_g;
|
||||
float max_percent = 0.0f;
|
||||
|
||||
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)) : "");
|
||||
percents.push_back(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
|
||||
@ -4310,7 +4406,7 @@ void GCodeViewer::render_legend() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
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::Temperature: { imgui.title(_u8L("Temperature (°C)")); 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; }
|
||||
default: { break; }
|
||||
}
|
||||
@ -4335,7 +4435,7 @@ void GCodeViewer::render_legend() const
|
||||
continue;
|
||||
const bool visible = is_visible(role);
|
||||
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->role_visibility_flags = visible ? extrusions->role_visibility_flags & ~(1 << role) : extrusions->role_visibility_flags | (1 << role);
|
||||
// update buffers' render paths
|
||||
@ -4357,8 +4457,11 @@ void GCodeViewer::render_legend() const
|
||||
case EViewType::Tool:
|
||||
{
|
||||
// shows only extruders actually used
|
||||
for (unsigned char i : m_extruder_ids) {
|
||||
append_item(EItemType::Rect, m_tool_colors[i], _u8L("Extruder") + " " + std::to_string(i + 1));
|
||||
size_t i = 0;
|
||||
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;
|
||||
}
|
||||
@ -4458,10 +4561,11 @@ 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, get_used_filament_from_volume](const TimesList& times, const std::vector<double>& used_filaments) {
|
||||
PartialTimes items;
|
||||
|
||||
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];
|
||||
}
|
||||
int last_extruder_id = 1;
|
||||
int color_change_idx = 0;
|
||||
for (const auto& time_rec : times) {
|
||||
switch (time_rec.first)
|
||||
{
|
||||
@ -4486,14 +4591,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_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 });
|
||||
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_from_volume(used_filaments[color_change_idx++], last_extruder_id -1) });
|
||||
|
||||
break;
|
||||
}
|
||||
@ -4504,7 +4609,7 @@ 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, 4>& offsets, const Times& times) {
|
||||
imgui.text(_u8L("Color change"));
|
||||
ImGui::SameLine();
|
||||
|
||||
@ -4523,7 +4628,7 @@ 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, 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::SameLine();
|
||||
|
||||
@ -4539,9 +4644,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, 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()) {
|
||||
labels.clear();
|
||||
times.clear();
|
||||
@ -4555,10 +4670,22 @@ 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);
|
||||
|
||||
|
||||
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();
|
||||
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
|
||||
const bool need_scrollable = static_cast<float>(partial_times.size()) * (icon_size + ImGui::GetStyle().ItemSpacing.y) > child_height;
|
||||
if (need_scrollable)
|
||||
@ -4570,7 +4697,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: {
|
||||
@ -4750,12 +4877,12 @@ void GCodeViewer::render_legend() const
|
||||
ImGui::AlignTextToFramePadding();
|
||||
switch (m_time_estimate_mode)
|
||||
{
|
||||
case PrintEstimatedTimeStatistics::ETimeMode::Normal:
|
||||
case PrintEstimatedStatistics::ETimeMode::Normal:
|
||||
{
|
||||
imgui.text(_u8L("Estimated printing time") + " [" + _u8L("Normal mode") + "]:");
|
||||
break;
|
||||
}
|
||||
case PrintEstimatedTimeStatistics::ETimeMode::Stealth:
|
||||
case PrintEstimatedStatistics::ETimeMode::Stealth:
|
||||
{
|
||||
imgui.text(_u8L("Estimated printing time") + " [" + _u8L("Stealth mode") + "]:");
|
||||
break;
|
||||
@ -4765,18 +4892,18 @@ void GCodeViewer::render_legend() const
|
||||
ImGui::SameLine();
|
||||
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;
|
||||
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) &&
|
||||
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;
|
||||
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)) {
|
||||
*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()->request_extra_frame();
|
||||
}
|
||||
@ -4784,12 +4911,12 @@ void GCodeViewer::render_legend() const
|
||||
};
|
||||
|
||||
switch (m_time_estimate_mode) {
|
||||
case PrintEstimatedTimeStatistics::ETimeMode::Normal: {
|
||||
show_mode_button(_L("Show stealth mode"), PrintEstimatedTimeStatistics::ETimeMode::Stealth);
|
||||
case PrintEstimatedStatistics::ETimeMode::Normal: {
|
||||
show_mode_button(_L("Show stealth mode"), PrintEstimatedStatistics::ETimeMode::Stealth);
|
||||
break;
|
||||
}
|
||||
case PrintEstimatedTimeStatistics::ETimeMode::Stealth: {
|
||||
show_mode_button(_L("Show normal mode"), PrintEstimatedTimeStatistics::ETimeMode::Normal);
|
||||
case PrintEstimatedStatistics::ETimeMode::Stealth: {
|
||||
show_mode_button(_L("Show normal mode"), PrintEstimatedStatistics::ETimeMode::Normal);
|
||||
break;
|
||||
}
|
||||
default : { assert(false); break; }
|
||||
|
@ -696,8 +696,8 @@ private:
|
||||
Shells m_shells;
|
||||
EViewType m_view_type{ EViewType::FeatureType };
|
||||
bool m_legend_enabled{ true };
|
||||
PrintEstimatedTimeStatistics m_time_statistics;
|
||||
PrintEstimatedTimeStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedTimeStatistics::ETimeMode::Normal };
|
||||
PrintEstimatedStatistics m_print_statistics;
|
||||
PrintEstimatedStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedStatistics::ETimeMode::Normal };
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
Statistics m_statistics;
|
||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
||||
|
@ -643,7 +643,7 @@ void Preview::update_layers_slider(const std::vector<double>& layers_z, bool kee
|
||||
if (sla_print_technology)
|
||||
m_layers_slider->SetLayersTimes(plater->sla_print().print_statistics().layers_times);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1172,10 +1172,10 @@ void Sidebar::update_sliced_info_sizer()
|
||||
new_label += format_wxstr(":\n - %1%\n - %2%", _L("objects"), _L("wipe tower"));
|
||||
|
||||
wxString info_text = is_wipe_tower ?
|
||||
wxString::Format("%.2f \n%.2f \n%.2f", ps.total_used_filament / /*1000*/koef,
|
||||
(ps.total_used_filament - ps.total_wipe_tower_filament) / /*1000*/koef,
|
||||
ps.total_wipe_tower_filament / /*1000*/koef) :
|
||||
wxString::Format("%.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) / koef,
|
||||
ps.total_wipe_tower_filament / koef) :
|
||||
wxString::Format("%.2f", ps.total_used_filament / koef);
|
||||
p->sliced_info->SetTextAndShow(siFilament_m, info_text, new_label);
|
||||
|
||||
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;
|
||||
else {
|
||||
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);
|
||||
info_text += wxString::Format("\n%.2f", filament_weight);
|
||||
@ -1357,7 +1357,8 @@ void Sidebar::update_ui_from_settings()
|
||||
update_sliced_info_sizer();
|
||||
// update Cut gizmo, if it's open
|
||||
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()
|
||||
|
@ -105,7 +105,7 @@ _constant()
|
||||
SV* filament_stats()
|
||||
%code%{
|
||||
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
|
||||
std::ostringstream ss;
|
||||
ss << it->first;
|
||||
|
Loading…
Reference in New Issue
Block a user