Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Slic3r/GUI/Plater.pm12
-rw-r--r--t/perimeters.t8
-rw-r--r--xs/src/libslic3r/GCode.cpp71
-rw-r--r--xs/src/libslic3r/GCode.hpp9
-rw-r--r--xs/src/libslic3r/GCodeTimeEstimator.cpp393
-rw-r--r--xs/src/libslic3r/GCodeTimeEstimator.hpp69
-rw-r--r--xs/src/libslic3r/Print.hpp3
-rw-r--r--xs/src/libslic3r/PrintConfig.cpp101
-rw-r--r--xs/src/libslic3r/PrintConfig.hpp5
-rw-r--r--xs/src/slic3r/GUI/3DScene.cpp2
-rw-r--r--xs/src/slic3r/GUI/Field.cpp52
-rw-r--r--xs/src/slic3r/GUI/Field.hpp29
-rw-r--r--xs/src/slic3r/GUI/GUI.cpp31
-rw-r--r--xs/src/slic3r/GUI/GUI.hpp7
-rw-r--r--xs/src/slic3r/GUI/OptionsGroup.cpp10
-rw-r--r--xs/src/slic3r/GUI/OptionsGroup.hpp12
-rw-r--r--xs/src/slic3r/GUI/Preset.cpp5
-rw-r--r--xs/src/slic3r/GUI/Tab.cpp118
-rw-r--r--xs/src/slic3r/GUI/Tab.hpp4
-rw-r--r--xs/xsp/GUI.xsp3
-rw-r--r--xs/xsp/Print.xsp6
21 files changed, 773 insertions, 177 deletions
diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index aef452f5e..4d421dc4a 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -535,7 +535,11 @@ sub new {
fil_mm3 => L("Used Filament (mm³)"),
fil_g => L("Used Filament (g)"),
cost => L("Cost"),
- time => L("Estimated printing time"),
+#==========================================================================================================================================
+ normal_time => L("Estimated printing time (normal mode)"),
+# default_time => L("Estimated printing time (default mode)"),
+#==========================================================================================================================================
+ silent_time => L("Estimated printing time (silent mode)"),
);
while (my $field = shift @info) {
my $label = shift @info;
@@ -1617,7 +1621,11 @@ sub on_export_completed {
$self->{"print_info_cost"}->SetLabel(sprintf("%.2f" , $self->{print}->total_cost));
$self->{"print_info_fil_g"}->SetLabel(sprintf("%.2f" , $self->{print}->total_weight));
$self->{"print_info_fil_mm3"}->SetLabel(sprintf("%.2f" , $self->{print}->total_extruded_volume));
- $self->{"print_info_time"}->SetLabel($self->{print}->estimated_print_time);
+#==========================================================================================================================================
+ $self->{"print_info_normal_time"}->SetLabel($self->{print}->estimated_normal_print_time);
+# $self->{"print_info_default_time"}->SetLabel($self->{print}->estimated_default_print_time);
+#==========================================================================================================================================
+ $self->{"print_info_silent_time"}->SetLabel($self->{print}->estimated_silent_print_time);
$self->{"print_info_fil_m"}->SetLabel(sprintf("%.2f" , $self->{print}->total_used_filament / 1000));
$self->{"print_info_box_show"}->(1);
diff --git a/t/perimeters.t b/t/perimeters.t
index ee332616d..d0657cb23 100644
--- a/t/perimeters.t
+++ b/t/perimeters.t
@@ -175,7 +175,7 @@ use Slic3r::Test;
if ($info->{extruding} && $info->{dist_XY} > 0) {
$cur_loop ||= [ [$self->X, $self->Y] ];
push @$cur_loop, [ @$info{qw(new_X new_Y)} ];
- } else {
+ } elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
if ($cur_loop) {
$has_cw_loops = 1 if Slic3r::Polygon->new(@$cur_loop)->is_clockwise;
$cur_loop = undef;
@@ -201,7 +201,7 @@ use Slic3r::Test;
if ($info->{extruding} && $info->{dist_XY} > 0) {
$cur_loop ||= [ [$self->X, $self->Y] ];
push @$cur_loop, [ @$info{qw(new_X new_Y)} ];
- } else {
+ } elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
if ($cur_loop) {
$has_cw_loops = 1 if Slic3r::Polygon->new_scale(@$cur_loop)->is_clockwise;
if ($self->F == $config->external_perimeter_speed*60) {
@@ -306,7 +306,7 @@ use Slic3r::Test;
if ($info->{extruding} && $info->{dist_XY} > 0 && ($args->{F} // $self->F) == $config->perimeter_speed*60) {
$perimeters{$self->Z}++ if !$in_loop;
$in_loop = 1;
- } else {
+ } elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
$in_loop = 0;
}
});
@@ -430,7 +430,7 @@ use Slic3r::Test;
push @seam_points, Slic3r::Point->new_scale($self->X, $self->Y);
}
$was_extruding = 1;
- } else {
+ } elsif ($cmd ne 'M73') { # skips remaining time lines (M73)
$was_extruding = 0;
}
});
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index 7ed78c433..e587c8e93 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -374,6 +374,12 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
throw std::runtime_error(std::string("G-code export to ") + path + " failed\nIs the disk full?\n");
}
fclose(file);
+
+ m_normal_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
+
+ if (m_silent_time_estimator_enabled)
+ m_silent_time_estimator.post_process_remaining_times(path_tmp, 60.0f);
+
if (! this->m_placeholder_parser_failed_templates.empty()) {
// G-code export proceeded, but some of the PlaceholderParser substitutions failed.
std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n";
@@ -403,10 +409,48 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
{
PROFILE_FUNC();
- // resets time estimator
- m_time_estimator.reset();
- m_time_estimator.set_dialect(print.config.gcode_flavor);
-
+ // resets time estimators
+ m_normal_time_estimator.reset();
+ m_normal_time_estimator.set_dialect(print.config.gcode_flavor);
+ m_normal_time_estimator.set_acceleration(print.config.machine_max_acceleration_extruding.values[0]);
+ m_normal_time_estimator.set_retract_acceleration(print.config.machine_max_acceleration_retracting.values[0]);
+ m_normal_time_estimator.set_minimum_feedrate(print.config.machine_min_extruding_rate.values[0]);
+ m_normal_time_estimator.set_minimum_travel_feedrate(print.config.machine_min_travel_rate.values[0]);
+ m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, print.config.machine_max_acceleration_x.values[0]);
+ m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, print.config.machine_max_acceleration_y.values[0]);
+ m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, print.config.machine_max_acceleration_z.values[0]);
+ m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, print.config.machine_max_acceleration_e.values[0]);
+ m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, print.config.machine_max_feedrate_x.values[0]);
+ m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, print.config.machine_max_feedrate_y.values[0]);
+ m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, print.config.machine_max_feedrate_z.values[0]);
+ m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, print.config.machine_max_feedrate_e.values[0]);
+ m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, print.config.machine_max_jerk_x.values[0]);
+ m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, print.config.machine_max_jerk_y.values[0]);
+ m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, print.config.machine_max_jerk_z.values[0]);
+ m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, print.config.machine_max_jerk_e.values[0]);
+
+ m_silent_time_estimator_enabled = (print.config.gcode_flavor == gcfMarlin) && print.config.silent_mode && boost::starts_with(print.config.printer_model.value, "MK3");
+ if (m_silent_time_estimator_enabled)
+ {
+ m_silent_time_estimator.reset();
+ m_silent_time_estimator.set_dialect(print.config.gcode_flavor);
+ m_silent_time_estimator.set_acceleration(print.config.machine_max_acceleration_extruding.values[1]);
+ m_silent_time_estimator.set_retract_acceleration(print.config.machine_max_acceleration_retracting.values[1]);
+ m_silent_time_estimator.set_minimum_feedrate(print.config.machine_min_extruding_rate.values[1]);
+ m_silent_time_estimator.set_minimum_travel_feedrate(print.config.machine_min_travel_rate.values[1]);
+ m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, print.config.machine_max_acceleration_x.values[1]);
+ m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, print.config.machine_max_acceleration_y.values[1]);
+ m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, print.config.machine_max_acceleration_z.values[1]);
+ m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, print.config.machine_max_acceleration_e.values[1]);
+ m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, print.config.machine_max_feedrate_x.values[1]);
+ m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, print.config.machine_max_feedrate_y.values[1]);
+ m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, print.config.machine_max_feedrate_z.values[1]);
+ m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, print.config.machine_max_feedrate_e.values[1]);
+ m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, print.config.machine_max_jerk_x.values[1]);
+ m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, print.config.machine_max_jerk_y.values[1]);
+ m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, print.config.machine_max_jerk_z.values[1]);
+ m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, print.config.machine_max_jerk_e.values[1]);
+ }
// resets analyzer
m_analyzer.reset();
m_enable_analyzer = preview_data != nullptr;
@@ -806,7 +850,9 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
_write(file, m_writer.postamble());
// calculates estimated printing time
- m_time_estimator.calculate_time();
+ m_normal_time_estimator.calculate_time();
+ if (m_silent_time_estimator_enabled)
+ m_silent_time_estimator.calculate_time();
// Get filament stats.
print.filament_stats.clear();
@@ -814,13 +860,14 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
print.total_extruded_volume = 0.;
print.total_weight = 0.;
print.total_cost = 0.;
- print.estimated_print_time = m_time_estimator.get_time_hms();
+ 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 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<size_t,float>(extruder.id(), used_filament));
+ print.filament_stats.insert(std::pair<size_t, float>(extruder.id(), (float)used_filament));
_write_format(file, "; filament used = %.1lfmm (%.1lfcm3)\n", used_filament, extruded_volume * 0.001);
if (filament_weight > 0.) {
print.total_weight = print.total_weight + filament_weight;
@@ -834,7 +881,9 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
print.total_extruded_volume = print.total_extruded_volume + extruded_volume;
}
_write_format(file, "; total filament cost = %.1lf\n", print.total_cost);
- _write_format(file, "; estimated printing time = %s\n", m_time_estimator.get_time_hms().c_str());
+ _write_format(file, "; estimated printing time (normal mode) = %s\n", m_normal_time_estimator.get_time_dhms().c_str());
+ if (m_silent_time_estimator_enabled)
+ _write_format(file, "; estimated printing time (silent mode) = %s\n", m_silent_time_estimator.get_time_dhms().c_str());
// Append full config.
_write(file, "\n");
@@ -1406,7 +1455,7 @@ void GCode::process_layer(
if (m_pressure_equalizer)
gcode = m_pressure_equalizer->process(gcode.c_str(), false);
// printf("G-code after filter:\n%s\n", out.c_str());
-
+
_write(file, gcode);
}
@@ -2073,7 +2122,9 @@ void GCode::_write(FILE* file, const char *what)
// writes string to file
fwrite(gcode, 1, ::strlen(gcode), file);
// updates time estimator and gcode lines vector
- m_time_estimator.add_gcode_block(gcode);
+ m_normal_time_estimator.add_gcode_block(gcode);
+ if (m_silent_time_estimator_enabled)
+ m_silent_time_estimator.add_gcode_block(gcode);
}
}
diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp
index a5c63f208..7bc525731 100644
--- a/xs/src/libslic3r/GCode.hpp
+++ b/xs/src/libslic3r/GCode.hpp
@@ -133,6 +133,9 @@ public:
m_last_height(GCodeAnalyzer::Default_Height),
m_brim_done(false),
m_second_layer_things_done(false),
+ m_normal_time_estimator(GCodeTimeEstimator::Normal),
+ m_silent_time_estimator(GCodeTimeEstimator::Silent),
+ m_silent_time_estimator_enabled(false),
m_last_obj_copy(nullptr, Point(std::numeric_limits<coord_t>::max(), std::numeric_limits<coord_t>::max()))
{}
~GCode() {}
@@ -303,8 +306,10 @@ protected:
// Index of a last object copy extruded.
std::pair<const PrintObject*, Point> m_last_obj_copy;
- // Time estimator
- GCodeTimeEstimator m_time_estimator;
+ // Time estimators
+ GCodeTimeEstimator m_normal_time_estimator;
+ GCodeTimeEstimator m_silent_time_estimator;
+ bool m_silent_time_estimator_enabled;
// Analyzer
GCodeAnalyzer m_analyzer;
diff --git a/xs/src/libslic3r/GCodeTimeEstimator.cpp b/xs/src/libslic3r/GCodeTimeEstimator.cpp
index 176159ff5..6e500bd4b 100644
--- a/xs/src/libslic3r/GCodeTimeEstimator.cpp
+++ b/xs/src/libslic3r/GCodeTimeEstimator.cpp
@@ -4,18 +4,33 @@
#include <Shiny/Shiny.h>
+#include <boost/nowide/fstream.hpp>
+#include <boost/nowide/cstdio.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+
static const float MMMIN_TO_MMSEC = 1.0f / 60.0f;
static const float MILLISEC_TO_SEC = 0.001f;
static const float INCHES_TO_MM = 25.4f;
-static const float DEFAULT_FEEDRATE = 1500.0f; // from Prusa Firmware (Marlin_main.cpp)
-static const float DEFAULT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
-static const float DEFAULT_RETRACT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
-static const float DEFAULT_AXIS_MAX_FEEDRATE[] = { 500.0f, 500.0f, 12.0f, 120.0f }; // Prusa Firmware 1_75mm_MK2
-static const float DEFAULT_AXIS_MAX_ACCELERATION[] = { 9000.0f, 9000.0f, 500.0f, 10000.0f }; // Prusa Firmware 1_75mm_MK2
-static const float DEFAULT_AXIS_MAX_JERK[] = { 10.0f, 10.0f, 0.2f, 2.5f }; // from Prusa Firmware (Configuration.h)
-static const float DEFAULT_MINIMUM_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
-static const float DEFAULT_MINIMUM_TRAVEL_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
-static const float DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE = 1.0f; // 100 percent
+
+static const float NORMAL_FEEDRATE = 1500.0f; // from Prusa Firmware (Marlin_main.cpp)
+static const float NORMAL_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
+static const float NORMAL_RETRACT_ACCELERATION = 1500.0f; // Prusa Firmware 1_75mm_MK2
+static const float NORMAL_AXIS_MAX_FEEDRATE[] = { 500.0f, 500.0f, 12.0f, 120.0f }; // Prusa Firmware 1_75mm_MK2
+static const float NORMAL_AXIS_MAX_ACCELERATION[] = { 9000.0f, 9000.0f, 500.0f, 10000.0f }; // Prusa Firmware 1_75mm_MK2
+static const float NORMAL_AXIS_MAX_JERK[] = { 10.0f, 10.0f, 0.4f, 2.5f }; // from Prusa Firmware (Configuration.h)
+static const float NORMAL_MINIMUM_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
+static const float NORMAL_MINIMUM_TRAVEL_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
+static const float NORMAL_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE = 1.0f; // 100 percent
+
+static const float SILENT_FEEDRATE = 1500.0f; // from Prusa Firmware (Marlin_main.cpp)
+static const float SILENT_ACCELERATION = 1250.0f; // Prusa Firmware 1_75mm_MK25-RAMBo13a-E3Dv6full
+static const float SILENT_RETRACT_ACCELERATION = 1250.0f; // Prusa Firmware 1_75mm_MK25-RAMBo13a-E3Dv6full
+static const float SILENT_AXIS_MAX_FEEDRATE[] = { 200.0f, 200.0f, 12.0f, 120.0f }; // Prusa Firmware 1_75mm_MK25-RAMBo13a-E3Dv6full
+static const float SILENT_AXIS_MAX_ACCELERATION[] = { 1000.0f, 1000.0f, 200.0f, 5000.0f }; // Prusa Firmware 1_75mm_MK25-RAMBo13a-E3Dv6full
+static const float SILENT_AXIS_MAX_JERK[] = { 10.0f, 10.0f, 0.4f, 2.5f }; // from Prusa Firmware (Configuration.h)
+static const float SILENT_MINIMUM_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
+static const float SILENT_MINIMUM_TRAVEL_FEEDRATE = 0.0f; // from Prusa Firmware (Configuration_adv.h)
+static const float SILENT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE = 1.0f; // 100 percent
static const float PREVIOUS_FEEDRATE_THRESHOLD = 0.0001f;
@@ -73,6 +88,11 @@ namespace Slic3r {
return ::sqrt(value);
}
+ GCodeTimeEstimator::Block::Block()
+ : st_synchronized(false)
+ {
+ }
+
float GCodeTimeEstimator::Block::move_length() const
{
float length = ::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
@@ -159,12 +179,45 @@ namespace Slic3r {
}
#endif // ENABLE_MOVE_STATS
- GCodeTimeEstimator::GCodeTimeEstimator()
+ GCodeTimeEstimator::GCodeTimeEstimator(EMode mode)
+ : _mode(mode)
{
reset();
set_default();
}
+ void GCodeTimeEstimator::add_gcode_line(const std::string& gcode_line)
+ {
+ PROFILE_FUNC();
+ _parser.parse_line(gcode_line,
+ [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
+ { this->_process_gcode_line(reader, line); });
+ }
+
+ void GCodeTimeEstimator::add_gcode_block(const char *ptr)
+ {
+ PROFILE_FUNC();
+ GCodeReader::GCodeLine gline;
+ auto action = [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
+ { this->_process_gcode_line(reader, line); };
+ for (; *ptr != 0;) {
+ gline.reset();
+ ptr = _parser.parse_line(ptr, gline, action);
+ }
+ }
+
+ void GCodeTimeEstimator::calculate_time()
+ {
+ PROFILE_FUNC();
+ _reset_time();
+ _set_blocks_st_synchronize(false);
+ _calculate_time();
+
+#if ENABLE_MOVE_STATS
+ _log_moves_stats();
+#endif // ENABLE_MOVE_STATS
+ }
+
void GCodeTimeEstimator::calculate_time_from_text(const std::string& gcode)
{
reset();
@@ -178,9 +231,6 @@ namespace Slic3r {
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
-
- _reset_blocks();
- _reset();
}
void GCodeTimeEstimator::calculate_time_from_file(const std::string& file)
@@ -193,9 +243,6 @@ namespace Slic3r {
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
-
- _reset_blocks();
- _reset();
}
void GCodeTimeEstimator::calculate_time_from_lines(const std::vector<std::string>& gcode_lines)
@@ -211,42 +258,118 @@ namespace Slic3r {
#if ENABLE_MOVE_STATS
_log_moves_stats();
#endif // ENABLE_MOVE_STATS
-
- _reset_blocks();
- _reset();
}
- void GCodeTimeEstimator::add_gcode_line(const std::string& gcode_line)
+ bool GCodeTimeEstimator::post_process_remaining_times(const std::string& filename, float interval)
{
- PROFILE_FUNC();
- _parser.parse_line(gcode_line,
- [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
- { this->_process_gcode_line(reader, line); });
- }
+ boost::nowide::ifstream in(filename);
+ if (!in.good())
+ throw std::runtime_error(std::string("Remaining times export failed.\nCannot open file for reading.\n"));
- void GCodeTimeEstimator::add_gcode_block(const char *ptr)
- {
- PROFILE_FUNC();
- GCodeReader::GCodeLine gline;
- auto action = [this](GCodeReader &reader, const GCodeReader::GCodeLine &line)
- { this->_process_gcode_line(reader, line); };
- for (; *ptr != 0;) {
- gline.reset();
- ptr = _parser.parse_line(ptr, gline, action);
+ std::string path_tmp = filename + ".times";
+
+ FILE* out = boost::nowide::fopen(path_tmp.c_str(), "wb");
+ if (out == nullptr)
+ throw std::runtime_error(std::string("Remaining times export failed.\nCannot open file for writing.\n"));
+
+ std::string time_mask;
+ switch (_mode)
+ {
+ default:
+ case Normal:
+ {
+ time_mask = "M73 P%s R%s\n";
+ break;
+ }
+ case Silent:
+ {
+ time_mask = "M73 Q%s S%s\n";
+ break;
+ }
}
- }
- void GCodeTimeEstimator::calculate_time()
- {
- PROFILE_FUNC();
- _calculate_time();
+ unsigned int g1_lines_count = 0;
+ float last_recorded_time = 0.0f;
+ std::string gcode_line;
+ // buffer line to export only when greater than 64K to reduce writing calls
+ std::string export_line;
+ char time_line[64];
+ while (std::getline(in, gcode_line))
+ {
+ if (!in.good())
+ {
+ fclose(out);
+ throw std::runtime_error(std::string("Remaining times export failed.\nError while reading from file.\n"));
+ }
-#if ENABLE_MOVE_STATS
- _log_moves_stats();
-#endif // ENABLE_MOVE_STATS
+ gcode_line += "\n";
- _reset_blocks();
- _reset();
+ // add remaining time lines where needed
+ _parser.parse_line(gcode_line,
+ [this, &g1_lines_count, &last_recorded_time, &time_line, &gcode_line, time_mask, interval](GCodeReader& reader, const GCodeReader::GCodeLine& line)
+ {
+ if (line.cmd_is("G1"))
+ {
+ ++g1_lines_count;
+
+ if (!line.has_e())
+ return;
+
+ G1LineIdToBlockIdMap::const_iterator it = _g1_line_ids.find(g1_lines_count);
+ if ((it != _g1_line_ids.end()) && (it->second < (unsigned int)_blocks.size()))
+ {
+ const Block& block = _blocks[it->second];
+ if (block.elapsed_time != -1.0f)
+ {
+ float block_remaining_time = _time - block.elapsed_time;
+ if (std::abs(last_recorded_time - block_remaining_time) > interval)
+ {
+ sprintf(time_line, time_mask.c_str(), std::to_string((int)(100.0f * block.elapsed_time / _time)).c_str(), _get_time_minutes(block_remaining_time).c_str());
+ gcode_line += time_line;
+
+ last_recorded_time = block_remaining_time;
+ }
+ }
+ }
+ }
+ });
+
+ export_line += gcode_line;
+ if (export_line.length() > 65535)
+ {
+ fwrite((const void*)export_line.c_str(), 1, export_line.length(), out);
+ if (ferror(out))
+ {
+ in.close();
+ fclose(out);
+ boost::nowide::remove(path_tmp.c_str());
+ throw std::runtime_error(std::string("Remaining times export failed.\nIs the disk full?\n"));
+ }
+ export_line.clear();
+ }
+ }
+
+ if (export_line.length() > 0)
+ {
+ fwrite((const void*)export_line.c_str(), 1, export_line.length(), out);
+ if (ferror(out))
+ {
+ in.close();
+ fclose(out);
+ boost::nowide::remove(path_tmp.c_str());
+ throw std::runtime_error(std::string("Remaining times export failed.\nIs the disk full?\n"));
+ }
+ }
+
+ fclose(out);
+ in.close();
+
+ boost::nowide::remove(filename.c_str());
+ if (boost::nowide::rename(path_tmp.c_str(), filename.c_str()) != 0)
+ throw std::runtime_error(std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + filename + '\n' +
+ "Is " + path_tmp + " locked?" + '\n');
+
+ return true;
}
void GCodeTimeEstimator::set_axis_position(EAxis axis, float position)
@@ -266,6 +389,24 @@ namespace Slic3r {
void GCodeTimeEstimator::set_axis_max_jerk(EAxis axis, float jerk)
{
+ if ((axis == X) || (axis == Y))
+ {
+ switch (_mode)
+ {
+ default:
+ case Normal:
+ {
+ jerk = std::min(jerk, NORMAL_AXIS_MAX_JERK[axis]);
+ break;
+ }
+ case Silent:
+ {
+ jerk = std::min(jerk, SILENT_AXIS_MAX_JERK[axis]);
+ break;
+ }
+ }
+ }
+
_state.axis[axis].max_jerk = jerk;
}
@@ -389,6 +530,21 @@ namespace Slic3r {
return _state.e_local_positioning_type;
}
+ int GCodeTimeEstimator::get_g1_line_id() const
+ {
+ return _state.g1_line_id;
+ }
+
+ void GCodeTimeEstimator::increment_g1_line_id()
+ {
+ ++_state.g1_line_id;
+ }
+
+ void GCodeTimeEstimator::reset_g1_line_id()
+ {
+ _state.g1_line_id = 0;
+ }
+
void GCodeTimeEstimator::add_additional_time(float timeSec)
{
_state.additional_time += timeSec;
@@ -411,25 +567,25 @@ namespace Slic3r {
set_global_positioning_type(Absolute);
set_e_local_positioning_type(Absolute);
- set_feedrate(DEFAULT_FEEDRATE);
- set_acceleration(DEFAULT_ACCELERATION);
- set_retract_acceleration(DEFAULT_RETRACT_ACCELERATION);
- set_minimum_feedrate(DEFAULT_MINIMUM_FEEDRATE);
- set_minimum_travel_feedrate(DEFAULT_MINIMUM_TRAVEL_FEEDRATE);
- set_extrude_factor_override_percentage(DEFAULT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE);
-
- for (unsigned char a = X; a < Num_Axis; ++a)
+ switch (_mode)
{
- EAxis axis = (EAxis)a;
- set_axis_max_feedrate(axis, DEFAULT_AXIS_MAX_FEEDRATE[a]);
- set_axis_max_acceleration(axis, DEFAULT_AXIS_MAX_ACCELERATION[a]);
- set_axis_max_jerk(axis, DEFAULT_AXIS_MAX_JERK[a]);
+ default:
+ case Normal:
+ {
+ _set_default_as_normal();
+ break;
+ }
+ case Silent:
+ {
+ _set_default_as_silent();
+ break;
+ }
}
}
void GCodeTimeEstimator::reset()
{
- _time = 0.0f;
+ _reset_time();
#if ENABLE_MOVE_STATS
_moves_stats.clear();
#endif // ENABLE_MOVE_STATS
@@ -442,23 +598,14 @@ namespace Slic3r {
return _time;
}
- std::string GCodeTimeEstimator::get_time_hms() const
+ std::string GCodeTimeEstimator::get_time_dhms() const
{
- float timeinsecs = get_time();
- int hours = (int)(timeinsecs / 3600.0f);
- timeinsecs -= (float)hours * 3600.0f;
- int minutes = (int)(timeinsecs / 60.0f);
- timeinsecs -= (float)minutes * 60.0f;
-
- char buffer[64];
- if (hours > 0)
- ::sprintf(buffer, "%dh %dm %ds", hours, minutes, (int)timeinsecs);
- else if (minutes > 0)
- ::sprintf(buffer, "%dm %ds", minutes, (int)timeinsecs);
- else
- ::sprintf(buffer, "%ds", (int)timeinsecs);
+ return _get_time_dhms(get_time());
+ }
- return buffer;
+ std::string GCodeTimeEstimator::get_time_minutes() const
+ {
+ return _get_time_minutes(get_time());
}
void GCodeTimeEstimator::_reset()
@@ -471,6 +618,14 @@ namespace Slic3r {
set_axis_position(Z, 0.0f);
set_additional_time(0.0f);
+
+ reset_g1_line_id();
+ _g1_line_ids.clear();
+ }
+
+ void GCodeTimeEstimator::_reset_time()
+ {
+ _time = 0.0f;
}
void GCodeTimeEstimator::_reset_blocks()
@@ -478,6 +633,50 @@ namespace Slic3r {
_blocks.clear();
}
+ void GCodeTimeEstimator::_set_default_as_normal()
+ {
+ set_feedrate(NORMAL_FEEDRATE);
+ set_acceleration(NORMAL_ACCELERATION);
+ set_retract_acceleration(NORMAL_RETRACT_ACCELERATION);
+ set_minimum_feedrate(NORMAL_MINIMUM_FEEDRATE);
+ set_minimum_travel_feedrate(NORMAL_MINIMUM_TRAVEL_FEEDRATE);
+ set_extrude_factor_override_percentage(NORMAL_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE);
+
+ for (unsigned char a = X; a < Num_Axis; ++a)
+ {
+ EAxis axis = (EAxis)a;
+ set_axis_max_feedrate(axis, NORMAL_AXIS_MAX_FEEDRATE[a]);
+ set_axis_max_acceleration(axis, NORMAL_AXIS_MAX_ACCELERATION[a]);
+ set_axis_max_jerk(axis, NORMAL_AXIS_MAX_JERK[a]);
+ }
+ }
+
+ void GCodeTimeEstimator::_set_default_as_silent()
+ {
+ set_feedrate(SILENT_FEEDRATE);
+ set_acceleration(SILENT_ACCELERATION);
+ set_retract_acceleration(SILENT_RETRACT_ACCELERATION);
+ set_minimum_feedrate(SILENT_MINIMUM_FEEDRATE);
+ set_minimum_travel_feedrate(SILENT_MINIMUM_TRAVEL_FEEDRATE);
+ set_extrude_factor_override_percentage(SILENT_EXTRUDE_FACTOR_OVERRIDE_PERCENTAGE);
+
+ for (unsigned char a = X; a < Num_Axis; ++a)
+ {
+ EAxis axis = (EAxis)a;
+ set_axis_max_feedrate(axis, SILENT_AXIS_MAX_FEEDRATE[a]);
+ set_axis_max_acceleration(axis, SILENT_AXIS_MAX_ACCELERATION[a]);
+ set_axis_max_jerk(axis, SILENT_AXIS_MAX_JERK[a]);
+ }
+ }
+
+ void GCodeTimeEstimator::_set_blocks_st_synchronize(bool state)
+ {
+ for (Block& block : _blocks)
+ {
+ block.st_synchronized = state;
+ }
+ }
+
void GCodeTimeEstimator::_calculate_time()
{
_forward_pass();
@@ -486,14 +685,18 @@ namespace Slic3r {
_time += get_additional_time();
- for (const Block& block : _blocks)
+ for (Block& block : _blocks)
{
+ if (block.st_synchronized)
+ continue;
+
#if ENABLE_MOVE_STATS
float block_time = 0.0f;
block_time += block.acceleration_time();
block_time += block.cruise_time();
block_time += block.deceleration_time();
_time += block_time;
+ block.elapsed_time = _time;
MovesStatsMap::iterator it = _moves_stats.find(block.move_type);
if (it == _moves_stats.end())
@@ -505,6 +708,7 @@ namespace Slic3r {
_time += block.acceleration_time();
_time += block.cruise_time();
_time += block.deceleration_time();
+ block.elapsed_time = _time;
#endif // ENABLE_MOVE_STATS
}
}
@@ -642,6 +846,8 @@ namespace Slic3r {
void GCodeTimeEstimator::_processG1(const GCodeReader::GCodeLine& line)
{
+ increment_g1_line_id();
+
// updates axes positions from line
EUnits units = get_units();
float new_pos[Num_Axis];
@@ -829,6 +1035,7 @@ namespace Slic3r {
// adds block to blocks list
_blocks.emplace_back(block);
+ _g1_line_ids.insert(G1LineIdToBlockIdMap::value_type(get_g1_line_id(), (unsigned int)_blocks.size() - 1));
}
void GCodeTimeEstimator::_processG4(const GCodeReader::GCodeLine& line)
@@ -1043,7 +1250,7 @@ namespace Slic3r {
void GCodeTimeEstimator::_simulate_st_synchronize()
{
_calculate_time();
- _reset_blocks();
+ _set_blocks_st_synchronize(true);
}
void GCodeTimeEstimator::_forward_pass()
@@ -1051,7 +1258,10 @@ namespace Slic3r {
if (_blocks.size() > 1)
{
for (unsigned int i = 0; i < (unsigned int)_blocks.size() - 1; ++i)
- {
+ {
+ if (_blocks[i].st_synchronized || _blocks[i + 1].st_synchronized)
+ continue;
+
_planner_forward_pass_kernel(_blocks[i], _blocks[i + 1]);
}
}
@@ -1063,6 +1273,9 @@ namespace Slic3r {
{
for (int i = (int)_blocks.size() - 1; i >= 1; --i)
{
+ if (_blocks[i - 1].st_synchronized || _blocks[i].st_synchronized)
+ continue;
+
_planner_reverse_pass_kernel(_blocks[i - 1], _blocks[i]);
}
}
@@ -1115,6 +1328,9 @@ namespace Slic3r {
for (Block& b : _blocks)
{
+ if (b.st_synchronized)
+ continue;
+
curr = next;
next = &b;
@@ -1144,6 +1360,33 @@ namespace Slic3r {
}
}
+ std::string GCodeTimeEstimator::_get_time_dhms(float time_in_secs)
+ {
+ int days = (int)(time_in_secs / 86400.0f);
+ time_in_secs -= (float)days * 86400.0f;
+ int hours = (int)(time_in_secs / 3600.0f);
+ time_in_secs -= (float)hours * 3600.0f;
+ int minutes = (int)(time_in_secs / 60.0f);
+ time_in_secs -= (float)minutes * 60.0f;
+
+ char buffer[64];
+ if (days > 0)
+ ::sprintf(buffer, "%dd %dh %dm %ds", days, hours, minutes, (int)time_in_secs);
+ else if (hours > 0)
+ ::sprintf(buffer, "%dh %dm %ds", hours, minutes, (int)time_in_secs);
+ else if (minutes > 0)
+ ::sprintf(buffer, "%dm %ds", minutes, (int)time_in_secs);
+ else
+ ::sprintf(buffer, "%ds", (int)time_in_secs);
+
+ return buffer;
+ }
+
+ std::string GCodeTimeEstimator::_get_time_minutes(float time_in_secs)
+ {
+ return std::to_string((int)(::roundf(time_in_secs / 60.0f)));
+ }
+
#if ENABLE_MOVE_STATS
void GCodeTimeEstimator::_log_moves_stats() const
{
diff --git a/xs/src/libslic3r/GCodeTimeEstimator.hpp b/xs/src/libslic3r/GCodeTimeEstimator.hpp
index 8f948abd1..0307b658e 100644
--- a/xs/src/libslic3r/GCodeTimeEstimator.hpp
+++ b/xs/src/libslic3r/GCodeTimeEstimator.hpp
@@ -17,6 +17,12 @@ namespace Slic3r {
class GCodeTimeEstimator
{
public:
+ enum EMode : unsigned char
+ {
+ Normal,
+ Silent
+ };
+
enum EUnits : unsigned char
{
Millimeters,
@@ -70,7 +76,8 @@ namespace Slic3r {
float additional_time; // s
float minimum_feedrate; // mm/s
float minimum_travel_feedrate; // mm/s
- float extrude_factor_override_percentage;
+ float extrude_factor_override_percentage;
+ unsigned int g1_line_id;
};
public:
@@ -121,7 +128,6 @@ namespace Slic3r {
bool nominal_length;
};
-
#if ENABLE_MOVE_STATS
EMoveType move_type;
#endif // ENABLE_MOVE_STATS
@@ -134,6 +140,11 @@ namespace Slic3r {
FeedrateProfile feedrate;
Trapezoid trapezoid;
+ float elapsed_time;
+
+ bool st_synchronized;
+
+ Block();
// Returns the length of the move covered by this block, in mm
float move_length() const;
@@ -187,19 +198,34 @@ namespace Slic3r {
typedef std::map<Block::EMoveType, MoveStats> MovesStatsMap;
#endif // ENABLE_MOVE_STATS
+ typedef std::map<unsigned int, unsigned int> G1LineIdToBlockIdMap;
+
private:
+ EMode _mode;
GCodeReader _parser;
State _state;
Feedrates _curr;
Feedrates _prev;
BlocksList _blocks;
+ // Map between g1 line id and blocks id, used to speed up export of remaining times
+ G1LineIdToBlockIdMap _g1_line_ids;
float _time; // s
+
#if ENABLE_MOVE_STATS
MovesStatsMap _moves_stats;
#endif // ENABLE_MOVE_STATS
public:
- GCodeTimeEstimator();
+ explicit GCodeTimeEstimator(EMode mode);
+
+ // Adds the given gcode line
+ void add_gcode_line(const std::string& gcode_line);
+
+ void add_gcode_block(const char *ptr);
+ void add_gcode_block(const std::string &str) { this->add_gcode_block(str.c_str()); }
+
+ // Calculates the time estimate from the gcode lines added using add_gcode_line() or add_gcode_block()
+ void calculate_time();
// Calculates the time estimate from the given gcode in string format
void calculate_time_from_text(const std::string& gcode);
@@ -210,14 +236,12 @@ namespace Slic3r {
// Calculates the time estimate from the gcode contained in given list of gcode lines
void calculate_time_from_lines(const std::vector<std::string>& gcode_lines);
- // Adds the given gcode line
- void add_gcode_line(const std::string& gcode_line);
-
- void add_gcode_block(const char *ptr);
- void add_gcode_block(const std::string &str) { this->add_gcode_block(str.c_str()); }
-
- // Calculates the time estimate from the gcode lines added using add_gcode_line()
- void calculate_time();
+ // Process the gcode contained in the file with the given filename,
+ // placing in it new lines (M73) containing the remaining time, at the given interval in seconds
+ // and saving the result back in the same file
+ // This time estimator should have been already used to calculate the time estimate for the gcode
+ // contained in the given file before to call this method
+ bool post_process_remaining_times(const std::string& filename, float interval_sec);
// Set current position on the given axis with the given value
void set_axis_position(EAxis axis, float position);
@@ -263,6 +287,10 @@ namespace Slic3r {
void set_e_local_positioning_type(EPositioningType type);
EPositioningType get_e_local_positioning_type() const;
+ int get_g1_line_id() const;
+ void increment_g1_line_id();
+ void reset_g1_line_id();
+
void add_additional_time(float timeSec);
void set_additional_time(float timeSec);
float get_additional_time() const;
@@ -275,13 +303,22 @@ namespace Slic3r {
// Returns the estimated time, in seconds
float get_time() const;
- // Returns the estimated time, in format HHh MMm SSs
- std::string get_time_hms() const;
+ // Returns the estimated time, in format DDd HHh MMm SSs
+ std::string get_time_dhms() const;
+
+ // Returns the estimated time, in minutes (integer)
+ std::string get_time_minutes() const;
private:
void _reset();
+ void _reset_time();
void _reset_blocks();
+ void _set_default_as_normal();
+ void _set_default_as_silent();
+
+ void _set_blocks_st_synchronize(bool state);
+
// Calculates the time estimate
void _calculate_time();
@@ -353,6 +390,12 @@ namespace Slic3r {
void _recalculate_trapezoids();
+ // Returns the given time is seconds in format DDd HHh MMm SSs
+ static std::string _get_time_dhms(float time_in_secs);
+
+ // Returns the given, in minutes (integer)
+ static std::string _get_time_minutes(float time_in_secs);
+
#if ENABLE_MOVE_STATS
void _log_moves_stats() const;
#endif // ENABLE_MOVE_STATS
diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp
index 3ea7ffb68..2217547ea 100644
--- a/xs/src/libslic3r/Print.hpp
+++ b/xs/src/libslic3r/Print.hpp
@@ -236,7 +236,8 @@ public:
PrintRegionPtrs regions;
PlaceholderParser placeholder_parser;
// TODO: status_cb
- std::string estimated_print_time;
+ std::string estimated_normal_print_time;
+ std::string estimated_silent_print_time;
double total_used_filament, total_extruded_volume, total_cost, total_weight;
std::map<size_t, float> filament_stats;
PrintState<PrintStep, psCount> state;
diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp
index 6f3cdc04d..f541089a3 100644
--- a/xs/src/libslic3r/PrintConfig.cpp
+++ b/xs/src/libslic3r/PrintConfig.cpp
@@ -291,11 +291,11 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("hilbertcurve");
def->enum_values.push_back("archimedeanchords");
def->enum_values.push_back("octagramspiral");
- def->enum_labels.push_back("Rectilinear");
- def->enum_labels.push_back("Concentric");
- def->enum_labels.push_back("Hilbert Curve");
- def->enum_labels.push_back("Archimedean Chords");
- def->enum_labels.push_back("Octagram Spiral");
+ def->enum_labels.push_back(L("Rectilinear"));
+ def->enum_labels.push_back(L("Concentric"));
+ def->enum_labels.push_back(L("Hilbert Curve"));
+ def->enum_labels.push_back(L("Archimedean Chords"));
+ def->enum_labels.push_back(L("Octagram Spiral"));
// solid_fill_pattern is an obsolete equivalent to external_fill_pattern.
def->aliases.push_back("solid_fill_pattern");
def->default_value = new ConfigOptionEnum<InfillPattern>(ipRectilinear);
@@ -651,19 +651,19 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("hilbertcurve");
def->enum_values.push_back("archimedeanchords");
def->enum_values.push_back("octagramspiral");
- def->enum_labels.push_back("Rectilinear");
- def->enum_labels.push_back("Grid");
- def->enum_labels.push_back("Triangles");
- def->enum_labels.push_back("Stars");
- def->enum_labels.push_back("Cubic");
- def->enum_labels.push_back("Line");
- def->enum_labels.push_back("Concentric");
- def->enum_labels.push_back("Honeycomb");
- def->enum_labels.push_back("3D Honeycomb");
- def->enum_labels.push_back("Gyroid");
- def->enum_labels.push_back("Hilbert Curve");
- def->enum_labels.push_back("Archimedean Chords");
- def->enum_labels.push_back("Octagram Spiral");
+ def->enum_labels.push_back(L("Rectilinear"));
+ def->enum_labels.push_back(L("Grid"));
+ def->enum_labels.push_back(L("Triangles"));
+ def->enum_labels.push_back(L("Stars"));
+ def->enum_labels.push_back(L("Cubic"));
+ def->enum_labels.push_back(L("Line"));
+ def->enum_labels.push_back(L("Concentric"));
+ def->enum_labels.push_back(L("Honeycomb"));
+ def->enum_labels.push_back(L("3D Honeycomb"));
+ def->enum_labels.push_back(L("Gyroid"));
+ def->enum_labels.push_back(L("Hilbert Curve"));
+ def->enum_labels.push_back(L("Archimedean Chords"));
+ def->enum_labels.push_back(L("Octagram Spiral"));
def->default_value = new ConfigOptionEnum<InfillPattern>(ipStars);
def = this->add("first_layer_acceleration", coFloat);
@@ -771,7 +771,7 @@ PrintConfigDef::PrintConfigDef()
def->enum_labels.push_back("Mach3/LinuxCNC");
def->enum_labels.push_back("Machinekit");
def->enum_labels.push_back("Smoothie");
- def->enum_labels.push_back("No extrusion");
+ def->enum_labels.push_back(L("No extrusion"));
def->default_value = new ConfigOptionEnum<GCodeFlavor>(gcfMarlin);
def = this->add("infill_acceleration", coFloat);
@@ -892,6 +892,12 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
def->default_value = new ConfigOptionFloat(0.3);
+ def = this->add("silent_mode", coBool);
+ def->label = L("Support silent mode");
+ def->tooltip = L("Set silent mode for the G-code flavor");
+ def->default_value = new ConfigOptionBool(true);
+
+ const int machine_limits_opt_width = 70;
{
struct AxisDefault {
std::string name;
@@ -901,75 +907,82 @@ PrintConfigDef::PrintConfigDef()
};
std::vector<AxisDefault> axes {
// name, max_feedrate, max_acceleration, max_jerk
- { "x", { 200., 200. }, { 1000., 1000. }, { 10., 10. } },
- { "y", { 200., 200. }, { 1000., 1000. }, { 10., 10. } },
- { "z", { 12., 12. }, { 200., 200. }, { 0.4, 0.4 } },
- { "e", { 120., 120. }, { 5000., 5000. }, { 2.5, 2.5 } }
+ { "x", { 500., 200. }, { 9000., 1000. }, { 10., 10. } },
+ { "y", { 500., 200. }, { 9000., 1000. }, { 10., 10. } },
+ { "z", { 12., 12. }, { 500., 200. }, { 0.2, 0.4 } },
+ { "e", { 120., 120. }, { 10000., 5000. }, { 2.5, 2.5 } }
};
for (const AxisDefault &axis : axes) {
std::string axis_upper = boost::to_upper_copy<std::string>(axis.name);
// Add the machine feedrate limits for XYZE axes. (M203)
def = this->add("machine_max_feedrate_" + axis.name, coFloats);
- def->label = (boost::format(L("Maximum feedrate %1%")) % axis_upper).str();
+ def->full_label = (boost::format(L("Maximum feedrate %1%")) % axis_upper).str();
def->category = L("Machine limits");
def->tooltip = (boost::format(L("Maximum feedrate of the %1% axis")) % axis_upper).str();
def->sidetext = L("mm/s");
def->min = 0;
+ def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats(axis.max_feedrate);
// Add the machine acceleration limits for XYZE axes (M201)
def = this->add("machine_max_acceleration_" + axis.name, coFloats);
- def->label = (boost::format(L("Maximum acceleration %1%")) % axis_upper).str();
+ def->full_label = (boost::format(L("Maximum acceleration %1%")) % axis_upper).str();
def->category = L("Machine limits");
def->tooltip = (boost::format(L("Maximum acceleration of the %1% axis")) % axis_upper).str();
def->sidetext = L("mm/s²");
def->min = 0;
+ def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats(axis.max_acceleration);
// Add the machine jerk limits for XYZE axes (M205)
def = this->add("machine_max_jerk_" + axis.name, coFloats);
- def->label = (boost::format(L("Maximum jerk %1%")) % axis_upper).str();
+ def->full_label = (boost::format(L("Maximum jerk %1%")) % axis_upper).str();
def->category = L("Machine limits");
def->tooltip = (boost::format(L("Maximum jerk of the %1% axis")) % axis_upper).str();
def->sidetext = L("mm/s");
def->min = 0;
+ def->width = machine_limits_opt_width;
def->default_value = new ConfigOptionFloats(axis.max_jerk);
}
}
// M205 S... [mm/sec]
def = this->add("machine_min_extruding_rate", coFloats);
- def->label = L("Minimum feedrate when extruding");
+ def->full_label = L("Minimum feedrate when extruding");
def->category = L("Machine limits");
def->tooltip = L("Minimum feedrate when extruding") + " (M205 S)";
def->sidetext = L("mm/s");
def->min = 0;
- def->default_value = new ConfigOptionFloats(0., 0.);
+ def->width = machine_limits_opt_width;
+ def->default_value = new ConfigOptionFloats{ 0., 0. };
// M205 T... [mm/sec]
def = this->add("machine_min_travel_rate", coFloats);
- def->label = L("Minimum travel feedrate");
+ def->full_label = L("Minimum travel feedrate");
def->category = L("Machine limits");
def->tooltip = L("Minimum travel feedrate") + " (M205 T)";
def->sidetext = L("mm/s");
def->min = 0;
- def->default_value = new ConfigOptionFloats(0., 0.);
+ def->width = machine_limits_opt_width;
+ def->default_value = new ConfigOptionFloats{ 0., 0. };
// M204 S... [mm/sec^2]
def = this->add("machine_max_acceleration_extruding", coFloats);
- def->label = L("Maximum acceleration when extruding");
+ def->full_label = L("Maximum acceleration when extruding");
def->category = L("Machine limits");
def->tooltip = L("Maximum acceleration when extruding") + " (M204 S)";
def->sidetext = L("mm/s²");
def->min = 0;
- def->default_value = new ConfigOptionFloats(1250., 1250.);
+ def->width = machine_limits_opt_width;
+ def->default_value = new ConfigOptionFloats{ 1500., 1250. };
// M204 T... [mm/sec^2]
def = this->add("machine_max_acceleration_retracting", coFloats);
- def->label = L("Maximum acceleration when retracting");
+ def->full_label = L("Maximum acceleration when retracting");
def->category = L("Machine limits");
def->tooltip = L("Maximum acceleration when retracting") + " (M204 T)";
def->sidetext = L("mm/s²");
def->min = 0;
- def->default_value = new ConfigOptionFloats(1250., 1250.);
+ def->width = machine_limits_opt_width;
+ def->default_value = new ConfigOptionFloats{ 1500., 1250. };
def = this->add("max_fan_speed", coInts);
def->label = L("Max");
@@ -1392,10 +1405,10 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("nearest");
def->enum_values.push_back("aligned");
def->enum_values.push_back("rear");
- def->enum_labels.push_back("Random");
- def->enum_labels.push_back("Nearest");
- def->enum_labels.push_back("Aligned");
- def->enum_labels.push_back("Rear");
+ def->enum_labels.push_back(L("Random"));
+ def->enum_labels.push_back(L("Nearest"));
+ def->enum_labels.push_back(L("Aligned"));
+ def->enum_labels.push_back(L("Rear"));
def->default_value = new ConfigOptionEnum<SeamPosition>(spAligned);
#if 0
@@ -1608,7 +1621,7 @@ PrintConfigDef::PrintConfigDef()
def->label = L("Single Extruder Multi Material");
def->tooltip = L("The printer multiplexes filaments into a single hot end.");
def->cli = "single-extruder-multi-material!";
- def->default_value = new ConfigOptionBool(false);
+ def->default_value = new ConfigOptionBool(false);
def = this->add("support_material", coBool);
def->label = L("Generate support material");
@@ -1658,8 +1671,8 @@ PrintConfigDef::PrintConfigDef()
def->min = 0;
def->enum_values.push_back("0");
def->enum_values.push_back("0.2");
- def->enum_labels.push_back("0 (soluble)");
- def->enum_labels.push_back("0.2 (detachable)");
+ def->enum_labels.push_back((boost::format("0 (%1%)") % L("soluble")).str());
+ def->enum_labels.push_back((boost::format("0.2 (%1%)") % L("detachable")).str());
def->default_value = new ConfigOptionFloat(0.2);
def = this->add("support_material_enforce_layers", coInt);
@@ -1748,9 +1761,9 @@ PrintConfigDef::PrintConfigDef()
def->enum_values.push_back("rectilinear");
def->enum_values.push_back("rectilinear-grid");
def->enum_values.push_back("honeycomb");
- def->enum_labels.push_back("rectilinear");
- def->enum_labels.push_back("rectilinear grid");
- def->enum_labels.push_back("honeycomb");
+ def->enum_labels.push_back(L("Rectilinear"));
+ def->enum_labels.push_back(L("Rectilinear grid"));
+ def->enum_labels.push_back(L("Honeycomb"));
def->default_value = new ConfigOptionEnum<SupportMaterialPattern>(smpRectilinear);
def = this->add("support_material_spacing", coFloat);
diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp
index 6a03c3a04..c530868a1 100644
--- a/xs/src/libslic3r/PrintConfig.hpp
+++ b/xs/src/libslic3r/PrintConfig.hpp
@@ -562,9 +562,9 @@ public:
ConfigOptionFloat cooling_tube_retraction;
ConfigOptionFloat cooling_tube_length;
ConfigOptionFloat parking_pos_retraction;
+ ConfigOptionBool silent_mode;
ConfigOptionFloat extra_loading_move;
-
std::string get_extrusion_axis() const
{
return
@@ -623,6 +623,7 @@ protected:
OPT_PTR(cooling_tube_retraction);
OPT_PTR(cooling_tube_length);
OPT_PTR(parking_pos_retraction);
+ OPT_PTR(silent_mode);
OPT_PTR(extra_loading_move);
}
};
@@ -676,6 +677,7 @@ public:
ConfigOptionString output_filename_format;
ConfigOptionFloat perimeter_acceleration;
ConfigOptionStrings post_process;
+ ConfigOptionString printer_model;
ConfigOptionString printer_notes;
ConfigOptionFloat resolution;
ConfigOptionFloats retract_before_travel;
@@ -746,6 +748,7 @@ protected:
OPT_PTR(output_filename_format);
OPT_PTR(perimeter_acceleration);
OPT_PTR(post_process);
+ OPT_PTR(printer_model);
OPT_PTR(printer_notes);
OPT_PTR(resolution);
OPT_PTR(retract_before_travel);
diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp
index a52946afb..d8fe592e8 100644
--- a/xs/src/slic3r/GUI/3DScene.cpp
+++ b/xs/src/slic3r/GUI/3DScene.cpp
@@ -1686,7 +1686,7 @@ bool _3DScene::LegendTexture::generate(const GCodePreviewData& preview_data, con
m_data.clear();
// collects items to render
- auto title = GUI::L_str(preview_data.get_legend_title());
+ auto title = _(preview_data.get_legend_title());
const GCodePreviewData::LegendItemsList& items = preview_data.get_legend_items(tool_colors);
unsigned int items_count = (unsigned int)items.size();
diff --git a/xs/src/slic3r/GUI/Field.cpp b/xs/src/slic3r/GUI/Field.cpp
index 85247b41b..36a1c396f 100644
--- a/xs/src/slic3r/GUI/Field.cpp
+++ b/xs/src/slic3r/GUI/Field.cpp
@@ -45,6 +45,22 @@ namespace Slic3r { namespace GUI {
set_undo_bitmap(&bmp);
set_undo_to_sys_bitmap(&bmp);
+ switch (m_opt.type)
+ {
+ case coPercents:
+ case coFloats:
+ case coStrings:
+ case coBools:
+ case coInts: {
+ auto tag_pos = m_opt_id.find("#");
+ if (tag_pos != std::string::npos)
+ m_opt_idx = stoi(m_opt_id.substr(tag_pos + 1, m_opt_id.size()));
+ break;
+ }
+ default:
+ break;
+ }
+
BUILD();
}
@@ -77,7 +93,7 @@ namespace Slic3r { namespace GUI {
wxString Field::get_tooltip_text(const wxString& default_string)
{
wxString tooltip_text("");
- wxString tooltip = L_str(m_opt.tooltip);
+ wxString tooltip = _(m_opt.tooltip);
if (tooltip.length() > 0)
tooltip_text = tooltip + "(" + _(L("default")) + ": " +
(boost::iends_with(m_opt_id, "_gcode") ? "\n" : "") +
@@ -161,10 +177,10 @@ namespace Slic3r { namespace GUI {
case coFloat:
{
double val = m_opt.type == coFloats ?
- static_cast<const ConfigOptionFloats*>(m_opt.default_value)->get_at(0) :
+ static_cast<const ConfigOptionFloats*>(m_opt.default_value)->get_at(m_opt_idx) :
m_opt.type == coFloat ?
m_opt.default_value->getFloat() :
- static_cast<const ConfigOptionPercents*>(m_opt.default_value)->get_at(0);
+ static_cast<const ConfigOptionPercents*>(m_opt.default_value)->get_at(m_opt_idx);
text_value = double_to_string(val);
break;
}
@@ -174,10 +190,8 @@ namespace Slic3r { namespace GUI {
case coStrings:
{
const ConfigOptionStrings *vec = static_cast<const ConfigOptionStrings*>(m_opt.default_value);
- if (vec == nullptr || vec->empty()) break;
- if (vec->size() > 1)
- break;
- text_value = vec->values.at(0);
+ if (vec == nullptr || vec->empty()) break; //for the case of empty default value
+ text_value = vec->get_at(m_opt_idx);
break;
}
default:
@@ -259,7 +273,7 @@ void CheckBox::BUILD() {
bool check_value = m_opt.type == coBool ?
m_opt.default_value->getBool() : m_opt.type == coBools ?
- static_cast<ConfigOptionBools*>(m_opt.default_value)->values.at(0) :
+ static_cast<ConfigOptionBools*>(m_opt.default_value)->get_at(m_opt_idx) :
false;
auto temp = new wxCheckBox(m_parent, wxID_ANY, wxString(""), wxDefaultPosition, size);
@@ -365,7 +379,7 @@ void Choice::BUILD() {
}
else{
for (auto el : m_opt.enum_labels.empty() ? m_opt.enum_values : m_opt.enum_labels){
- const wxString& str = m_opt_id == "support" ? L_str(el) : el;
+ const wxString& str = _(el);//m_opt_id == "support" ? _(el) : el;
temp->Append(str);
}
set_selection();
@@ -418,7 +432,7 @@ void Choice::set_selection()
break;
}
case coStrings:{
- text_value = static_cast<const ConfigOptionStrings*>(m_opt.default_value)->values.at(0);
+ text_value = static_cast<const ConfigOptionStrings*>(m_opt.default_value)->get_at(m_opt_idx);
size_t idx = 0;
for (auto el : m_opt.enum_values)
@@ -582,7 +596,7 @@ void ColourPicker::BUILD()
if (m_opt.height >= 0) size.SetHeight(m_opt.height);
if (m_opt.width >= 0) size.SetWidth(m_opt.width);
- wxString clr(static_cast<ConfigOptionStrings*>(m_opt.default_value)->values.at(0));
+ wxString clr(static_cast<ConfigOptionStrings*>(m_opt.default_value)->get_at(m_opt_idx));
auto temp = new wxColourPickerCtrl(m_parent, wxID_ANY, clr, wxDefaultPosition, size);
// // recast as a wxWindow to fit the calling convention
@@ -675,6 +689,22 @@ boost::any& PointCtrl::get_value()
return m_value = ret_point;
}
+void StaticText::BUILD()
+{
+ auto size = wxSize(wxDefaultSize);
+ if (m_opt.height >= 0) size.SetHeight(m_opt.height);
+ if (m_opt.width >= 0) size.SetWidth(m_opt.width);
+
+ wxString legend(static_cast<ConfigOptionString*>(m_opt.default_value)->value);
+ auto temp = new wxStaticText(m_parent, wxID_ANY, legend, wxDefaultPosition, size);
+ temp->SetFont(bold_font());
+
+ // // recast as a wxWindow to fit the calling convention
+ window = dynamic_cast<wxWindow*>(temp);
+
+ temp->SetToolTip(get_tooltip_text(legend));
+}
+
} // GUI
} // Slic3r
diff --git a/xs/src/slic3r/GUI/Field.hpp b/xs/src/slic3r/GUI/Field.hpp
index 948178d3e..db8d2a408 100644
--- a/xs/src/slic3r/GUI/Field.hpp
+++ b/xs/src/slic3r/GUI/Field.hpp
@@ -95,6 +95,7 @@ public:
/// Copy of ConfigOption for deduction purposes
const ConfigOptionDef m_opt {ConfigOptionDef()};
const t_config_option_key m_opt_id;//! {""};
+ int m_opt_idx = 0;
/// Sets a value for this control.
/// subclasses should overload with a specific version
@@ -384,6 +385,34 @@ public:
wxSizer* getSizer() override { return sizer; }
};
+class StaticText : public Field {
+ using Field::Field;
+public:
+ StaticText(const ConfigOptionDef& opt, const t_config_option_key& id) : Field(opt, id) {}
+ StaticText(wxWindow* parent, const ConfigOptionDef& opt, const t_config_option_key& id) : Field(parent, opt, id) {}
+ ~StaticText() {}
+
+ wxWindow* window{ nullptr };
+ void BUILD() override;
+
+ void set_value(const std::string& value, bool change_event = false) {
+ m_disable_change_event = !change_event;
+ dynamic_cast<wxStaticText*>(window)->SetLabel(value);
+ m_disable_change_event = false;
+ }
+ void set_value(const boost::any& value, bool change_event = false) {
+ m_disable_change_event = !change_event;
+ dynamic_cast<wxStaticText*>(window)->SetLabel(boost::any_cast<wxString>(value));
+ m_disable_change_event = false;
+ }
+
+ boost::any& get_value()override { return m_value; }
+
+ void enable() override { dynamic_cast<wxColourPickerCtrl*>(window)->Enable(); };
+ void disable() override{ dynamic_cast<wxColourPickerCtrl*>(window)->Disable(); };
+ wxWindow* getWindow() override { return window; }
+};
+
} // GUI
} // Slic3r
diff --git a/xs/src/slic3r/GUI/GUI.cpp b/xs/src/slic3r/GUI/GUI.cpp
index b27da33c8..af7022f2b 100644
--- a/xs/src/slic3r/GUI/GUI.cpp
+++ b/xs/src/slic3r/GUI/GUI.cpp
@@ -56,8 +56,9 @@
#include "../Utils/PresetUpdater.hpp"
#include "../Config/Snapshot.hpp"
-#include "libslic3r/I18N.hpp"
+
#include "3DScene.hpp"
+#include "libslic3r/I18N.hpp"
namespace Slic3r { namespace GUI {
@@ -110,6 +111,7 @@ wxNotebook *g_wxTabPanel = nullptr;
AppConfig *g_AppConfig = nullptr;
PresetBundle *g_PresetBundle= nullptr;
PresetUpdater *g_PresetUpdater = nullptr;
+_3DScene *g_3DScene = nullptr;
wxColour g_color_label_modified;
wxColour g_color_label_sys;
wxColour g_color_label_default;
@@ -118,6 +120,9 @@ std::vector<Tab *> g_tabs_list;
wxLocale* g_wxLocale;
+wxFont g_small_font;
+wxFont g_bold_font;
+
std::shared_ptr<ConfigOptionsGroup> m_optgroup;
double m_brim_width = 0.0;
wxButton* g_wiping_dialog_button = nullptr;
@@ -150,6 +155,16 @@ void update_label_colours_from_appconfig()
}
}
+static void init_fonts()
+{
+ g_small_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
+ g_bold_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT).Bold();
+#ifdef __WXMAC__
+ g_small_font.SetPointSize(11);
+ g_bold_font.SetPointSize(13);
+#endif /*__WXMAC__*/
+}
+
static std::string libslic3r_translate_callback(const char *s) { return wxGetTranslation(wxString(s, wxConvUTF8)).utf8_str().data(); }
void set_wxapp(wxApp *app)
@@ -158,6 +173,7 @@ void set_wxapp(wxApp *app)
// Let the libslic3r know the callback, which will translate messages on demand.
Slic3r::I18N::set_translate_callback(libslic3r_translate_callback);
init_label_colours();
+ init_fonts();
}
void set_main_frame(wxFrame *main_frame)
@@ -185,6 +201,11 @@ void set_preset_updater(PresetUpdater *updater)
g_PresetUpdater = updater;
}
+void set_3DScene(_3DScene *scene)
+{
+ g_3DScene = scene;
+}
+
std::vector<Tab *>& get_tabs_list()
{
return g_tabs_list;
@@ -675,6 +696,14 @@ void set_label_clr_sys(const wxColour& clr) {
g_AppConfig->save();
}
+const wxFont& small_font(){
+ return g_small_font;
+}
+
+const wxFont& bold_font(){
+ return g_bold_font;
+}
+
const wxColour& get_label_clr_default() {
return g_color_label_default;
}
diff --git a/xs/src/slic3r/GUI/GUI.hpp b/xs/src/slic3r/GUI/GUI.hpp
index 83052cb6e..efb11b7df 100644
--- a/xs/src/slic3r/GUI/GUI.hpp
+++ b/xs/src/slic3r/GUI/GUI.hpp
@@ -11,7 +11,7 @@
class wxApp;
class wxWindow;
class wxFrame;
-class wxWindow;
+class wxFont;
class wxMenuBar;
class wxNotebook;
class wxComboCtrl;
@@ -32,6 +32,7 @@ class AppConfig;
class PresetUpdater;
class DynamicPrintConfig;
class TabIface;
+class _3DScene;
#define _(s) Slic3r::GUI::I18N::translate((s))
@@ -90,6 +91,7 @@ void set_tab_panel(wxNotebook *tab_panel);
void set_app_config(AppConfig *app_config);
void set_preset_bundle(PresetBundle *preset_bundle);
void set_preset_updater(PresetUpdater *updater);
+void set_3DScene(_3DScene *scene);
AppConfig* get_app_config();
wxApp* get_app();
@@ -102,6 +104,9 @@ unsigned get_colour_approx_luma(const wxColour &colour);
void set_label_clr_modified(const wxColour& clr);
void set_label_clr_sys(const wxColour& clr);
+const wxFont& small_font();
+const wxFont& bold_font();
+
extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change);
// This is called when closing the application, when loading a config file or when starting the config wizard
diff --git a/xs/src/slic3r/GUI/OptionsGroup.cpp b/xs/src/slic3r/GUI/OptionsGroup.cpp
index 629a9f3a0..d5cc29e19 100644
--- a/xs/src/slic3r/GUI/OptionsGroup.cpp
+++ b/xs/src/slic3r/GUI/OptionsGroup.cpp
@@ -31,6 +31,8 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
m_fields.emplace(id, STDMOVE(Choice::Create<Choice>(parent(), opt, id)));
} else if (opt.gui_type.compare("slider") == 0) {
} else if (opt.gui_type.compare("i_spin") == 0) { // Spinctrl
+ } else if (opt.gui_type.compare("legend") == 0) { // StaticText
+ m_fields.emplace(id, STDMOVE(StaticText::Create<StaticText>(parent(), opt, id)));
} else {
switch (opt.type) {
case coFloatOrPercent:
@@ -86,7 +88,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
if (!this->m_disabled)
this->back_to_sys_value(opt_id);
};
- if (!m_is_tab_opt) {
+ if (!m_show_modified_btns) {
field->m_Undo_btn->Hide();
field->m_Undo_to_sys_btn->Hide();
}
@@ -199,7 +201,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
ConfigOptionDef option = opt.opt;
// add label if any
if (option.label != "") {
- wxString str_label = L_str(option.label);
+ wxString str_label = _(option.label);
//! To correct translation by context have to use wxGETTEXT_IN_CONTEXT macro from wxWidget 3.1.1
// wxString str_label = (option.label == "Top" || option.label == "Bottom") ?
// wxGETTEXT_IN_CONTEXT("Layers", wxString(option.label.c_str()):
@@ -220,7 +222,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
// add sidetext if any
if (option.sidetext != "") {
- auto sidetext = new wxStaticText(parent(), wxID_ANY, L_str(option.sidetext), wxDefaultPosition, wxDefaultSize);
+ auto sidetext = new wxStaticText(parent(), wxID_ANY, _(option.sidetext), wxDefaultPosition, wxDefaultSize);
sidetext->SetFont(sidetext_font);
sizer->Add(sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4);
}
@@ -242,7 +244,7 @@ void OptionsGroup::append_line(const Line& line, wxStaticText** colored_Label/*
}
Line OptionsGroup::create_single_option_line(const Option& option) const {
- Line retval{ L_str(option.opt.label), L_str(option.opt.tooltip) };
+ Line retval{ _(option.opt.label), _(option.opt.tooltip) };
Option tmp(option);
tmp.opt.label = std::string("");
retval.append_option(tmp);
diff --git a/xs/src/slic3r/GUI/OptionsGroup.hpp b/xs/src/slic3r/GUI/OptionsGroup.hpp
index 83b5b1233..422e1afd9 100644
--- a/xs/src/slic3r/GUI/OptionsGroup.hpp
+++ b/xs/src/slic3r/GUI/OptionsGroup.hpp
@@ -127,9 +127,15 @@ public:
inline void enable() { for (auto& field : m_fields) field.second->enable(); }
inline void disable() { for (auto& field : m_fields) field.second->disable(); }
+ void set_show_modified_btns_val(bool show) {
+ m_show_modified_btns = show;
+ }
+
OptionsGroup(wxWindow* _parent, const wxString& title, bool is_tab_opt=false) :
- m_parent(_parent), title(title), m_is_tab_opt(is_tab_opt), staticbox(title!="") {
- sizer = (staticbox ? new wxStaticBoxSizer(new wxStaticBox(_parent, wxID_ANY, title), wxVERTICAL) : new wxBoxSizer(wxVERTICAL));
+ m_parent(_parent), title(title), m_show_modified_btns(is_tab_opt), staticbox(title!="") {
+ auto stb = new wxStaticBox(_parent, wxID_ANY, title);
+ stb->SetFont(bold_font());
+ sizer = (staticbox ? new wxStaticBoxSizer(stb/*new wxStaticBox(_parent, wxID_ANY, title)*/, wxVERTICAL) : new wxBoxSizer(wxVERTICAL));
auto num_columns = 1U;
if (label_width != 0) num_columns++;
if (extra_column != nullptr) num_columns++;
@@ -156,7 +162,7 @@ protected:
bool m_disabled {false};
wxGridSizer* m_grid_sizer {nullptr};
// "true" if option is created in preset tabs
- bool m_is_tab_opt{ false };
+ bool m_show_modified_btns{ false };
// This panel is needed for correct showing of the ToolTips for Button, StaticText and CheckBox
// Tooltips on GTK doesn't work inside wxStaticBoxSizer unless you insert a panel
diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp
index f3cedd693..91a2aa7bd 100644
--- a/xs/src/slic3r/GUI/Preset.cpp
+++ b/xs/src/slic3r/GUI/Preset.cpp
@@ -327,6 +327,11 @@ const std::vector<std::string>& Preset::printer_options()
"single_extruder_multi_material", "start_gcode", "end_gcode", "before_layer_gcode", "layer_gcode", "toolchange_gcode",
"between_objects_gcode", "printer_vendor", "printer_model", "printer_variant", "printer_notes", "cooling_tube_retraction",
"cooling_tube_length", "parking_pos_retraction", "extra_loading_move", "max_print_height", "default_print_profile", "inherits",
+ "silent_mode", "machine_max_acceleration_extruding", "machine_max_acceleration_retracting",
+ "machine_max_acceleration_x", "machine_max_acceleration_y", "machine_max_acceleration_z", "machine_max_acceleration_e",
+ "machine_max_feedrate_x", "machine_max_feedrate_y", "machine_max_feedrate_z", "machine_max_feedrate_e",
+ "machine_min_extruding_rate", "machine_min_travel_rate",
+ "machine_max_jerk_x", "machine_max_jerk_y", "machine_max_jerk_z", "machine_max_jerk_e"
};
s_opts.insert(s_opts.end(), Preset::nozzle_options().begin(), Preset::nozzle_options().end());
}
diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp
index aa1c9c124..911ec0cbe 100644
--- a/xs/src/slic3r/GUI/Tab.cpp
+++ b/xs/src/slic3r/GUI/Tab.cpp
@@ -1605,6 +1605,22 @@ void TabPrinter::build()
optgroup = page->new_optgroup(_(L("Firmware")));
optgroup->append_single_option_line("gcode_flavor");
+ optgroup->append_single_option_line("silent_mode");
+
+ optgroup->m_on_change = [this, optgroup](t_config_option_key opt_key, boost::any value){
+ wxTheApp->CallAfter([this, opt_key, value](){
+ if (opt_key.compare("silent_mode") == 0) {
+ bool val = boost::any_cast<bool>(value);
+ if (m_use_silent_mode != val) {
+ m_rebuild_kinematics_page = true;
+ m_use_silent_mode = val;
+ }
+ }
+ build_extruder_pages();
+ update_dirty();
+ on_value_change(opt_key, value);
+ });
+ };
optgroup = page->new_optgroup(_(L("Advanced")));
optgroup->append_single_option_line("use_relative_e_distances");
@@ -1686,8 +1702,94 @@ void TabPrinter::extruders_count_changed(size_t extruders_count){
on_value_change("extruders_count", extruders_count);
}
-void TabPrinter::build_extruder_pages(){
+void TabPrinter::append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key)
+{
+ auto option = optgroup->get_option(opt_key, 0);
+ auto line = Line{ option.opt.full_label, "" };
+ line.append_option(option);
+ if (m_use_silent_mode)
+ line.append_option(optgroup->get_option(opt_key, 1));
+ optgroup->append_line(line);
+}
+
+PageShp TabPrinter::build_kinematics_page()
+{
+ auto page = add_options_page(_(L("Machine limits")), "cog.png", true);
+
+ if (m_use_silent_mode) {
+ // Legend for OptionsGroups
+ auto optgroup = page->new_optgroup(_(L("")));
+ optgroup->set_show_modified_btns_val(false);
+ optgroup->label_width = 230;
+ auto line = Line{ "", "" };
+
+ ConfigOptionDef def;
+ def.type = coString;
+ def.width = 150;
+ def.gui_type = "legend";
+ def.tooltip = L("Values in this column are for Full Power mode");
+ def.default_value = new ConfigOptionString{ L("Full Power") };
+
+ auto option = Option(def, "full_power_legend");
+ line.append_option(option);
+
+ def.tooltip = L("Values in this column are for Silent mode");
+ def.default_value = new ConfigOptionString{ L("Silent") };
+ option = Option(def, "silent_legend");
+ line.append_option(option);
+
+ optgroup->append_line(line);
+ }
+
+ std::vector<std::string> axes{ "x", "y", "z", "e" };
+ auto optgroup = page->new_optgroup(_(L("Maximum accelerations")));
+ for (const std::string &axis : axes) {
+ append_option_line(optgroup, "machine_max_acceleration_" + axis);
+ }
+
+ optgroup = page->new_optgroup(_(L("Maximum feedrates")));
+ for (const std::string &axis : axes) {
+ append_option_line(optgroup, "machine_max_feedrate_" + axis);
+ }
+
+ optgroup = page->new_optgroup(_(L("Starting Acceleration")));
+ append_option_line(optgroup, "machine_max_acceleration_extruding");
+ append_option_line(optgroup, "machine_max_acceleration_retracting");
+
+ optgroup = page->new_optgroup(_(L("Advanced")));
+ append_option_line(optgroup, "machine_min_extruding_rate");
+ append_option_line(optgroup, "machine_min_travel_rate");
+ for (const std::string &axis : axes) {
+ append_option_line(optgroup, "machine_max_jerk_" + axis);
+ }
+
+ return page;
+}
+
+
+void TabPrinter::build_extruder_pages()
+{
size_t n_before_extruders = 2; // Count of pages before Extruder pages
+ bool is_marlin_flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin;
+
+ // Add/delete Kinematics page according to is_marlin_flavor
+ size_t existed_page = 0;
+ for (int i = n_before_extruders; i < m_pages.size(); ++i) // first make sure it's not there already
+ if (m_pages[i]->title().find(_(L("Machine limits"))) != std::string::npos) {
+ if (!is_marlin_flavor || m_rebuild_kinematics_page)
+ m_pages.erase(m_pages.begin() + i);
+ else
+ existed_page = i;
+ break;
+ }
+
+ if (existed_page < n_before_extruders && is_marlin_flavor){
+ auto page = build_kinematics_page();
+ m_pages.insert(m_pages.begin() + n_before_extruders, page);
+ }
+
+ if (is_marlin_flavor)
+ n_before_extruders++;
size_t n_after_single_extruder_MM = 2; // Count of pages after single_extruder_multi_material page
if (m_extruders_count_old == m_extruders_count ||
@@ -1796,6 +1898,17 @@ void TabPrinter::update(){
get_field("toolchange_gcode")->toggle(have_multiple_extruders);
get_field("single_extruder_multi_material")->toggle(have_multiple_extruders);
+ bool is_marlin_flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value == gcfMarlin;
+
+ const std::string &printer_model = m_config->opt_string("printer_model");
+ bool can_use_silent_mode = printer_model.empty() ? false : printer_model == "MK3"; // "true" only for MK3 printers
+
+ get_field("silent_mode")->toggle(can_use_silent_mode && is_marlin_flavor);
+ if (can_use_silent_mode && m_use_silent_mode != m_config->opt_bool("silent_mode")) {
+ m_rebuild_kinematics_page = true;
+ m_use_silent_mode = m_config->opt_bool("silent_mode");
+ }
+
for (size_t i = 0; i < m_extruders_count; ++i) {
bool have_retract_length = m_config->opt_float("retract_length", i) > 0;
@@ -1914,7 +2027,8 @@ void Tab::rebuild_page_tree()
auto itemId = m_treectrl->AppendItem(rootItem, p->title(), p->iconID());
m_treectrl->SetItemTextColour(itemId, p->get_item_colour());
if (p->title() == selected) {
- m_disable_tree_sel_changed_event = 1;
+ if (!(p->title() == _(L("Machine limits")) || p->title() == _(L("Single extruder MM setup")))) // These Pages have to be updated inside OnTreeSelChange
+ m_disable_tree_sel_changed_event = 1;
m_treectrl->SelectItem(itemId);
m_disable_tree_sel_changed_event = 0;
have_selection = 1;
diff --git a/xs/src/slic3r/GUI/Tab.hpp b/xs/src/slic3r/GUI/Tab.hpp
index 0c43f9c97..8b4eae7de 100644
--- a/xs/src/slic3r/GUI/Tab.hpp
+++ b/xs/src/slic3r/GUI/Tab.hpp
@@ -316,6 +316,9 @@ public:
class TabPrinter : public Tab
{
bool m_has_single_extruder_MM_page = false;
+ bool m_use_silent_mode = false;
+ void append_option_line(ConfigOptionsGroupShp optgroup, const std::string opt_key);
+ bool m_rebuild_kinematics_page = false;
public:
wxButton* m_serial_test_btn;
wxButton* m_octoprint_host_test_btn;
@@ -333,6 +336,7 @@ public:
void update() override;
void update_serial_ports();
void extruders_count_changed(size_t extruders_count);
+ PageShp build_kinematics_page();
void build_extruder_pages();
void on_preset_loaded() override;
void init_options_list() override;
diff --git a/xs/xsp/GUI.xsp b/xs/xsp/GUI.xsp
index af0612f19..6b05e9a67 100644
--- a/xs/xsp/GUI.xsp
+++ b/xs/xsp/GUI.xsp
@@ -101,3 +101,6 @@ void desktop_open_datadir_folder()
void fix_model_by_win10_sdk_gui(ModelObject *model_object_src, Print *print, Model *model_dst)
%code%{ Slic3r::fix_model_by_win10_sdk_gui(*model_object_src, *print, *model_dst); %};
+
+void set_3DScene(SV *scene)
+ %code%{ Slic3r::GUI::set_3DScene((_3DScene *)wxPli_sv_2_object(aTHX_ scene, "Slic3r::Model::3DScene") ); %};
diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp
index e336131d0..717064916 100644
--- a/xs/xsp/Print.xsp
+++ b/xs/xsp/Print.xsp
@@ -145,8 +145,10 @@ _constant()
%code%{ RETVAL = &THIS->skirt; %};
Ref<ExtrusionEntityCollection> brim()
%code%{ RETVAL = &THIS->brim; %};
- std::string estimated_print_time()
- %code%{ RETVAL = THIS->estimated_print_time; %};
+ std::string estimated_normal_print_time()
+ %code%{ RETVAL = THIS->estimated_normal_print_time; %};
+ std::string estimated_silent_print_time()
+ %code%{ RETVAL = THIS->estimated_silent_print_time; %};
PrintObjectPtrs* objects()
%code%{ RETVAL = &THIS->objects; %};