diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 01740ca7b..4368783a6 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -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(PrintEstimatedTimeStatistics::ETimeMode::Normal)].time); + print_statistics.estimated_normal_print_time = get_time_dhms(result.print_statistics.modes[static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].time) : "N/A"; + get_time_dhms(result.print_statistics.modes[static_cast(PrintEstimatedStatistics::ETimeMode::Stealth)].time) : "N/A"; + } + + static void update_print_estimated_stats(const GCodeProcessor& processor, const std::vector& 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(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(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{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.) { diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 232a51239..917f84f40 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -186,6 +186,72 @@ void GCodeProcessor::TimeMachine::CustomGCodeTime::reset() times = std::vector>(); } +void GCodeProcessor::UsedFilaments::reset() +{ + color_change_cache = 0.0f; + volumes_per_color_change = std::vector(); + + 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 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(); filament_unload_times = std::vector(); - for (size_t i = 0; i < static_cast(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { machines[i].reset(); } - machines[static_cast(PrintEstimatedTimeStatistics::ETimeMode::Normal)].enabled = true; + machines[static_cast(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 #if ENABLE_EXTENDED_M73_LINES - std::array, static_cast(PrintEstimatedTimeStatistics::ETimeMode::Count)> last_exported_main; - for (size_t i = 0; i < static_cast(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + std::array, static_cast(PrintEstimatedStatistics::ETimeMode::Count)> last_exported_main; + for (size_t i = 0; i < static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count)> last_exported_stop; - for (size_t i = 0; i < static_cast(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + std::array(PrintEstimatedStatistics::ETimeMode::Count)> last_exported_stop; + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { last_exported_stop[i] = time_in_minutes(machines[i].time); } #else - std::array, static_cast(PrintEstimatedTimeStatistics::ETimeMode::Count)> last_exported; - for (size_t i = 0; i < static_cast(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + std::array, static_cast(PrintEstimatedStatistics::ETimeMode::Count)> last_exported; + for (size_t i = 0; i < static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { const TimeMachine& machine = machines[i]; - PrintEstimatedTimeStatistics::ETimeMode mode = static_cast(i); - if (mode == PrintEstimatedTimeStatistics::ETimeMode::Normal || machine.enabled) { + PrintEstimatedStatistics::ETimeMode mode = static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { const TimeMachine& machine = machines[i]; if (machine.enabled) { // export pair @@ -789,13 +855,13 @@ GCodeProcessor::GCodeProcessor() { reset(); #if ENABLE_EXTENDED_M73_LINES - m_time_processor.machines[static_cast(PrintEstimatedTimeStatistics::ETimeMode::Normal)].line_m73_main_mask = "M73 P%s R%s\n"; - m_time_processor.machines[static_cast(PrintEstimatedTimeStatistics::ETimeMode::Normal)].line_m73_stop_mask = "M73 C%s\n"; - m_time_processor.machines[static_cast(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].line_m73_main_mask = "M73 Q%s S%s\n"; - m_time_processor.machines[static_cast(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].line_m73_stop_mask = "M73 D%s\n"; + m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_main_mask = "M73 P%s R%s\n"; + m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_stop_mask = "M73 C%s\n"; + m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_main_mask = "M73 Q%s S%s\n"; + m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Stealth)].line_m73_stop_mask = "M73 D%s\n"; #else - m_time_processor.machines[static_cast(PrintEstimatedTimeStatistics::ETimeMode::Normal)].line_m73_mask = "M73 P%s R%s\n"; - m_time_processor.machines[static_cast(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].line_m73_mask = "M73 Q%s S%s\n"; + m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].line_m73_mask = "M73 P%s R%s\n"; + m_time_processor.machines[static_cast(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(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(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(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(config.filament_unload_time.values[i]); } - for (size_t i = 0; i < static_cast(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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("filament_density"); + if (filament_densities != nullptr) { + for (double dens : filament_densities->values) { + m_filament_densities.push_back(static_cast(dens)); + } + } + m_result.extruders_count = config.option("nozzle_diameter")->values.size(); const ConfigOptionPoints* extruder_offset = config.option("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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].enabled = enabled; + m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled = enabled; } void GCodeProcessor::reset() @@ -1096,6 +1174,7 @@ void GCodeProcessor::reset() } m_filament_diameters = std::vector(Min_Extruder_Count, 1.75f); + m_filament_densities = std::vector(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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(mode)].time : 0.0f; + return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? m_time_processor.machines[static_cast(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(mode)].time)) : std::string("N/A"); + return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? short_time(get_time_dhms(m_time_processor.machines[static_cast(mode)].time)) : std::string("N/A"); } -std::vector>> GCodeProcessor::get_custom_gcode_times(PrintEstimatedTimeStatistics::ETimeMode mode, bool include_remaining) const +std::vector>> GCodeProcessor::get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const { std::vector>> ret; - if (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) { + if (mode < PrintEstimatedStatistics::ETimeMode::Count) { const TimeMachine& machine = m_time_processor.machines[static_cast(mode)]; float total_time = 0.0f; for (const auto& [type, time] : machine.gcode_time.times) { @@ -1241,10 +1323,10 @@ std::vector>> GCodeProcesso return ret; } -std::vector> GCodeProcessor::get_moves_time(PrintEstimatedTimeStatistics::ETimeMode mode) const +std::vector> GCodeProcessor::get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const { std::vector> ret; - if (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) { + if (mode < PrintEstimatedStatistics::ETimeMode::Count) { for (size_t i = 0; i < m_time_processor.machines[static_cast(mode)].moves_time.size(); ++i) { float time = m_time_processor.machines[static_cast(mode)].moves_time[i]; if (time > 0.0f) @@ -1254,10 +1336,10 @@ std::vector> GCodeProcessor::get_moves_time(PrintEst return ret; } -std::vector> GCodeProcessor::get_roles_time(PrintEstimatedTimeStatistics::ETimeMode mode) const +std::vector> GCodeProcessor::get_roles_time(PrintEstimatedStatistics::ETimeMode mode) const { std::vector> ret; - if (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) { + if (mode < PrintEstimatedStatistics::ETimeMode::Count) { for (size_t i = 0; i < m_time_processor.machines[static_cast(mode)].roles_time.size(); ++i) { float time = m_time_processor.machines[static_cast(mode)].roles_time[i]; if (time > 0.0f) @@ -1267,9 +1349,9 @@ std::vector> GCodeProcessor::get_roles_time(Prin return ret; } -std::vector GCodeProcessor::get_layers_time(PrintEstimatedTimeStatistics::ETimeMode mode) const +std::vector GCodeProcessor::get_layers_time(PrintEstimatedStatistics::ETimeMode mode) const { - return (mode < PrintEstimatedTimeStatistics::ETimeMode::Count) ? + return (mode < PrintEstimatedStatistics::ETimeMode::Count) ? m_time_processor.machines[static_cast(mode)].layers_time : std::vector(); } @@ -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,7 +1629,8 @@ void GCodeProcessor::process_tags(const std::string_view comment) extruder_id = static_cast(eid); } - m_extruder_colors[extruder_id] = static_cast(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(m_extruder_offsets.size()) + m_cp_color.counter; // color_change position in list of color for preview ++m_cp_color.counter; if (m_cp_color.counter == UCHAR_MAX) m_cp_color.counter = 0; @@ -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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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& blocks = machine.blocks; curr.feedrate = (delta_pos[E] == 0.0f) ? - minimum_travel_feedrate(static_cast(i), m_feedrate) : - minimum_feedrate(static_cast(i), m_feedrate); + minimum_travel_feedrate(static_cast(i), m_feedrate) : + minimum_feedrate(static_cast(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(i), static_cast(a)); + float axis_max_feedrate = get_axis_max_feedrate(static_cast(i), static_cast(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(i)) : + (type == EMoveType::Travel) ? get_travel_acceleration(static_cast(i)) : (is_extrusion_only_move(delta_pos) ? - get_retract_acceleration(static_cast(i)) : - get_acceleration(static_cast(i))); + get_retract_acceleration(static_cast(i)) : + get_acceleration(static_cast(i))); for (unsigned char a = X; a <= E; ++a) { - float axis_max_acceleration = get_axis_max_acceleration(static_cast(i), static_cast(a)); + float axis_max_acceleration = get_axis_max_acceleration(static_cast(i), static_cast(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(i), static_cast(a)); + float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(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(i), static_cast(a)); + float axis_max_jerk = get_axis_max_jerk(static_cast(i), static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { - if (static_cast(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal || + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { + if (static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { - if (static_cast(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal || + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { + if (static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { - if (static_cast(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal || + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { + if (static_cast(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(i), value); - set_travel_acceleration(static_cast(i), value); + set_acceleration(static_cast(i), value); + set_travel_acceleration(static_cast(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(i), value); + set_acceleration(static_cast(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(i), value); + set_travel_acceleration(static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { - if (static_cast(i) == PrintEstimatedTimeStatistics::ETimeMode::Normal || + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { + if (static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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(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(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(mode)); } -float GCodeProcessor::get_acceleration(PrintEstimatedTimeStatistics::ETimeMode mode) const +float GCodeProcessor::get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const { size_t id = static_cast(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(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(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(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Count); ++i) { + for (size_t i = 0; i < static_cast(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(mode)]; + auto update_mode = [this](PrintEstimatedStatistics::ETimeMode mode) { + PrintEstimatedStatistics::Mode& data = m_result.print_statistics.modes[static_cast(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(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].enabled) - update_mode(PrintEstimatedTimeStatistics::ETimeMode::Stealth); + update_mode(PrintEstimatedStatistics::ETimeMode::Normal); + if (m_time_processor.machines[static_cast(PrintEstimatedStatistics::ETimeMode::Stealth)].enabled) + update_mode(PrintEstimatedStatistics::ETimeMode::Stealth); else - m_result.time_statistics.modes[static_cast(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].reset(); + m_result.print_statistics.modes[static_cast(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 */ diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 75ec1546b..8975255ec 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -36,7 +36,7 @@ namespace Slic3r { Count }; - struct PrintEstimatedTimeStatistics + struct PrintEstimatedStatistics { enum class ETimeMode : unsigned char { @@ -62,14 +62,21 @@ namespace Slic3r { } }; + std::vector volumes_per_color_change; + std::map volumes_per_extruder; + std::map> used_filaments_per_role; + std::array(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 filament_load_times; std::vector filament_unload_times; - std::array(PrintEstimatedTimeStatistics::ETimeMode::Count)> machines; + std::array(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 volumes_per_color_change; + + double tool_change_cache; + std::map volumes_per_extruder; + + double role_cache; + // ExtrusionRole : + std::map> 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 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 m_filament_diameters; + std::vector 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(PrintEstimatedTimeStatistics::ETimeMode::Stealth)].enabled; + return m_time_processor.machines[static_cast(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 cancel_callback = nullptr); - float get_time(PrintEstimatedTimeStatistics::ETimeMode mode) const; - std::string get_time_dhm(PrintEstimatedTimeStatistics::ETimeMode mode) const; - std::vector>> 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>> get_custom_gcode_times(PrintEstimatedStatistics::ETimeMode mode, bool include_remaining) const; - std::vector> get_moves_time(PrintEstimatedTimeStatistics::ETimeMode mode) const; - std::vector> get_roles_time(PrintEstimatedTimeStatistics::ETimeMode mode) const; - std::vector get_layers_time(PrintEstimatedTimeStatistics::ETimeMode mode) const; + std::vector> get_moves_time(PrintEstimatedStatistics::ETimeMode mode) const; + std::vector> get_roles_time(PrintEstimatedStatistics::ETimeMode mode) const; + std::vector 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); diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index b4241c91e..3fdc49db8 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -407,7 +407,7 @@ struct PrintStatistics double total_weight; double total_wipe_tower_cost; double total_wipe_tower_filament; - std::map filament_stats; + std::map filament_stats; // Config with the filled in print statistics. DynamicConfig config() const; diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index c7cb3a5d9..233bdf1cd 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -17,6 +17,7 @@ #include "GLCanvas3D.hpp" #include "GLToolbar.hpp" #include "GUI_Preview.hpp" +#include "GUI_ObjectManipulation.hpp" #include #include @@ -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(m_time_estimate_mode)].time; + if (m_time_estimate_mode != PrintEstimatedStatistics::ETimeMode::Normal) { + float time = m_print_statistics.modes[static_cast(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(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(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(); - 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(m_time_estimate_mode)]; + const PrintEstimatedStatistics::Mode& time_mode = m_print_statistics.modes[static_cast(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& offsets = { 0.0f, 0.0f }, + bool visible = true, const std::string& time = "", float percent = 0.0f, float max_percent = 0.0f, const std::array& offsets = { 0.0f, 0.0f, 0.0f, 0.0f }, + double used_filament_m = 0.0, double used_filament_g = 0.0, std::function 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& texts, const std::array& 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& texts, const std::array& 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& labels, const std::vector& times, - const std::array& titles, float extra_size = 0.0f) { + const std::array& titles, float extra_size = 0.0f) { const ImGuiStyle& style = ImGui::GetStyle(); - std::array ret = { 0.0f, 0.0f }; + std::array 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 offsets = { 0.0f, 0.0f }; + std::array offsets = { 0.0f, 0.0f, 0.0f, 0.0f }; std::vector labels; std::vector times; std::vector percents; + std::vector used_filaments_m; + std::vector 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& 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 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(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(&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 used_filament {0.0f, 0.0f}; }; using PartialTimes = std::vector; - auto generate_partial_times = [this](const TimesList& times) { + auto generate_partial_times = [this, get_used_filament_from_volume](const TimesList& times, const std::vector& used_filaments) { PartialTimes items; std::vector 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& offsets, const Times& times) { + auto append_color_change = [&imgui](const Color& color1, const Color& color2, const std::array& 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& offsets, const Times& times) { + auto append_print = [&imgui, imperial_units](const Color& color, const std::array& offsets, const Times& times, std::pair 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(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(mode) && - short_time(get_time_dhms(m_time_statistics.modes[static_cast(mode)].time)) != short_time(get_time_dhms(m_time_statistics.modes[i].time))) { + short_time(get_time_dhms(m_print_statistics.modes[static_cast(mode)].time)) != short_time(get_time_dhms(m_print_statistics.modes[i].time))) { show = true; break; } } - if (show && m_time_statistics.modes[static_cast(mode)].roles_times.size() > 0) { + if (show && m_print_statistics.modes[static_cast(mode)].roles_times.size() > 0) { if (imgui.button(label)) { - *const_cast(&m_time_estimate_mode) = mode; + *const_cast(&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; } diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 2ccda6f5d..112c681d4 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -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 diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index ea289bb14..52223b3d4 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -643,7 +643,7 @@ void Preview::update_layers_slider(const std::vector& 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); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index aebec14ee..13601396f 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -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& Sidebar::combos_filament() diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 44d58266b..8aef9e7a3 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -105,7 +105,7 @@ _constant() SV* filament_stats() %code%{ HV* hv = newHV(); - for (std::map::const_iterator it = THIS->print_statistics().filament_stats.begin(); it != THIS->print_statistics().filament_stats.end(); ++it) { + for (std::map::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;