diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index ee2689d16..7c9e9899e 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1648,13 +1648,26 @@ sub print_info_box_show { $print_info_sizer->Add($grid_sizer, 0, wxEXPAND); my @info = ( L("Used Filament (m)") - => sprintf("%.2f" , $self->{print}->total_used_filament / 1000), + => $self->{print}->total_wipe_tower_filament > 0 ? + sprintf("%.2f (%.2f %s + %.2f %s)" , $self->{print}->total_used_filament / 1000, + ($self->{print}->total_used_filament - $self->{print}->total_wipe_tower_filament) / 1000, + L("objects"), + $self->{print}->total_wipe_tower_filament / 1000, + L("wipe_tower")) : + sprintf("%.2f" , $self->{print}->total_used_filament / 1000), + L("Used Filament (mm³)") => sprintf("%.2f" , $self->{print}->total_extruded_volume), L("Used Filament (g)"), => sprintf("%.2f" , $self->{print}->total_weight), L("Cost"), - => sprintf("%.2f" , $self->{print}->total_cost), + => $self->{print}->total_wipe_tower_cost > 0 ? + sprintf("%.2f (%.2f %s + %.2f %s)" , $self->{print}->total_cost, + ($self->{print}->total_cost - $self->{print}->total_wipe_tower_cost), + L("objects"), + $self->{print}->total_wipe_tower_cost, + L("wipe_tower")) : + sprintf("%.2f" , $self->{print}->total_cost), L("Estimated printing time (normal mode)") => $self->{print}->estimated_normal_print_time, L("Estimated printing time (silent mode)") diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index b34ba5441..b6d17d56a 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -276,7 +276,6 @@ std::string WipeTowerIntegration::rotate_wipe_tower_moves(const std::string& gco } - std::string WipeTowerIntegration::prime(GCode &gcodegen) { assert(m_layer_idx == 0); @@ -960,17 +959,20 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) // Get filament stats. print.filament_stats.clear(); - print.total_used_filament = 0.; - print.total_extruded_volume = 0.; - print.total_weight = 0.; - print.total_cost = 0.; + print.total_used_filament = 0.; + print.total_extruded_volume = 0.; + print.total_weight = 0.; + print.total_cost = 0.; + print.total_wipe_tower_cost = 0.; + print.total_wipe_tower_filament = 0.; print.estimated_normal_print_time = m_normal_time_estimator.get_time_dhms(); print.estimated_silent_print_time = m_silent_time_estimator_enabled ? m_silent_time_estimator.get_time_dhms() : "N/A"; for (const Extruder &extruder : m_writer.extruders()) { - double used_filament = extruder.used_filament(); - double extruded_volume = extruder.extruded_volume(); + double used_filament = extruder.used_filament() + (has_wipe_tower ? print.m_wipe_tower_used_filament[extruder.id()] : 0.f); + double extruded_volume = extruder.extruded_volume() + (has_wipe_tower ? print.m_wipe_tower_used_filament[extruder.id()] * 2.4052f : 0.f); // assumes 1.75mm filament diameter double filament_weight = extruded_volume * extruder.filament_density() * 0.001; double filament_cost = filament_weight * extruder.filament_cost() * 0.001; + print.filament_stats.insert(std::pair(extruder.id(), (float)used_filament)); _write_format(file, "; filament used = %.1lfmm (%.1lfcm3)\n", used_filament, extruded_volume * 0.001); if (filament_weight > 0.) { @@ -981,8 +983,10 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) _write_format(file, "; filament cost = %.1lf\n", filament_cost); } } - print.total_used_filament = print.total_used_filament + used_filament; - print.total_extruded_volume = print.total_extruded_volume + extruded_volume; + print.total_used_filament += used_filament; + print.total_extruded_volume += extruded_volume; + print.total_wipe_tower_filament += has_wipe_tower ? used_filament - extruder.used_filament() : 0.; + print.total_wipe_tower_cost += has_wipe_tower ? (extruded_volume - extruder.extruded_volume())* extruder.filament_density() * 0.001 * extruder.filament_cost() * 0.001 : 0.; } _write_format(file, "; total filament cost = %.1lf\n", print.total_cost); _write_format(file, "; estimated printing time (normal mode) = %s\n", m_normal_time_estimator.get_time_dhms().c_str()); diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp index 4953c39fe..d319bee01 100644 --- a/xs/src/libslic3r/GCode.hpp +++ b/xs/src/libslic3r/GCode.hpp @@ -98,6 +98,7 @@ public: void next_layer() { ++ m_layer_idx; m_tool_change_idx = 0; } std::string tool_change(GCode &gcodegen, int extruder_id, bool finish_layer); std::string finalize(GCode &gcodegen); + std::vector used_filament_length() const; private: WipeTowerIntegration& operator=(const WipeTowerIntegration&); diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp index 9bf350328..e7cd8ea1a 100644 --- a/xs/src/libslic3r/GCode/WipeTower.hpp +++ b/xs/src/libslic3r/GCode/WipeTower.hpp @@ -155,6 +155,9 @@ public: // the wipe tower has been completely covered by the tool change extrusions, // or the rest of the tower has been filled by a sparse infill with the finish_layer() method. virtual bool layer_finished() const = 0; + + // Returns used filament length per extruder: + virtual std::vector get_used_filament() const = 0; }; }; // namespace Slic3r diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 42c06252b..23a2bef9b 100644 --- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -111,9 +111,10 @@ public: const WipeTower::xy start_pos_rotated() const { return m_start_pos; } const WipeTower::xy pos_rotated() const { return WipeTower::xy(m_current_pos, 0.f, m_y_shift).rotate(m_wipe_tower_width, m_wipe_tower_depth, m_internal_angle); } float elapsed_time() const { return m_elapsed_time; } + float get_and_reset_used_filament_length() { float temp = m_used_filament_length; m_used_filament_length = 0.f; return temp; } // Extrude with an explicitely provided amount of extrusion. - Writer& extrude_explicit(float x, float y, float e, float f = 0.f) + Writer& extrude_explicit(float x, float y, float e, float f = 0.f, bool record_length = false) { if (x == m_current_pos.x && y == m_current_pos.y && e == 0.f && (f == 0.f || f == m_current_feedrate)) // Neither extrusion nor a travel move. @@ -122,6 +123,8 @@ public: float dx = x - m_current_pos.x; float dy = y - m_current_pos.y; double len = sqrt(dx*dx+dy*dy); + if (record_length) + m_used_filament_length += e; // Now do the "internal rotation" with respect to the wipe tower center @@ -162,8 +165,8 @@ public: return *this; } - Writer& extrude_explicit(const WipeTower::xy &dest, float e, float f = 0.f) - { return extrude_explicit(dest.x, dest.y, e, f); } + Writer& extrude_explicit(const WipeTower::xy &dest, float e, float f = 0.f, bool record_length = false) + { return extrude_explicit(dest.x, dest.y, e, f, record_length); } // Travel to a new XY position. f=0 means use the current value. Writer& travel(float x, float y, float f = 0.f) @@ -177,7 +180,7 @@ public: { float dx = x - m_current_pos.x; float dy = y - m_current_pos.y; - return extrude_explicit(x, y, sqrt(dx*dx+dy*dy) * m_extrusion_flow, f); + return extrude_explicit(x, y, sqrt(dx*dx+dy*dy) * m_extrusion_flow, f, true); } Writer& extrude(const WipeTower::xy &dest, const float f = 0.f) @@ -259,8 +262,8 @@ public: // extrude quickly amount e to x2 with feed f. Writer& ram(float x1, float x2, float dy, float e0, float e, float f) { - extrude_explicit(x1, m_current_pos.y + dy, e0, f); - extrude_explicit(x2, m_current_pos.y, e); + extrude_explicit(x1, m_current_pos.y + dy, e0, f, true); + extrude_explicit(x2, m_current_pos.y, e, 0.f, true); return *this; } @@ -404,6 +407,7 @@ private: float m_last_fan_speed = 0.f; int current_temp = -1; const float m_default_analyzer_line_width; + float m_used_filament_length = 0.f; std::string set_format_X(float x) { @@ -537,6 +541,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // so that tool_change() will know to extrude the wipe tower brim: m_print_brim = true; + // Ask our writer about how much material was consumed: + m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); + ToolChangeResult result; result.priming = true; result.print_z = this->m_z_pos; @@ -632,6 +639,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo ";------------------\n" "\n\n"); + // Ask our writer about how much material was consumed: + m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); + ToolChangeResult result; result.priming = false; result.print_z = this->m_z_pos; @@ -683,6 +693,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(bool sideOnly, flo m_print_brim = false; // Mark the brim as extruded + // Ask our writer about how much material was consumed: + m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); + ToolChangeResult result; result.priming = false; result.print_z = this->m_z_pos; @@ -849,6 +862,9 @@ void WipeTowerPrusaMM::toolchange_Change( const unsigned int new_tool, material_type new_material) { + // Ask the writer about how much of the old filament we consumed: + m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); + // Speed override for the material. Go slow for flex and soluble materials. int speed_override; switch (new_material) { @@ -911,7 +927,6 @@ void WipeTowerPrusaMM::toolchange_Wipe( const float& xl = cleaning_box.ld.x; const float& xr = cleaning_box.rd.x; - // Variables x_to_wipe and traversed_x are here to be able to make sure it always wipes at least // the ordered volume, even if it means violating the box. This can later be removed and simply // wipe until the end of the assigned area. @@ -926,7 +941,6 @@ void WipeTowerPrusaMM::toolchange_Wipe( m_left_to_right = !m_left_to_right; } - // now the wiping itself: for (int i = 0; true; ++i) { if (i!=0) { @@ -935,7 +949,7 @@ void WipeTowerPrusaMM::toolchange_Wipe( else if (wipe_speed < 2210.f) wipe_speed = 4200.f; else wipe_speed = std::min(4800.f, wipe_speed + 50.f); } - + float traversed_x = writer.x(); if (m_left_to_right) writer.extrude(xr - (i % 4 == 0 ? 0 : 1.5*m_perimeter_width), writer.y(), wipe_speed * wipe_coeff); @@ -1050,6 +1064,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer() m_depth_traversed = m_wipe_tower_depth-m_perimeter_width; + // Ask our writer about how much material was consumed: + m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); + ToolChangeResult result; result.priming = false; result.print_z = this->m_z_pos; @@ -1167,6 +1184,8 @@ void WipeTowerPrusaMM::generate(std::vector layer_result; for (auto layer : m_plan) @@ -1208,9 +1227,6 @@ void WipeTowerPrusaMM::generate(std::vector> speed) m_filpar[idx].ramming_speed.push_back(speed); + + m_used_filament_length.resize(std::max(m_used_filament_length.size(), idx + 1)); // makes sure that the vector is big enough so we don't have to check later } @@ -172,6 +174,8 @@ public: return ( (m_is_first_layer ? m_wipe_tower_depth - m_perimeter_width : m_layer_info->depth) - WT_EPSILON < m_depth_traversed); } + virtual std::vector get_used_filament() const { return m_used_filament_length; } + private: WipeTowerPrusaMM(); @@ -331,6 +335,9 @@ private: std::vector m_plan; // Stores information about all layers and toolchanges for the future wipe tower (filled by plan_toolchange(...)) std::vector::iterator m_layer_info = m_plan.end(); + // Stores information about used filament length per extruder: + std::vector m_used_filament_length; + // Returns gcode for wipe tower brim // sideOnly -- set to false -- experimental, draw brim on sides of wipe tower diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index bd14837d9..ba8abd040 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1193,6 +1193,8 @@ void Print::_make_wipe_tower() } m_wipe_tower_final_purge = Slic3r::make_unique( wipe_tower.tool_change((unsigned int)-1, false)); + + m_wipe_tower_used_filament = wipe_tower.get_used_filament(); } std::string Print::output_filename() diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index e3430ad0e..537070a34 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -240,7 +240,7 @@ public: // TODO: status_cb std::string estimated_normal_print_time; std::string estimated_silent_print_time; - double total_used_filament, total_extruded_volume, total_cost, total_weight; + double total_used_filament, total_extruded_volume, total_cost, total_weight, total_wipe_tower_cost, total_wipe_tower_filament; std::map filament_stats; PrintState state; @@ -309,6 +309,7 @@ public: std::unique_ptr m_wipe_tower_priming; std::vector> m_wipe_tower_tool_changes; std::unique_ptr m_wipe_tower_final_purge; + std::vector m_wipe_tower_used_filament; std::string output_filename(); std::string output_filepath(const std::string &path); diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 717064916..50f899f2c 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -276,6 +276,26 @@ Print::total_cost(...) THIS->total_cost = (double)SvNV(ST(1)); } RETVAL = THIS->total_cost; + OUTPUT: + RETVAL + +double +Print::total_wipe_tower_cost(...) + CODE: + if (items > 1) { + THIS->total_wipe_tower_cost = (double)SvNV(ST(1)); + } + RETVAL = THIS->total_wipe_tower_cost; + OUTPUT: + RETVAL + +double +Print::total_wipe_tower_filament(...) + CODE: + if (items > 1) { + THIS->total_wipe_tower_filament = (double)SvNV(ST(1)); + } + RETVAL = THIS->total_wipe_tower_filament; OUTPUT: RETVAL %}