diff --git a/resources/icons/super_slicer_logo.svg b/resources/icons/super_slicer_logo.svg
new file mode 100644
index 000000000..db75e6d93
--- /dev/null
+++ b/resources/icons/super_slicer_logo.svg
@@ -0,0 +1,68 @@
+
+
diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui
index e6339ff27..f07e756c9 100644
--- a/resources/ui_layout/print.ui
+++ b/resources/ui_layout/print.ui
@@ -59,7 +59,7 @@ group:Advanced
setting:label_width$10:width$3:sidetext_width$2:seam_angle_cost
setting:label_width$10:width$3:sidetext_width$2:seam_travel_cost
end_line
- line:Looping perimeter
+ line:One-loop perimeters
setting:perimeter_loop
setting:perimeter_loop_seam
end_line
diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt
index cbe14bc02..5df62138e 100644
--- a/src/libslic3r/CMakeLists.txt
+++ b/src/libslic3r/CMakeLists.txt
@@ -89,6 +89,8 @@ add_library(libslic3r STATIC
GCode/ThumbnailData.hpp
GCode/CoolingBuffer.cpp
GCode/CoolingBuffer.hpp
+ GCode/FanMover.cpp
+ GCode/FanMover.hpp
GCode/PostProcessor.cpp
GCode/PostProcessor.hpp
# GCode/PressureEqualizer.cpp
diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp
index 0ad7c42ed..e6c496a1a 100644
--- a/src/libslic3r/GCode.cpp
+++ b/src/libslic3r/GCode.cpp
@@ -6,6 +6,7 @@
#include "EdgeGrid.hpp"
#include "Geometry.hpp"
#include "GCode/Analyzer.hpp"
+#include "GCode/FanMover.hpp"
#include "GCode/PrintExtents.hpp"
#include "GCode/WipeTower.hpp"
#include "ShortestPath.hpp"
@@ -1262,6 +1263,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
m_last_mm3_per_mm = 0.0;
m_last_width = 0.0f;
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
+ m_fan_mover.release();
#else
m_last_mm3_per_mm = GCodeAnalyzer::Default_mm3_per_mm;
m_last_width = GCodeAnalyzer::Default_Width;
@@ -1840,12 +1842,12 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
#endif // ENABLE_GCODE_VIEWER
// Append full config.
- _write(file, "\n");
+ _write(file, "\n", true);
{
std::string full_config = "";
append_full_config(print, full_config);
if (!full_config.empty())
- _write(file, full_config);
+ _write(file, full_config, true);
}
print.throw_if_canceled();
}
@@ -3661,28 +3663,30 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
}
-void GCode::_post_process(std::string& what) {
- //TODO reactivate it by a way or another
-#if !ENABLE_GCODE_VIEWER
+void GCode::_post_process(std::string& what, bool flush) {
+
//if enabled, move the fan startup earlier.
if (this->config().fan_speedup_time.value != 0) {
- Slic3r::FanMover fen_post_process(std::abs(this->config().fan_speedup_time.value), this->config().fan_speedup_time.value>0);
- what = fen_post_process.process_gcode(what);
+ if (this->m_fan_mover.get() == nullptr)
+ this->m_fan_mover.reset(new Slic3r::FanMover(
+ std::abs(this->config().fan_speedup_time.value),
+ this->config().fan_speedup_time.value > 0,
+ this->config().use_relative_e_distances.value));
+ what = this->m_fan_mover->process_gcode(what, flush);
}
-#endif // !ENABLE_GCODE_VIEWER
+
}
-void GCode::_write(FILE* file, const char *what)
+void GCode::_write(FILE* file, const char *what, bool flush /*=false*/)
{
if (what != nullptr) {
-#if ENABLE_GCODE_VIEWER
- const char* gcode = what;
-#else
//const char * gcode_pp = _post_process(what).c_str();
std::string str_preproc{ what };
- _post_process(str_preproc);
-
+ _post_process(str_preproc, flush);
+#if ENABLE_GCODE_VIEWER
+ const char* gcode = str_preproc.c_str();
+#else
const std::string str_ana = m_analyzer.process_gcode(str_preproc);
// apply analyzer, if enabled
diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp
index 578c816d3..b990c5e50 100644
--- a/src/libslic3r/GCode.hpp
+++ b/src/libslic3r/GCode.hpp
@@ -12,6 +12,7 @@
#include "PlaceholderParser.hpp"
#include "PrintConfig.hpp"
#include "GCode/CoolingBuffer.hpp"
+#include "GCode/FanMover.hpp"
#include "GCode/SpiralVase.hpp"
#include "GCode/ToolOrdering.hpp"
#include "GCode/WipeTower.hpp"
@@ -464,8 +465,8 @@ private:
#endif // ENABLE_GCODE_VIEWER
// Write a string into a file.
- void _write(FILE* file, const std::string& what) { this->_write(file, what.c_str()); }
- void _write(FILE* file, const char *what);
+ void _write(FILE* file, const std::string& what, bool flush = false) { this->_write(file, what.c_str()); }
+ void _write(FILE* file, const char *what, bool flush = false);
// Write a string into a file.
// Add a newline, if the string does not end with a newline already.
@@ -475,8 +476,9 @@ private:
// Formats and write into a file the given data.
void _write_format(FILE* file, const char* format, ...);
- //some post-processing on the file, before the analyzer
- void _post_process(std::string& what);
+ //some post-processing on the file, with their data class
+ std::unique_ptr m_fan_mover;
+ void _post_process(std::string& what, bool flush = true);
std::string _extrude(const ExtrusionPath &path, const std::string &description, double speed = -1);
std::string _before_extrude(const ExtrusionPath &path, const std::string &description, double speed = -1);
diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp
index faef66485..4afe65389 100644
--- a/src/libslic3r/GCode/CoolingBuffer.cpp
+++ b/src/libslic3r/GCode/CoolingBuffer.cpp
@@ -712,7 +712,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
float slowdown_below_layer_time = float(EXTRUDER_CONFIG(slowdown_below_layer_time));
float fan_below_layer_time = float(EXTRUDER_CONFIG(fan_below_layer_time));
//if (EXTRUDER_CONFIG(cooling)) {
- if (layer_time < slowdown_below_layer_time) {
+ if (layer_time < slowdown_below_layer_time && fan_below_layer_time > 0) {
// Layer time very short. Enable the fan to a full throttle.
fan_speed_new = max_fan_speed;
} else if (layer_time < fan_below_layer_time) {
diff --git a/src/libslic3r/GCode/FanMover.cpp b/src/libslic3r/GCode/FanMover.cpp
new file mode 100644
index 000000000..e34039319
--- /dev/null
+++ b/src/libslic3r/GCode/FanMover.cpp
@@ -0,0 +1,219 @@
+#include "FanMover.hpp"
+
+#include "GCodeReader.hpp"
+
+/*
+#include
+#include
+#include
+
+#include "../libslic3r.h"
+#include "../PrintConfig.hpp"
+#include "../Utils.hpp"
+#include "Print.hpp"
+
+#include
+*/
+
+
+namespace Slic3r {
+
+const std::string& FanMover::process_gcode(const std::string& gcode, bool flush)
+{
+ m_process_output = "";
+
+ m_parser.parse_buffer(gcode,
+ [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) { /*m_process_output += line.raw() + "\n";*/ this->_process_gcode_line(reader, line); });
+
+ if (flush) {
+ while (!buffer.empty()) {
+ m_process_output += buffer.back().raw + "\n";
+ buffer.pop_back();
+ }
+ }
+
+ return m_process_output;
+}
+
+bool is_end_of_word(char c) {
+ return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 0;
+}
+
+float get_axis_value(const std::string& line, char axis)
+{
+ char match[3] = " X";
+ match[1] = axis;
+
+ size_t pos = line.find(match) + 2;
+ size_t end = line.find(' ', pos + 1);
+ // Try to parse the numeric value.
+ const char* c = line.c_str();
+ char* pend = nullptr;
+ double v = strtod(c+ pos, &pend);
+ if (pend != nullptr && is_end_of_word(*pend)) {
+ // The axis value has been parsed correctly.
+ return float(v);
+ }
+ return NAN;
+}
+
+void change_axis_value(std::string& line, char axis, const float new_value, const int decimal_digits)
+{
+
+ std::ostringstream ss;
+ ss << std::fixed << std::setprecision(decimal_digits) << new_value;
+
+ char match[3] = " X";
+ match[1] = axis;
+
+ size_t pos = line.find(match) + 2;
+ size_t end = line.find(' ', pos + 1);
+ line = line.replace(pos, end - pos, ss.str());
+}
+
+void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCodeLine& line)
+{
+ // processes 'normal' gcode lines
+ std::string cmd = line.cmd();
+ double time = 0;
+ float fan_speed = -1;
+ if (cmd.length() > 1) {
+ if (line.has_f())
+ current_speed = line.f() / 60.0f;
+ switch (::toupper(cmd[0])) {
+ case 'G':
+ {
+ if (::atoi(&cmd[1]) == 1 || ::atoi(&cmd[1]) == 0) {
+ double distx = line.dist_X(reader);
+ double disty = line.dist_Y(reader);
+ double distz = line.dist_Z(reader);
+ double dist = distx * distx + disty * disty + distz * distz;
+ if (dist > 0) {
+ dist = std::sqrt(dist);
+ time = dist / current_speed;
+ }
+ }
+ break;
+ }
+ case 'M':
+ {
+ if (::atoi(&cmd[1]) == 106) {
+ if (line.has_value('S', fan_speed) ) {
+ int nb_M106_erased = 0;
+ if (fan_speed > expected_fan_speed) {
+ time = -1; // don't write!
+ buffer.emplace_front(BufferData("; erased: "+line.raw(), 0, -1));
+ //erase M106 in the buffer -> don't slowdown if you are in the process of step-up.
+ auto it = buffer.begin();
+ int i = 0;
+ while (it != buffer.end()) {
+ if (it->raw.compare(0, 4, "M106") == 0 && it->fan_speed < fan_speed) {
+ //found something that is lower than us -> change is speed by ours and delete us
+ it->fan_speed = fan_speed;
+ std::stringstream ss; ss << "S" << (int)fan_speed;
+ it->raw = std::regex_replace(it->raw, regex_fan_speed, ss.str());
+ nb_M106_erased++;
+ } else {
+ ++it;
+ i++;
+ }
+ }
+
+ if (nb_M106_erased == 0) {
+ //try to split the G1/G0 line to increae precision
+ if (!buffer.empty()) {
+ BufferData& backdata = buffer.back();
+ if (buffer_time_size > nb_seconds_delay * 1.1f && backdata.raw.size() > 2
+ && backdata.raw[0] == 'G' && backdata.raw[1] == '1' && backdata.raw[2] == ' ') {
+ float percent = (buffer_time_size - nb_seconds_delay) / backdata.time;
+ std::string before = backdata.raw;
+ std::string& after = backdata.raw;
+ if (backdata.dx != 0) {
+ change_axis_value(before, 'X', backdata.x + backdata.dx * percent, 3);
+ }
+ if (backdata.dy != 0) {
+ change_axis_value(before, 'Y', backdata.y + backdata.dy * percent, 3);
+ }
+ if (backdata.dz != 0) {
+ change_axis_value(before, 'Z', backdata.z + backdata.dz * percent, 3);
+ }
+ if (backdata.de != 0) {
+ if (relative_e) {
+ change_axis_value(before, 'E', backdata.de * percent, 5);
+ change_axis_value(after, 'E', backdata.de * (1 - percent), 5);
+ } else {
+ change_axis_value(before, 'E', backdata.e + backdata.de * percent, 5);
+ change_axis_value(after, 'E', backdata.e + backdata.de * (1 - percent), 5);
+ }
+ }
+ m_process_output += before + "\n";
+ buffer_time_size -= backdata.time * percent;
+ backdata.time -= backdata.time * percent;
+
+ }
+ }
+
+ //print it
+ if (with_D_option) {
+ std::stringstream ss;
+ ss << " D" << (uint32_t)(buffer_time_size * 1000) << "\n";
+ m_process_output += line.raw() + ss.str();
+ } else {
+ m_process_output += line.raw() + "\n";
+ }
+ current_fan_speed = fan_speed;
+ }
+ }
+
+ //update
+ expected_fan_speed = fan_speed;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ if (time >= 0) {
+ buffer.emplace_front(BufferData(line.raw(), time, fan_speed));
+ BufferData& front = buffer.front();
+ if (line.has(Axis::X)) {
+ front.x = reader.x();
+ front.dx = line.dist_X(reader);
+ }
+ if (line.has(Axis::Y)) {
+ front.y = reader.y();
+ front.dy = line.dist_Y(reader);
+ }
+ if (line.has(Axis::Z)) {
+ front.z = reader.z();
+ front.dz = line.dist_Z(reader);
+ }
+ if (line.has(Axis::E)) {
+ front.e = reader.e();
+ if(relative_e)
+ front.de = line.e();
+ else
+ front.de = line.dist_E(reader);
+ }
+ buffer_time_size += time;
+ }
+ // puts the line back into the gcode
+ //if buffer too big, flush it.
+ if (time > 0) {
+ while (buffer_time_size - buffer.back().time > nb_seconds_delay) {
+ BufferData &backdata = buffer.back();
+ if (backdata.fan_speed < 0 || (int)backdata.fan_speed != (int)current_fan_speed) {
+ buffer_time_size -= backdata.time;
+ m_process_output += backdata.raw + "\n";
+ if (backdata.fan_speed >= 0) {
+ current_fan_speed = backdata.fan_speed;
+ }
+ }
+ buffer.pop_back();
+ }
+ }
+}
+
+} // namespace Slic3r
+
diff --git a/src/libslic3r/GCode/FanMover.hpp b/src/libslic3r/GCode/FanMover.hpp
new file mode 100644
index 000000000..3cc43eddb
--- /dev/null
+++ b/src/libslic3r/GCode/FanMover.hpp
@@ -0,0 +1,59 @@
+#ifndef slic3r_GCode_FanMover_hpp_
+#define slic3r_GCode_FanMover_hpp_
+
+
+#include "../libslic3r.h"
+#include "../PrintConfig.hpp"
+#include "../ExtrusionEntity.hpp"
+
+#include "../Point.hpp"
+#include "../GCodeReader.hpp"
+#include
+
+namespace Slic3r {
+
+class BufferData {
+public:
+ std::string raw;
+ float time;
+ float fan_speed;
+ float x = 0, y = 0, z = 0, e = 0;
+ float dx = 0, dy = 0, dz = 0, de = 0;
+ BufferData(std::string line, float time = 0, float fan_speed = 0) : raw(line), time(time), fan_speed(fan_speed) {}
+};
+
+class FanMover
+{
+private:
+ const std::regex regex_fan_speed;
+ const float nb_seconds_delay;
+ const bool with_D_option;
+ const bool relative_e;
+
+ // in unit/second
+ double current_speed = 1000 / 60.0;;
+ float buffer_time_size = 0;
+ GCodeReader m_parser{};
+ int expected_fan_speed = 0;
+ int current_fan_speed = 0;
+
+ // The output of process_layer()
+ std::list buffer;
+ std::string m_process_output;
+
+public:
+ FanMover(const float nb_seconds_delay, const bool with_D_option, const bool relative_e)
+ : regex_fan_speed("S[0-9]+"), nb_seconds_delay(nb_seconds_delay), with_D_option(with_D_option), relative_e(relative_e){}
+
+ // Adds the gcode contained in the given string to the analysis and returns it after removing the workcodes
+ const std::string& process_gcode(const std::string& gcode, bool flush);
+
+private:
+ // Processes the given gcode line
+ void _process_gcode_line(GCodeReader& reader, const GCodeReader::GCodeLine& line);
+};
+
+} // namespace Slic3r
+
+
+#endif /* slic3r_GCode_FanMover_hpp_ */
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index f452303da..00afa88e8 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -2068,7 +2068,7 @@ void PrintConfigDef::init_fff_params()
" It assume infinite acceleration for this time estimation, and only takes into account G1 and G0 moves. Use 0 to deactivate, negative to remove the 'D' option.");
def->sidetext = L("s");
def->mode = comAdvanced;
- def->set_default_value(new ConfigOptionFloat(-1));
+ def->set_default_value(new ConfigOptionFloat(-0.5));
def = this->add("machine_limits_usage", coEnum);
def->label = L("How to apply");
@@ -3877,7 +3877,7 @@ void PrintConfigDef::init_fff_params()
"\nPut 0 to disable.");
def->cli = "z-step=f";
def->sidetext = L("mm");
- def->min = 0.0001;
+ def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0.005));
diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp
index e45b2632f..a26d88bef 100644
--- a/src/slic3r/GUI/Field.cpp
+++ b/src/slic3r/GUI/Field.cpp
@@ -22,7 +22,7 @@
namespace Slic3r { namespace GUI {
-wxString double_to_string(double const value, const int max_precision /*= 4*/)
+wxString double_to_string(double const value, const int max_precision /*= 8*/)
{
// Style_NoTrailingZeroes does not work on OSX. It also does not work correctly with some locales on Windows.
// return wxNumberFormatter::ToString(value, max_precision, wxNumberFormatter::Style_NoTrailingZeroes);
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 3ee431637..10ab7f71c 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -134,7 +134,7 @@ public:
memDC.SelectObject(bitmap);
memDC.SetFont(m_action_font);
- memDC.SetTextForeground(wxColour(237, 107, 33));
+ memDC.SetTextForeground(wxColour(0, 102, 255));
memDC.DrawText(text, int(m_scale * 60), int(m_scale * 275));
memDC.SelectObject(wxNullBitmap);
@@ -186,9 +186,9 @@ public:
BitmapCache bmp_cache;
int logo_size = lround(width * 0.25);
#if ENABLE_GCODE_VIEWER
- wxBitmap logo_bmp = *bmp_cache.load_svg(wxGetApp().is_editor() ? "prusa_slicer_logo" : "add_gcode", logo_size, logo_size);
+ wxBitmap logo_bmp = *bmp_cache.load_svg(wxGetApp().is_editor() ? "super_slicer_logo" : "add_gcode", logo_size, logo_size);
#else
- wxBitmap logo_bmp = *bmp_cache.load_svg("prusa_slicer_logo", logo_size, logo_size);
+ wxBitmap logo_bmp = *bmp_cache.load_svg("super_slicer_logo", logo_size, logo_size);
#endif // ENABLE_GCODE_VIEWER
wxCoord margin = int(m_scale * 20);
@@ -761,7 +761,7 @@ bool GUI_App::on_init_inner()
}
// create splash screen with updated bmp
- scrn = new SplashScreen(bmp.IsOk() ? bmp : create_scaled_bitmap("prusa_slicer_logo", nullptr, 400),
+ scrn = new SplashScreen(bmp.IsOk() ? bmp : create_scaled_bitmap("super_slicer_logo", nullptr, 400),
wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_TIMEOUT, 4000, splashscreen_pos);
wxYield();
scrn->SetText(_L("Loading configuration..."));