FIX: backend get the extruder id based on filament_map

Change-Id: Ib7679c0fc67336e462467dab9f5b4d4684d6eb19
(cherry picked from commit dcd9fd501354da33baea2adc0f645fabe8880cf1)
This commit is contained in:
zhimin.zeng
2024-07-02 19:26:52 +08:00
committed by Noisyfox
parent f5d2a1bc0c
commit 8db3e3cd54
20 changed files with 193 additions and 131 deletions

View File

@@ -12,7 +12,7 @@ Extruder::Extruder(unsigned int id, GCodeConfig *config, bool share_extruder) :
m_share_extruder(share_extruder) m_share_extruder(share_extruder)
{ {
reset(); reset();
// cache values that are going to be called often // cache values that are going to be called often
m_e_per_mm3 = this->filament_flow_ratio(); m_e_per_mm3 = this->filament_flow_ratio();
m_e_per_mm3 /= this->filament_crossection(); m_e_per_mm3 /= this->filament_crossection();
@@ -20,7 +20,11 @@ Extruder::Extruder(unsigned int id, GCodeConfig *config, bool share_extruder) :
unsigned int Extruder::extruder_id() const unsigned int Extruder::extruder_id() const
{ {
return get_extruder_index(m_id); assert(m_config);
if (m_id < m_config->filament_map.size()) {
return m_config->filament_map.get_at(m_id);
}
return 0;
} }
double Extruder::extrude(double dE) double Extruder::extrude(double dE)
@@ -47,7 +51,7 @@ double Extruder::extrude(double dE)
/* This method makes sure the extruder is retracted by the specified amount /* This method makes sure the extruder is retracted by the specified amount
of filament and returns the amount of filament retracted. of filament and returns the amount of filament retracted.
If the extruder is already retracted by the same or a greater amount, If the extruder is already retracted by the same or a greater amount,
this method is a no-op. this method is a no-op.
The restart_extra argument sets the extra length to be used for The restart_extra argument sets the extra length to be used for
unretraction. If we're actually performing a retraction, any restart_extra unretraction. If we're actually performing a retraction, any restart_extra

View File

@@ -435,7 +435,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
if (new_filament_id != -1 && new_filament_id != tcr.new_tool) if (new_filament_id != -1 && new_filament_id != tcr.new_tool)
throw Slic3r::InvalidArgument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect."); throw Slic3r::InvalidArgument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect.");
int new_extruder_id = get_extruder_index(new_filament_id); int new_extruder_id = get_extruder_index(*m_print_config, new_filament_id);
std::string gcode; std::string gcode;
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin (except for priming lines) // Toolchangeresult.gcode assumes the wipe tower corner is at the origin (except for priming lines)
@@ -1534,7 +1534,7 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu
bool activate_long_retraction_when_cut = false; bool activate_long_retraction_when_cut = false;
for (const auto& extruder : m_writer.extruders()) for (const auto& extruder : m_writer.extruders())
activate_long_retraction_when_cut |= ( activate_long_retraction_when_cut |= (
m_config.long_retractions_when_cut.get_at(extruder.extruder_id()) m_config.long_retractions_when_cut.get_at(extruder.extruder_id())
&& m_config.retraction_distances_when_cut.get_at(extruder.extruder_id()) > 0 && m_config.retraction_distances_when_cut.get_at(extruder.extruder_id()) > 0
); );
@@ -1821,6 +1821,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
{ {
PROFILE_FUNC(); PROFILE_FUNC();
m_print = &print;
// modifies m_silent_time_estimator_enabled // modifies m_silent_time_estimator_enabled
DoExport::init_gcode_processor(print.config(), m_processor, m_silent_time_estimator_enabled); DoExport::init_gcode_processor(print.config(), m_processor, m_silent_time_estimator_enabled);
const bool is_bbl_printers = print.is_BBL_printer(); const bool is_bbl_printers = print.is_BBL_printer();
@@ -2155,7 +2157,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
m_cooling_buffer = make_unique<CoolingBuffer>(*this); m_cooling_buffer = make_unique<CoolingBuffer>(*this);
m_cooling_buffer->set_current_extruder(initial_extruder_id); m_cooling_buffer->set_current_extruder(initial_extruder_id);
int extruder_id = get_extruder_index(initial_extruder_id); int extruder_id = get_extruder_id(initial_extruder_id);
// Orca: Initialise AdaptivePA processor filter // Orca: Initialise AdaptivePA processor filter
m_pa_processor = std::make_unique<AdaptivePAProcessor>(*this, tool_ordering.all_extruders()); m_pa_processor = std::make_unique<AdaptivePAProcessor>(*this, tool_ordering.all_extruders());
@@ -2741,6 +2743,18 @@ void GCode::check_placeholder_parser_failed()
} }
} }
size_t GCode::get_extruder_id(unsigned int filament_id) const
{
if (m_print) {
std::vector<int> filament_maps = m_print->get_filament_maps();
if (filament_id < filament_maps.size()) {
return filament_maps[filament_id];
}
}
return 0;
}
// Process all layers of all objects (non-sequential mode) with a parallel pipeline: // Process all layers of all objects (non-sequential mode) with a parallel pipeline:
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser // Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
// and export G-code into file. // and export G-code into file.
@@ -6370,7 +6384,7 @@ std::string GCode::retract(bool toolchange, bool is_last_retraction, LiftType li
std::string GCode::set_extruder(unsigned int filament_id, double print_z, bool by_object) std::string GCode::set_extruder(unsigned int filament_id, double print_z, bool by_object)
{ {
int extruder_id = get_extruder_index(filament_id); int extruder_id = get_extruder_id(filament_id);
if (!m_writer.need_toolchange(filament_id)) if (!m_writer.need_toolchange(filament_id))
return ""; return "";

View File

@@ -93,7 +93,8 @@ public:
m_plate_origin(plate_origin), m_plate_origin(plate_origin),
m_single_extruder_multi_material(print_config.single_extruder_multi_material), m_single_extruder_multi_material(print_config.single_extruder_multi_material),
m_enable_timelapse_print(print_config.timelapse_type.value == TimelapseType::tlSmooth), m_enable_timelapse_print(print_config.timelapse_type.value == TimelapseType::tlSmooth),
m_is_first_print(true) m_is_first_print(true),
m_print_config(&print_config)
{} {}
std::string prime(GCode &gcodegen); std::string prime(GCode &gcodegen);
@@ -136,6 +137,7 @@ private:
bool m_single_extruder_multi_material; bool m_single_extruder_multi_material;
bool m_enable_timelapse_print; bool m_enable_timelapse_print;
bool m_is_first_print; bool m_is_first_print;
const PrintConfig * m_print_config;
}; };
class ColorPrintColors class ColorPrintColors
@@ -352,6 +354,7 @@ private:
//BBS //BBS
void check_placeholder_parser_failed(); void check_placeholder_parser_failed();
size_t get_extruder_id(unsigned int filament_id) const;
void set_last_pos(const Point &pos) { m_last_pos = pos; m_last_pos_defined = true; } void set_last_pos(const Point &pos) { m_last_pos = pos; m_last_pos_defined = true; }
bool last_pos_defined() const { return m_last_pos_defined; } bool last_pos_defined() const { return m_last_pos_defined; }
@@ -584,6 +587,8 @@ private:
bool m_silent_time_estimator_enabled; bool m_silent_time_estimator_enabled;
Print *m_print{nullptr};
// Processor // Processor
GCodeProcessor m_processor; GCodeProcessor m_processor;

View File

@@ -78,7 +78,7 @@ struct CoolingLine
length(0.f), feedrate(0.f), time(0.f), time_max(0.f), slowdown(false) {} length(0.f), feedrate(0.f), time(0.f), time_max(0.f), slowdown(false) {}
bool adjustable(bool slowdown_external_perimeters) const { bool adjustable(bool slowdown_external_perimeters) const {
return (this->type & TYPE_ADJUSTABLE) && return (this->type & TYPE_ADJUSTABLE) &&
(! (this->type & TYPE_EXTERNAL_PERIMETER) || slowdown_external_perimeters) && (! (this->type & TYPE_EXTERNAL_PERIMETER) || slowdown_external_perimeters) &&
this->time < this->time_max; this->time < this->time_max;
} }
@@ -105,7 +105,7 @@ struct CoolingLine
}; };
// Calculate the required per extruder time stretches. // Calculate the required per extruder time stretches.
struct PerExtruderAdjustments struct PerExtruderAdjustments
{ {
// Calculate the total elapsed time per this extruder, adjusted for the slowdown. // Calculate the total elapsed time per this extruder, adjusted for the slowdown.
float elapsed_time_total() const { float elapsed_time_total() const {
@@ -114,7 +114,7 @@ struct PerExtruderAdjustments
time_total += line.time; time_total += line.time;
return time_total; return time_total;
} }
// Calculate the total elapsed time when slowing down // Calculate the total elapsed time when slowing down
// to the minimum extrusion feed rate defined for the current material. // to the minimum extrusion feed rate defined for the current material.
float maximum_time_after_slowdown(bool slowdown_external_perimeters) const { float maximum_time_after_slowdown(bool slowdown_external_perimeters) const {
float time_total = 0.f; float time_total = 0.f;
@@ -185,7 +185,7 @@ struct PerExtruderAdjustments
bool adj2 = l2.adjustable(); bool adj2 = l2.adjustable();
return (adj1 == adj2) ? l1.feedrate > l2.feedrate : adj1; return (adj1 == adj2) ? l1.feedrate > l2.feedrate : adj1;
}); });
for (n_lines_adjustable = 0; for (n_lines_adjustable = 0;
n_lines_adjustable < lines.size() && this->lines[n_lines_adjustable].adjustable(); n_lines_adjustable < lines.size() && this->lines[n_lines_adjustable].adjustable();
++ n_lines_adjustable); ++ n_lines_adjustable);
time_non_adjustable = 0.f; time_non_adjustable = 0.f;
@@ -242,7 +242,7 @@ struct PerExtruderAdjustments
// The following two values are set by sort_lines_by_decreasing_feedrate(): // The following two values are set by sort_lines_by_decreasing_feedrate():
// Number of adjustable lines, at the start of lines. // Number of adjustable lines, at the start of lines.
size_t n_lines_adjustable = 0; size_t n_lines_adjustable = 0;
// Non-adjustable time of lines starting with n_lines_adjustable. // Non-adjustable time of lines starting with n_lines_adjustable.
float time_non_adjustable = 0; float time_non_adjustable = 0;
// Current total time for this extruder. // Current total time for this extruder.
float time_total = 0; float time_total = 0;
@@ -257,7 +257,7 @@ struct PerExtruderAdjustments
// Calculate a new feedrate when slowing down by time_stretch for segments faster than min_feedrate. // Calculate a new feedrate when slowing down by time_stretch for segments faster than min_feedrate.
// Used by non-proportional slow down. // Used by non-proportional slow down.
float new_feedrate_to_reach_time_stretch( float new_feedrate_to_reach_time_stretch(
std::vector<PerExtruderAdjustments*>::const_iterator it_begin, std::vector<PerExtruderAdjustments*>::const_iterator it_end, std::vector<PerExtruderAdjustments*>::const_iterator it_begin, std::vector<PerExtruderAdjustments*>::const_iterator it_end,
float min_feedrate, float time_stretch, size_t max_iter = 20) float min_feedrate, float time_stretch, size_t max_iter = 20)
{ {
float new_feedrate = min_feedrate; float new_feedrate = min_feedrate;
@@ -285,7 +285,7 @@ float new_feedrate_to_reach_time_stretch(
for (size_t i = 0; i < (*it)->n_lines_adjustable; ++i) { for (size_t i = 0; i < (*it)->n_lines_adjustable; ++i) {
const CoolingLine &line = (*it)->lines[i]; const CoolingLine &line = (*it)->lines[i];
if (line.feedrate > min_feedrate && line.feedrate < new_feedrate) if (line.feedrate > min_feedrate && line.feedrate < new_feedrate)
// Some of the line segments taken into account in the calculation of nomin / denom are now slower than new_feedrate, // Some of the line segments taken into account in the calculation of nomin / denom are now slower than new_feedrate,
// which makes the new_feedrate lower than it should be. // which makes the new_feedrate lower than it should be.
// Re-run the calculation with a new min_feedrate limit, so that the segments with current feedrate lower than new_feedrate // Re-run the calculation with a new min_feedrate limit, so that the segments with current feedrate lower than new_feedrate
// are not taken into account. // are not taken into account.
@@ -361,7 +361,7 @@ std::vector<PerExtruderAdjustments> CoolingBuffer::parse_layer_gcode(const std::
// Time of any other movements before the first extrusion will be excluded from the layer time. // Time of any other movements before the first extrusion will be excluded from the layer time.
bool layer_had_extrusion = false; bool layer_had_extrusion = false;
for (; *line_start != 0; line_start = line_end) for (; *line_start != 0; line_start = line_end)
{ {
while (*line_end != '\n' && *line_end != 0) while (*line_end != '\n' && *line_end != 0)
++ line_end; ++ line_end;
@@ -574,7 +574,7 @@ static inline void extruder_range_slow_down_non_proportional(
} }
assert(feedrate > 0.f); assert(feedrate > 0.f);
// Sort by slow_down_min_speed, maximum speed first. // Sort by slow_down_min_speed, maximum speed first.
std::sort(by_min_print_speed.begin(), by_min_print_speed.end(), std::sort(by_min_print_speed.begin(), by_min_print_speed.end(),
[](const PerExtruderAdjustments *p1, const PerExtruderAdjustments *p2){ return p1->slow_down_min_speed > p2->slow_down_min_speed; }); [](const PerExtruderAdjustments *p1, const PerExtruderAdjustments *p2){ return p1->slow_down_min_speed > p2->slow_down_min_speed; });
// Slow down, fast moves first. // Slow down, fast moves first.
for (;;) { for (;;) {
@@ -696,7 +696,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
// Source G-code for the current layer. // Source G-code for the current layer.
const std::string &gcode, const std::string &gcode,
// ID of the current layer, used to disable fan for the first n layers. // ID of the current layer, used to disable fan for the first n layers.
size_t layer_id, size_t layer_id,
// Total time of this layer after slow down, used to control the fan. // Total time of this layer after slow down, used to control the fan.
float layer_time, float layer_time,
// Per extruder list of G-code lines and their cool down attributes. // Per extruder list of G-code lines and their cool down attributes.

View File

@@ -354,7 +354,7 @@ std::vector<unsigned int> ToolOrdering::generate_first_layer_tool_order(const Pr
auto first_layer = object->get_layer(0); auto first_layer = object->get_layer(0);
for (auto layerm : first_layer->regions()) { for (auto layerm : first_layer->regions()) {
int extruder_id = layerm->region().config().option("wall_filament")->getInt(); int extruder_id = layerm->region().config().option("wall_filament")->getInt();
for (auto expoly : layerm->raw_slices) { for (auto expoly : layerm->raw_slices) {
const double nozzle_diameter = print.config().nozzle_diameter.get_at(0); const double nozzle_diameter = print.config().nozzle_diameter.get_at(0);
const coordf_t initial_layer_line_width = print.config().get_abs_value("initial_layer_line_width", nozzle_diameter); const coordf_t initial_layer_line_width = print.config().get_abs_value("initial_layer_line_width", nozzle_diameter);
@@ -486,7 +486,7 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
for (auto layer : object.layers()) { for (auto layer : object.layers()) {
LayerTools &layer_tools = this->tools_for_layer(layer->print_z); LayerTools &layer_tools = this->tools_for_layer(layer->print_z);
// Override extruder with the next // Override extruder with the next
for (; it_per_layer_extruder_override != per_layer_extruder_switches.end() && it_per_layer_extruder_override->first < layer->print_z + EPSILON; ++ it_per_layer_extruder_override) for (; it_per_layer_extruder_override != per_layer_extruder_switches.end() && it_per_layer_extruder_override->first < layer->print_z + EPSILON; ++ it_per_layer_extruder_override)
extruder_override = (int)it_per_layer_extruder_override->second; extruder_override = (int)it_per_layer_extruder_override->second;
@@ -552,7 +552,7 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
sort_remove_duplicates(firstLayerExtruders); sort_remove_duplicates(firstLayerExtruders);
const_cast<PrintObject&>(object).object_first_layer_wall_extruders = firstLayerExtruders; const_cast<PrintObject&>(object).object_first_layer_wall_extruders = firstLayerExtruders;
for (auto& layer : m_layer_tools) { for (auto& layer : m_layer_tools) {
// Sort and remove duplicates // Sort and remove duplicates
sort_remove_duplicates(layer.extruders); sort_remove_duplicates(layer.extruders);
@@ -1057,7 +1057,11 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume()
size_t nozzle_nums = print_config->nozzle_diameter.values.size(); size_t nozzle_nums = print_config->nozzle_diameter.values.size();
if (nozzle_nums > 1) { if (nozzle_nums > 1) {
std::vector<int> filament_maps = get_recommended_filament_maps(); std::vector<int> filament_maps = get_recommended_filament_maps();
if (filament_maps.empty()) // multi-extruder and one-color
return;
reorder_extruders_for_minimum_flush_volume_multi_extruder(filament_maps); reorder_extruders_for_minimum_flush_volume_multi_extruder(filament_maps);
m_print->update_filament_maps_to_config(filament_maps);
return; return;
} }
@@ -1177,7 +1181,7 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume_multi_extruder(con
nozzle_flush_mtx.emplace_back(wipe_volumes); nozzle_flush_mtx.emplace_back(wipe_volumes);
} }
auto extruders_to_hash_key = [](const std::vector<unsigned int> &extruders, std::optional<unsigned int> initial_extruder_id) -> uint32_t { auto extruders_to_hash_key = [](const std::vector<unsigned int> &extruders, std::optional<unsigned int> initial_extruder_id) -> uint32_t {
uint32_t hash_key = 0; uint32_t hash_key = 0;
// high 16 bit define initial extruder ,low 16 bit define extruder set // high 16 bit define initial extruder ,low 16 bit define extruder set
@@ -1206,7 +1210,7 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume_multi_extruder(con
} }
return false; return false;
}; };
std::optional<unsigned int> current_extruder_id; std::optional<unsigned int> current_extruder_id;
std::vector<std::optional<unsigned int>> nozzle_to_cur_filaments; std::vector<std::optional<unsigned int>> nozzle_to_cur_filaments;

View File

@@ -51,7 +51,7 @@ void GCodeWriter::set_extruders(std::vector<unsigned int> extruder_ids)
m_extruders.reserve(extruder_ids.size()); m_extruders.reserve(extruder_ids.size());
for (unsigned int extruder_id : extruder_ids) for (unsigned int extruder_id : extruder_ids)
m_extruders.emplace_back(Extruder(extruder_id, &this->config, config.single_extruder_multi_material.value)); m_extruders.emplace_back(Extruder(extruder_id, &this->config, config.single_extruder_multi_material.value));
/* we enable support for multiple extruder if any extruder greater than 0 is used /* we enable support for multiple extruder if any extruder greater than 0 is used
(even if prints only uses that one) since we need to output Tx commands (even if prints only uses that one) since we need to output Tx commands
first extruder has index 0 */ first extruder has index 0 */
@@ -61,7 +61,7 @@ void GCodeWriter::set_extruders(std::vector<unsigned int> extruder_ids)
std::string GCodeWriter::preamble() std::string GCodeWriter::preamble()
{ {
std::ostringstream gcode; std::ostringstream gcode;
if (FLAVOR_IS_NOT(gcfMakerWare)) { if (FLAVOR_IS_NOT(gcfMakerWare)) {
gcode << "G90\n"; gcode << "G90\n";
gcode << "G21\n"; gcode << "G21\n";
@@ -82,7 +82,7 @@ std::string GCodeWriter::preamble()
} }
gcode << this->reset_e(true); gcode << this->reset_e(true);
} }
return gcode.str(); return gcode.str();
} }
@@ -207,9 +207,9 @@ std::string GCodeWriter::set_acceleration_internal(Acceleration type, unsigned i
auto& last_value = separate_travel ? m_last_travel_acceleration : m_last_acceleration ; auto& last_value = separate_travel ? m_last_travel_acceleration : m_last_acceleration ;
if (acceleration == 0 || acceleration == last_value) if (acceleration == 0 || acceleration == last_value)
return std::string(); return std::string();
last_value = acceleration; last_value = acceleration;
std::ostringstream gcode; std::ostringstream gcode;
if (FLAVOR_IS(gcfRepetier)) if (FLAVOR_IS(gcfRepetier))
gcode << (separate_travel ? "M202 X" : "M201 X") << acceleration << " Y" << acceleration; gcode << (separate_travel ? "M202 X" : "M201 X") << acceleration << " Y" << acceleration;
@@ -228,7 +228,7 @@ std::string GCodeWriter::set_acceleration_internal(Acceleration type, unsigned i
if (GCodeWriter::full_gcode_comment) gcode << " ; adjust acceleration"; if (GCodeWriter::full_gcode_comment) gcode << " ; adjust acceleration";
gcode << "\n"; gcode << "\n";
return gcode.str(); return gcode.str();
} }
@@ -406,7 +406,7 @@ std::string GCodeWriter::reset_e(bool force)
|| FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfMakerWare)
|| FLAVOR_IS(gcfSailfish)) || FLAVOR_IS(gcfSailfish))
return ""; return "";
if (m_extruder != nullptr) { if (m_extruder != nullptr) {
if (is_zero(m_extruder->E()) && ! force) if (is_zero(m_extruder->E()) && ! force)
return ""; return "";
@@ -433,10 +433,10 @@ std::string GCodeWriter::update_progress(unsigned int num, unsigned int tot, boo
if (config.disable_m73) { if (config.disable_m73) {
return ""; return "";
} }
unsigned int percent = (unsigned int)floor(100.0 * num / tot + 0.5); unsigned int percent = (unsigned int)floor(100.0 * num / tot + 0.5);
if (!allow_100) percent = std::min(percent, (unsigned int)99); if (!allow_100) percent = std::min(percent, (unsigned int)99);
std::ostringstream gcode; std::ostringstream gcode;
gcode << "M73 P" << percent; gcode << "M73 P" << percent;
//BBS //BBS
@@ -499,7 +499,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com
this->set_current_position_clear(true); this->set_current_position_clear(true);
//BBS: take plate offset into consider //BBS: take plate offset into consider
Vec2d point_on_plate = { point(0) - m_x_offset, point(1) - m_y_offset }; Vec2d point_on_plate = { point(0) - m_x_offset, point(1) - m_y_offset };
GCodeG1Formatter w; GCodeG1Formatter w;
w.emit_xy(point_on_plate); w.emit_xy(point_on_plate);
auto speed = m_is_first_layer auto speed = m_is_first_layer
@@ -519,7 +519,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
/* If target Z is lower than current Z but higher than nominal Z we /* If target Z is lower than current Z but higher than nominal Z we
don't perform the Z move but we only move in the XY plane and don't perform the Z move but we only move in the XY plane and
adjust the nominal Z by reducing the lift amount that will be adjust the nominal Z by reducing the lift amount that will be
used for unlift. */ used for unlift. */
// BBS // BBS
Vec3d dest_point = point; Vec3d dest_point = point;
@@ -557,7 +557,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
} }
//BBS: LazyLift //BBS: LazyLift
else if (m_to_lift_type == LiftType::LazyLift && else if (m_to_lift_type == LiftType::LazyLift &&
this->is_current_position_clear() && this->is_current_position_clear() &&
atan2(delta(2), delta_no_z.norm()) < this->extruder()->travel_slope()) { atan2(delta(2), delta_no_z.norm()) < this->extruder()->travel_slope()) {
//BBS: check whether we can make a travel like //BBS: check whether we can make a travel like
// _____ // _____
@@ -612,7 +612,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
the lift. */ the lift. */
m_lifted = 0; m_lifted = 0;
} }
//BBS: take plate offset into consider //BBS: take plate offset into consider
Vec3d point_on_plate = { dest_point(0) - m_x_offset, dest_point(1) - m_y_offset, dest_point(2) }; Vec3d point_on_plate = { dest_point(0) - m_x_offset, dest_point(1) - m_y_offset, dest_point(2) };
std::string out_string; std::string out_string;
@@ -649,7 +649,7 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment)
m_lifted = 0.; m_lifted = 0.;
return ""; return "";
} }
/* In all the other cases, we perform an actual Z move and cancel /* In all the other cases, we perform an actual Z move and cancel
the lift. */ the lift. */
m_lifted = 0; m_lifted = 0;
@@ -665,7 +665,7 @@ std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
speed = m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed") speed = m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed")
: this->config.travel_speed.value; : this->config.travel_speed.value;
} }
GCodeG1Formatter w; GCodeG1Formatter w;
w.emit_z(z); w.emit_z(z);
w.emit_f(speed * 60.0); w.emit_f(speed * 60.0);
@@ -683,7 +683,7 @@ std::string GCodeWriter::_spiral_travel_to_z(double z, const Vec2d &ij_offset, c
speed = m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed") speed = m_is_first_layer ? this->config.get_abs_value("initial_layer_travel_speed")
: this->config.travel_speed.value; : this->config.travel_speed.value;
} }
std::string output = "G17\n"; std::string output = "G17\n";
GCodeG2G3Formatter w(true); GCodeG2G3Formatter w(true);
w.emit_z(z); w.emit_z(z);
@@ -717,7 +717,7 @@ std::string GCodeWriter::extrude_to_xy(const Vec2d &point, double dE, const std:
m_pos(1) = point(1); m_pos(1) = point(1);
if(std::abs(dE) <= std::numeric_limits<double>::epsilon()) if(std::abs(dE) <= std::numeric_limits<double>::epsilon())
force_no_extrusion = true; force_no_extrusion = true;
if (!force_no_extrusion) if (!force_no_extrusion)
m_extruder->extrude(dE); m_extruder->extrude(dE);
@@ -761,7 +761,7 @@ std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std
m_lifted = 0; m_lifted = 0;
if (!force_no_extrusion) if (!force_no_extrusion)
m_extruder->extrude(dE); m_extruder->extrude(dE);
//BBS: take plate offset into consider //BBS: take plate offset into consider
Vec3d point_on_plate = { point(0) - m_x_offset, point(1) - m_y_offset, point(2) }; Vec3d point_on_plate = { point(0) - m_x_offset, point(1) - m_y_offset, point(2) };
@@ -819,7 +819,7 @@ std::string GCodeWriter::_retract(double length, double restart_extra, const std
gcode = w.string(); gcode = w.string();
} }
} }
if (FLAVOR_IS(gcfMakerWare)) if (FLAVOR_IS(gcfMakerWare))
gcode += "M103 ; extruder off\n"; gcode += "M103 ; extruder off\n";
@@ -829,10 +829,10 @@ std::string GCodeWriter::_retract(double length, double restart_extra, const std
std::string GCodeWriter::unretract() std::string GCodeWriter::unretract()
{ {
std::string gcode; std::string gcode;
if (FLAVOR_IS(gcfMakerWare)) if (FLAVOR_IS(gcfMakerWare))
gcode = "M101 ; extruder on\n"; gcode = "M101 ; extruder on\n";
if (double dE = m_extruder->unretract(); !is_zero(dE)) { if (double dE = m_extruder->unretract(); !is_zero(dE)) {
if (this->config.use_firmware_retraction) { if (this->config.use_firmware_retraction) {
gcode += FLAVOR_IS(gcfMachinekit) ? "G23 ; unretract\n" : "G11 ; unretract\n"; gcode += FLAVOR_IS(gcfMachinekit) ? "G23 ; unretract\n" : "G11 ; unretract\n";
@@ -849,7 +849,7 @@ std::string GCodeWriter::unretract()
gcode += w.string(); gcode += w.string();
} }
} }
return gcode; return gcode;
} }
@@ -919,7 +919,7 @@ std::string GCodeWriter::set_fan(const GCodeFlavor gcode_flavor, unsigned int sp
default: default:
gcode << "M106 S" << static_cast<unsigned int>(255.5 * speed / 100.0); break; gcode << "M106 S" << static_cast<unsigned int>(255.5 * speed / 100.0); break;
} }
if (GCodeWriter::full_gcode_comment) if (GCodeWriter::full_gcode_comment)
gcode << " ; enable fan"; gcode << " ; enable fan";
gcode << "\n"; gcode << "\n";
} }

View File

@@ -47,19 +47,19 @@ void Layer::make_slices()
polygons_append(slices_p, to_polygons(layerm->slices.surfaces)); polygons_append(slices_p, to_polygons(layerm->slices.surfaces));
slices = union_safety_offset_ex(slices_p); slices = union_safety_offset_ex(slices_p);
} }
this->lslices.clear(); this->lslices.clear();
this->lslices.reserve(slices.size()); this->lslices.reserve(slices.size());
// prepare ordering points // prepare ordering points
Points ordering_points; Points ordering_points;
ordering_points.reserve(slices.size()); ordering_points.reserve(slices.size());
for (const ExPolygon &ex : slices) for (const ExPolygon &ex : slices)
ordering_points.push_back(ex.contour.first_point()); ordering_points.push_back(ex.contour.first_point());
// sort slices // sort slices
std::vector<Points::size_type> order = chain_points(ordering_points); std::vector<Points::size_type> order = chain_points(ordering_points);
// populate slices vector // populate slices vector
for (size_t i : order) for (size_t i : order)
this->lslices.emplace_back(std::move(slices[i])); this->lslices.emplace_back(std::move(slices[i]));
@@ -178,11 +178,11 @@ bool Layer::is_perimeter_compatible(const PrintRegion& a, const PrintRegion& b)
void Layer::make_perimeters() void Layer::make_perimeters()
{ {
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id(); BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id();
// keep track of regions whose perimeters we have already generated // keep track of regions whose perimeters we have already generated
std::vector<unsigned char> done(m_regions.size(), false); std::vector<unsigned char> done(m_regions.size(), false);
for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm) for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm)
if ((*layerm)->slices.empty()) { if ((*layerm)->slices.empty()) {
(*layerm)->perimeters.clear(); (*layerm)->perimeters.clear();
(*layerm)->fills.clear(); (*layerm)->fills.clear();
@@ -194,7 +194,7 @@ void Layer::make_perimeters()
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id; BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
done[region_id] = true; done[region_id] = true;
const PrintRegion &this_region = (*layerm)->region(); const PrintRegion &this_region = (*layerm)->region();
// find compatible regions // find compatible regions
LayerRegionPtrs layerms; LayerRegionPtrs layerms;
layerms.push_back(*layerm); layerms.push_back(*layerm);
@@ -211,7 +211,7 @@ void Layer::make_perimeters()
done[it - m_regions.begin()] = true; done[it - m_regions.begin()] = true;
} }
} }
if (layerms.size() == 1) { // optimization if (layerms.size() == 1) { // optimization
(*layerm)->fill_surfaces.surfaces.clear(); (*layerm)->fill_surfaces.surfaces.clear();
(*layerm)->make_perimeters((*layerm)->slices, {*layerm}, &(*layerm)->fill_surfaces, &(*layerm)->fill_no_overlap_expolygons); (*layerm)->make_perimeters((*layerm)->slices, {*layerm}, &(*layerm)->fill_surfaces, &(*layerm)->fill_no_overlap_expolygons);
@@ -233,7 +233,7 @@ void Layer::make_perimeters()
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices) for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
new_slices.append(offset_ex(surfaces_with_extra_perimeters.second, ClipperSafetyOffset), surfaces_with_extra_perimeters.second.front()); new_slices.append(offset_ex(surfaces_with_extra_perimeters.second, ClipperSafetyOffset), surfaces_with_extra_perimeters.second.front());
} }
// make perimeters // make perimeters
SurfaceCollection fill_surfaces; SurfaceCollection fill_surfaces;
//BBS //BBS
@@ -241,7 +241,7 @@ void Layer::make_perimeters()
layerm_config->make_perimeters(new_slices, layerms, &fill_surfaces, &fill_no_overlap); layerm_config->make_perimeters(new_slices, layerms, &fill_surfaces, &fill_no_overlap);
// assign fill_surfaces to each layer // assign fill_surfaces to each layer
if (!fill_surfaces.surfaces.empty()) { if (!fill_surfaces.surfaces.empty()) {
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) { for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
// Separate the fill surfaces. // Separate the fill surfaces.
ExPolygons expp = intersection_ex(fill_surfaces.surfaces, (*l)->slices.surfaces); ExPolygons expp = intersection_ex(fill_surfaces.surfaces, (*l)->slices.surfaces);
@@ -272,7 +272,7 @@ void Layer::export_region_slices_to_svg(const char *path) const
for (const auto &surface : region->slices.surfaces) for (const auto &surface : region->slices.surfaces)
svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency); svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency);
export_surface_type_legend_to_svg(svg, legend_pos); export_surface_type_legend_to_svg(svg, legend_pos);
svg.Close(); svg.Close();
} }
// Export to "out/LayerRegion-name-%d.svg" with an increasing index with every export. // Export to "out/LayerRegion-name-%d.svg" with an increasing index with every export.
@@ -422,6 +422,15 @@ coordf_t Layer::get_sparse_infill_max_void_area()
return max_void_area; return max_void_area;
} }
size_t Layer::get_extruder_id(unsigned int filament_id) const
{
std::vector<int> filament_map = m_object->print()->get_filament_maps();
if (filament_id < filament_map.size()) {
return filament_map[filament_id];
}
return 0;
}
BoundingBox get_extents(const LayerRegion &layer_region) BoundingBox get_extents(const LayerRegion &layer_region)
{ {
BoundingBox bbox; BoundingBox bbox;

View File

@@ -241,6 +241,8 @@ public:
return idx; return idx;
} }
size_t get_extruder_id(unsigned int filament_id) const;
protected: protected:
friend class PrintObject; friend class PrintObject;
friend std::vector<Layer*> new_layers(PrintObject*, const std::vector<coordf_t>&); friend std::vector<Layer*> new_layers(PrintObject*, const std::vector<coordf_t>&);

View File

@@ -43,7 +43,7 @@ public:
unsigned short depth; unsigned short depth;
// Children contour, may be both CCW and CW oriented (outer contours or holes). // Children contour, may be both CCW and CW oriented (outer contours or holes).
std::vector<PerimeterGeneratorLoop> children; std::vector<PerimeterGeneratorLoop> children;
PerimeterGeneratorLoop(const Polygon &polygon, unsigned short depth, bool is_contour, bool is_small_width_perimeter = false) : PerimeterGeneratorLoop(const Polygon &polygon, unsigned short depth, bool is_contour, bool is_small_width_perimeter = false) :
polygon(polygon), is_contour(is_contour), is_smaller_width_perimeter(is_small_width_perimeter), depth(depth) {} polygon(polygon), is_contour(is_contour), is_smaller_width_perimeter(is_small_width_perimeter), depth(depth) {}
// External perimeter. It may be CCW or CW oriented (outer contour or hole contour). // External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
@@ -111,7 +111,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
for (const PerimeterGeneratorLoop &loop : loops) { for (const PerimeterGeneratorLoop &loop : loops) {
bool is_external = loop.is_external(); bool is_external = loop.is_external();
bool is_small_width = loop.is_smaller_width_perimeter; bool is_small_width = loop.is_smaller_width_perimeter;
ExtrusionRole role; ExtrusionRole role;
ExtrusionLoopRole loop_role; ExtrusionLoopRole loop_role;
role = is_external ? erExternalPerimeter : erPerimeter; role = is_external ? erExternalPerimeter : erPerimeter;
@@ -225,13 +225,13 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
coll.append(ExtrusionLoop(std::move(paths), loop_role)); coll.append(ExtrusionLoop(std::move(paths), loop_role));
} }
// Append thin walls to the nearest-neighbor search (only for first iteration) // Append thin walls to the nearest-neighbor search (only for first iteration)
if (! thin_walls.empty()) { if (! thin_walls.empty()) {
variable_width(thin_walls, erExternalPerimeter, perimeter_generator.ext_perimeter_flow, coll.entities); variable_width(thin_walls, erExternalPerimeter, perimeter_generator.ext_perimeter_flow, coll.entities);
thin_walls.clear(); thin_walls.clear();
} }
// Traverse children and build the final collection. // Traverse children and build the final collection.
Point zero_point(0, 0); Point zero_point(0, 0);
std::vector<std::pair<size_t, bool>> chain = chain_extrusion_entities(coll.entities, &zero_point); std::vector<std::pair<size_t, bool>> chain = chain_extrusion_entities(coll.entities, &zero_point);
@@ -1133,10 +1133,10 @@ void PerimeterGenerator::process_classic()
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.width() + this->perimeter_flow.width())); ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.width() + this->perimeter_flow.width()));
else else
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing())); ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
// overhang perimeters // overhang perimeters
m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm(); m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
// solid infill // solid infill
coord_t solid_infill_spacing = this->solid_infill_flow.scaled_spacing(); coord_t solid_infill_spacing = this->solid_infill_flow.scaled_spacing();
@@ -1148,7 +1148,7 @@ void PerimeterGenerator::process_classic()
double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->wall_filament - 1); double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->wall_filament - 1);
m_lower_slices_polygons = offset(*this->lower_slices, float(scale_(+nozzle_diameter / 2))); m_lower_slices_polygons = offset(*this->lower_slices, float(scale_(+nozzle_diameter / 2)));
} }
// Calculate the minimum required spacing between two adjacent traces. // Calculate the minimum required spacing between two adjacent traces.
// This should be equal to the nominal flow spacing but we experiment // This should be equal to the nominal flow spacing but we experiment
// with some tolerance in order to avoid triggering medial axis when // with some tolerance in order to avoid triggering medial axis when
@@ -1157,7 +1157,7 @@ void PerimeterGenerator::process_classic()
// For ext_min_spacing we use the ext_perimeter_spacing calculated for two adjacent // For ext_min_spacing we use the ext_perimeter_spacing calculated for two adjacent
// external loops (which is the correct way) instead of using ext_perimeter_spacing2 // external loops (which is the correct way) instead of using ext_perimeter_spacing2
// which is the spacing between external and internal, which is not correct // which is the spacing between external and internal, which is not correct
// and would make the collapsing (thus the details resolution) dependent on // and would make the collapsing (thus the details resolution) dependent on
// internal flow which is unrelated. // internal flow which is unrelated.
coord_t min_spacing = coord_t(perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE)); coord_t min_spacing = coord_t(perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE));
coord_t ext_min_spacing = coord_t(ext_perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE)); coord_t ext_min_spacing = coord_t(ext_perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE));
@@ -1275,16 +1275,16 @@ void PerimeterGenerator::process_classic()
coord_t distance = (i == 1) ? ext_perimeter_spacing2 : perimeter_spacing; coord_t distance = (i == 1) ? ext_perimeter_spacing2 : perimeter_spacing;
//BBS //BBS
//offsets = this->config->thin_walls ? //offsets = this->config->thin_walls ?
// This path will ensure, that the perimeters do not overfill, as in // This path will ensure, that the perimeters do not overfill, as in
// prusa3d/Slic3r GH #32, but with the cost of rounding the perimeters // prusa3d/Slic3r GH #32, but with the cost of rounding the perimeters
// excessively, creating gaps, which then need to be filled in by the not very // excessively, creating gaps, which then need to be filled in by the not very
// reliable gap fill algorithm. // reliable gap fill algorithm.
// Also the offset2(perimeter, -x, x) may sometimes lead to a perimeter, which is larger than // Also the offset2(perimeter, -x, x) may sometimes lead to a perimeter, which is larger than
// the original. // the original.
//offset2_ex(last, //offset2_ex(last,
// - float(distance + min_spacing / 2. - 1.), // - float(distance + min_spacing / 2. - 1.),
// float(min_spacing / 2. - 1.)) : // float(min_spacing / 2. - 1.)) :
// If "detect thin walls" is not enabled, this paths will be entered, which // If "detect thin walls" is not enabled, this paths will be entered, which
// leads to overflows, as in prusa3d/Slic3r GH #32 // leads to overflows, as in prusa3d/Slic3r GH #32
//offset_ex(last, - float(distance)); //offset_ex(last, - float(distance));
@@ -1352,7 +1352,7 @@ void PerimeterGenerator::process_classic()
if (i == loop_number && (! has_gap_fill || this->config->sparse_infill_density.value == 0)) { if (i == loop_number && (! has_gap_fill || this->config->sparse_infill_density.value == 0)) {
// The last run of this loop is executed to collect gaps for gap fill. // The last run of this loop is executed to collect gaps for gap fill.
// As the gap fill is either disabled or not // As the gap fill is either disabled or not
break; break;
} }
} }
@@ -1545,7 +1545,7 @@ void PerimeterGenerator::process_classic()
// fill gaps // fill gaps
if (! gaps.empty()) { if (! gaps.empty()) {
// collapse // collapse
double min = 0.2 * perimeter_width * (1 - INSET_OVERLAP_TOLERANCE); double min = 0.2 * perimeter_width * (1 - INSET_OVERLAP_TOLERANCE);
double max = 2. * perimeter_spacing; double max = 2. * perimeter_spacing;
ExPolygons gaps_ex = diff_ex( ExPolygons gaps_ex = diff_ex(
@@ -1602,7 +1602,7 @@ void PerimeterGenerator::process_classic()
// we offset by half the perimeter spacing (to get to the actual infill boundary) // we offset by half the perimeter spacing (to get to the actual infill boundary)
// and then we offset back and forth by half the infill spacing to only consider the // and then we offset back and forth by half the infill spacing to only consider the
// non-collapsing regions // non-collapsing regions
coord_t inset = coord_t inset =
(loop_number < 0) ? 0 : (loop_number < 0) ? 0 :
(loop_number == 0) ? (loop_number == 0) ?
// one loop // one loop

View File

@@ -80,7 +80,7 @@ void PlaceholderParser::update_timestamp(DynamicConfig &config)
time_t rawtime; time_t rawtime;
time(&rawtime); time(&rawtime);
struct tm* timeinfo = localtime(&rawtime); struct tm* timeinfo = localtime(&rawtime);
{ {
std::ostringstream ss; std::ostringstream ss;
ss << (1900 + timeinfo->tm_year); ss << (1900 + timeinfo->tm_year);
@@ -214,7 +214,7 @@ namespace client
explicit expr(const char *s) : m_type(TYPE_STRING) { m_data.s = new std::string(s); } explicit expr(const char *s) : m_type(TYPE_STRING) { m_data.s = new std::string(s); }
explicit expr(const std::string &s) : m_type(TYPE_STRING) { m_data.s = new std::string(s); } explicit expr(const std::string &s) : m_type(TYPE_STRING) { m_data.s = new std::string(s); }
explicit expr(std::string &&s) : m_type(TYPE_STRING) { m_data.s = new std::string(std::move(s)); } explicit expr(std::string &&s) : m_type(TYPE_STRING) { m_data.s = new std::string(std::move(s)); }
explicit expr(const std::string &s, const Iterator &it_begin, const Iterator &it_end) : explicit expr(const std::string &s, const Iterator &it_begin, const Iterator &it_end) :
m_type(TYPE_STRING), it_range(it_begin, it_end) { m_data.s = new std::string(s); } m_type(TYPE_STRING), it_range(it_begin, it_end) { m_data.s = new std::string(s); }
explicit expr(expr &&rhs, const Iterator &it_begin, const Iterator &it_end) : m_type(rhs.type()), it_range{ it_begin, it_end } explicit expr(expr &&rhs, const Iterator &it_begin, const Iterator &it_end) : m_type(rhs.type()), it_range{ it_begin, it_end }
{ {
@@ -233,8 +233,8 @@ namespace client
return *this; return *this;
} }
expr &operator=(expr &&rhs) expr &operator=(expr &&rhs)
{ {
if (this != &rhs) { if (this != &rhs) {
this->reset(); this->reset();
m_type = rhs.type(); m_type = rhs.type();
@@ -245,7 +245,7 @@ namespace client
return *this; return *this;
} }
void reset() void reset()
{ {
if (this->type() == TYPE_STRING) if (this->type() == TYPE_STRING)
delete m_data.s; delete m_data.s;
@@ -298,8 +298,8 @@ namespace client
else else
this->set_s_take_ownership(new std::string(s)); this->set_s_take_ownership(new std::string(s));
} }
std::string to_string() const std::string to_string() const
{ {
std::string out; std::string out;
switch (this->type()) { switch (this->type()) {
@@ -308,7 +308,7 @@ namespace client
break; break;
case TYPE_BOOL: out = this->b() ? "true" : "false"; break; case TYPE_BOOL: out = this->b() ? "true" : "false"; break;
case TYPE_INT: out = std::to_string(this->i()); break; case TYPE_INT: out = std::to_string(this->i()); break;
case TYPE_DOUBLE: case TYPE_DOUBLE:
#if 0 #if 0
// The default converter produces trailing zeros after the decimal point. // The default converter produces trailing zeros after the decimal point.
out = std::to_string(data.d); out = std::to_string(data.d);
@@ -333,7 +333,7 @@ namespace client
IteratorRange it_range; IteratorRange it_range;
expr unary_minus(const Iterator start_pos) const expr unary_minus(const Iterator start_pos) const
{ {
switch (this->type()) { switch (this->type()) {
case TYPE_EMPTY: case TYPE_EMPTY:
// Inside an if / else block to be skipped. // Inside an if / else block to be skipped.
@@ -351,7 +351,7 @@ namespace client
} }
expr unary_integer(const Iterator start_pos) const expr unary_integer(const Iterator start_pos) const
{ {
switch (this->type()) { switch (this->type()) {
case TYPE_EMPTY: case TYPE_EMPTY:
// Inside an if / else block to be skipped. // Inside an if / else block to be skipped.
@@ -369,7 +369,7 @@ namespace client
} }
expr round(const Iterator start_pos) const expr round(const Iterator start_pos) const
{ {
switch (this->type()) { switch (this->type()) {
case TYPE_EMPTY: case TYPE_EMPTY:
// Inside an if / else block to be skipped. // Inside an if / else block to be skipped.
@@ -387,7 +387,7 @@ namespace client
} }
expr unary_not(const Iterator start_pos) const expr unary_not(const Iterator start_pos) const
{ {
switch (this->type()) { switch (this->type()) {
case TYPE_EMPTY: case TYPE_EMPTY:
// Inside an if / else block to be skipped. // Inside an if / else block to be skipped.
@@ -403,7 +403,7 @@ namespace client
} }
expr &operator+=(const expr &rhs) expr &operator+=(const expr &rhs)
{ {
if (this->type() == TYPE_EMPTY) { if (this->type() == TYPE_EMPTY) {
// Inside an if / else block to be skipped. // Inside an if / else block to be skipped.
} else if (this->type() == TYPE_STRING) { } else if (this->type() == TYPE_STRING) {
@@ -426,7 +426,7 @@ namespace client
} }
expr &operator-=(const expr &rhs) expr &operator-=(const expr &rhs)
{ {
if (this->type() == TYPE_EMPTY) { if (this->type() == TYPE_EMPTY) {
// Inside an if / else block to be skipped. // Inside an if / else block to be skipped.
this->reset(); this->reset();
@@ -444,7 +444,7 @@ namespace client
} }
expr &operator*=(const expr &rhs) expr &operator*=(const expr &rhs)
{ {
if (this->type() == TYPE_EMPTY) { if (this->type() == TYPE_EMPTY) {
// Inside an if / else block to be skipped. // Inside an if / else block to be skipped.
this->reset(); this->reset();
@@ -535,16 +535,16 @@ namespace client
// Both types are numeric. // Both types are numeric.
switch (op) { switch (op) {
case '=': case '=':
value = (lhs.type() == TYPE_DOUBLE || rhs.type() == TYPE_DOUBLE) ? value = (lhs.type() == TYPE_DOUBLE || rhs.type() == TYPE_DOUBLE) ?
(std::abs(lhs.as_d() - rhs.as_d()) < 1e-8) : (lhs.i() == rhs.i()); (std::abs(lhs.as_d() - rhs.as_d()) < 1e-8) : (lhs.i() == rhs.i());
break; break;
case '<': case '<':
value = (lhs.type() == TYPE_DOUBLE || rhs.type() == TYPE_DOUBLE) ? value = (lhs.type() == TYPE_DOUBLE || rhs.type() == TYPE_DOUBLE) ?
(lhs.as_d() < rhs.as_d()) : (lhs.i() < rhs.i()); (lhs.as_d() < rhs.as_d()) : (lhs.i() < rhs.i());
break; break;
case '>': case '>':
default: default:
value = (lhs.type() == TYPE_DOUBLE || rhs.type() == TYPE_DOUBLE) ? value = (lhs.type() == TYPE_DOUBLE || rhs.type() == TYPE_DOUBLE) ?
(lhs.as_d() > rhs.as_d()) : (lhs.i() > rhs.i()); (lhs.as_d() > rhs.as_d()) : (lhs.i() > rhs.i());
break; break;
} }
@@ -556,7 +556,7 @@ namespace client
value = lhs.b() == rhs.b(); value = lhs.b() == rhs.b();
} else if (lhs.type() == TYPE_STRING || rhs.type() == TYPE_STRING) { } else if (lhs.type() == TYPE_STRING || rhs.type() == TYPE_STRING) {
// One type is string, the other could be converted to string. // One type is string, the other could be converted to string.
value = (op == '=') ? (lhs.to_string() == rhs.to_string()) : value = (op == '=') ? (lhs.to_string() == rhs.to_string()) :
(op == '<') ? (lhs.to_string() < rhs.to_string()) : (lhs.to_string() > rhs.to_string()); (op == '<') ? (lhs.to_string() < rhs.to_string()) : (lhs.to_string() > rhs.to_string());
} else { } else {
boost::throw_exception(qi::expectation_failure<Iterator>( boost::throw_exception(qi::expectation_failure<Iterator>(
@@ -576,7 +576,7 @@ namespace client
static void throw_if_not_numeric(const expr &param) static void throw_if_not_numeric(const expr &param)
{ {
const char *err_msg = "Not a numeric type."; const char *err_msg = "Not a numeric type.";
param.throw_if_not_numeric(err_msg); param.throw_if_not_numeric(err_msg);
} }
enum Function2ParamsType { enum Function2ParamsType {
@@ -585,7 +585,7 @@ namespace client
}; };
// Store the result into param1. // Store the result into param1.
static void function_2params(expr &param1, expr &param2, Function2ParamsType fun) static void function_2params(expr &param1, expr &param2, Function2ParamsType fun)
{ {
if (param1.type() == TYPE_EMPTY) if (param1.type() == TYPE_EMPTY)
// Inside an if / else block to be skipped // Inside an if / else block to be skipped
return; return;
@@ -615,7 +615,7 @@ namespace client
// Store the result into param1. // Store the result into param1.
static void random(expr &param1, expr &param2, std::mt19937 &rng) static void random(expr &param1, expr &param2, std::mt19937 &rng)
{ {
if (param1.type() == TYPE_EMPTY) if (param1.type() == TYPE_EMPTY)
// Inside an if / else block to be skipped // Inside an if / else block to be skipped
return; return;
@@ -631,7 +631,7 @@ namespace client
// param3 is optional // param3 is optional
template<bool leading_zeros> template<bool leading_zeros>
static void digits(expr &param1, expr &param2, expr &param3) static void digits(expr &param1, expr &param2, expr &param3)
{ {
if (param1.type() == TYPE_EMPTY) if (param1.type() == TYPE_EMPTY)
// Inside an if / else block to be skipped // Inside an if / else block to be skipped
return; return;
@@ -738,13 +738,13 @@ namespace client
static void logical_or (expr &lhs, expr &rhs) { logical_op(lhs, rhs, '|'); } static void logical_or (expr &lhs, expr &rhs) { logical_op(lhs, rhs, '|'); }
static void logical_and(expr &lhs, expr &rhs) { logical_op(lhs, rhs, '&'); } static void logical_and(expr &lhs, expr &rhs) { logical_op(lhs, rhs, '&'); }
void throw_exception(const char *message) const void throw_exception(const char *message) const
{ {
boost::throw_exception(qi::expectation_failure<Iterator>( boost::throw_exception(qi::expectation_failure<Iterator>(
this->it_range.begin(), this->it_range.end(), spirit::info(std::string("*") + message))); this->it_range.begin(), this->it_range.end(), spirit::info(std::string("*") + message)));
} }
void throw_if_not_numeric(const char *message) const void throw_if_not_numeric(const char *message) const
{ {
if (! this->numeric_type()) if (! this->numeric_type())
this->throw_exception(message); this->throw_exception(message);
@@ -794,7 +794,7 @@ namespace client
mutable DynamicConfig *config_outputs = nullptr; mutable DynamicConfig *config_outputs = nullptr;
// Local variables, read / write // Local variables, read / write
mutable DynamicConfig config_local; mutable DynamicConfig config_local;
size_t current_extruder_id = 0; size_t current_extruder_id = 0; // This is filament_id actually
// Random number generator and optionally global variables. // Random number generator and optionally global variables.
PlaceholderParser::ContextData *context_data = nullptr; PlaceholderParser::ContextData *context_data = nullptr;
// If false, the macro_processor will evaluate a full macro. // If false, the macro_processor will evaluate a full macro.
@@ -805,7 +805,14 @@ namespace client
// Table to translate symbol tag to a human readable error message. // Table to translate symbol tag to a human readable error message.
static std::map<std::string, std::string> tag_to_error_message; static std::map<std::string, std::string> tag_to_error_message;
// Should the parser consider the parsed string to be a macro or a boolean expression? size_t get_extruder_id() const {
const ConfigOptionInts * filament_map_opt = external_config->option<ConfigOptionInts>("filament_map");
if (filament_map_opt && current_extruder_id < filament_map_opt->values.size()) {
return filament_map_opt->values[current_extruder_id];
}
return 0;
}
static bool evaluate_full_macro(const MyContext *ctx) { return ! ctx->just_boolean_expression; } static bool evaluate_full_macro(const MyContext *ctx) { return ! ctx->just_boolean_expression; }
// Entering a conditional block. // Entering a conditional block.
@@ -908,7 +915,7 @@ namespace client
} }
static void legacy_variable_expansion2( static void legacy_variable_expansion2(
const MyContext *ctx, const MyContext *ctx,
IteratorRange &opt_key, IteratorRange &opt_key,
IteratorRange &opt_vector_index, IteratorRange &opt_vector_index,
std::string &output) std::string &output)
@@ -1546,7 +1553,7 @@ namespace client
static void evaluate_index(expr &expr_index, int &output) static void evaluate_index(expr &expr_index, int &output)
{ {
if (expr_index.type() != expr::TYPE_EMPTY) { if (expr_index.type() != expr::TYPE_EMPTY) {
if (expr_index.type() != expr::TYPE_INT) if (expr_index.type() != expr::TYPE_INT)
expr_index.throw_exception("Non-integer index is not allowed to address a vector variable."); expr_index.throw_exception("Non-integer index is not allowed to address a vector variable.");
output = expr_index.i(); output = expr_index.i();
} }
@@ -1738,11 +1745,11 @@ namespace client
// This parser is to be used inside a raw[] directive to accept a single valid UTF-8 character. // This parser is to be used inside a raw[] directive to accept a single valid UTF-8 character.
// If an invalid UTF-8 sequence is encountered, a qi::expectation_failure is thrown. // If an invalid UTF-8 sequence is encountered, a qi::expectation_failure is thrown.
struct utf8_char_parser : qi::primitive_parser<utf8_char_parser> struct utf8_char_parser : qi::primitive_parser<utf8_char_parser>
{ {
// Define the attribute type exposed by this parser component // Define the attribute type exposed by this parser component
template <typename Context, typename Iterator> template <typename Context, typename Iterator>
struct attribute struct attribute
{ {
typedef wchar_t type; typedef wchar_t type;
}; };
@@ -1750,7 +1757,7 @@ namespace client
// Also it throws if it encounters valid or invalid UTF-8 sequence. // Also it throws if it encounters valid or invalid UTF-8 sequence.
template <typename Iterator, typename Context , typename Skipper, typename Attribute> template <typename Iterator, typename Context , typename Skipper, typename Attribute>
bool parse(Iterator &first, Iterator const &last, Context &context, Skipper const &skipper, Attribute& attr) const bool parse(Iterator &first, Iterator const &last, Context &context, Skipper const &skipper, Attribute& attr) const
{ {
// The skipper shall always be empty, any white space will be accepted. // The skipper shall always be empty, any white space will be accepted.
// skip_over(first, last, skipper); // skip_over(first, last, skipper);
if (first == last) if (first == last)
@@ -1794,7 +1801,7 @@ namespace client
// This function is called during error handling to create a human readable string for the error context. // This function is called during error handling to create a human readable string for the error context.
template <typename Context> template <typename Context>
spirit::info what(Context&) const spirit::info what(Context&) const
{ {
return spirit::info("unicode_char"); return spirit::info("unicode_char");
} }
}; };
@@ -2039,7 +2046,7 @@ namespace client
legacy_variable_expansion = legacy_variable_expansion =
(identifier >> &lit(']')) (identifier >> &lit(']'))
[ px::bind(&MyContext::legacy_variable_expansion, _r1, _1, _val) ] [ px::bind(&MyContext::legacy_variable_expansion, _r1, _1, _val) ]
| (identifier > lit('[') > identifier > ']') | (identifier > lit('[') > identifier > ']')
[ px::bind(&MyContext::legacy_variable_expansion2, _r1, _1, _2, _val) ] [ px::bind(&MyContext::legacy_variable_expansion2, _r1, _1, _2, _val) ]
; ;
legacy_variable_expansion.name("legacy_variable_expansion"); legacy_variable_expansion.name("legacy_variable_expansion");
@@ -2057,12 +2064,12 @@ namespace client
eps[px::bind(&MyContext::block_enter, _r1, ! _a)] > conditional_expression(_r1)[px::bind(&MyContext::block_exit_ternary, _r1, ! _a, _1, _val)]); eps[px::bind(&MyContext::block_enter, _r1, ! _a)] > conditional_expression(_r1)[px::bind(&MyContext::block_exit_ternary, _r1, ! _a, _1, _val)]);
conditional_expression.name("conditional_expression"); conditional_expression.name("conditional_expression");
logical_or_expression = logical_or_expression =
logical_and_expression(_r1) [_val = _1] logical_and_expression(_r1) [_val = _1]
>> *( ((kw["or"] | "||") > logical_and_expression(_r1) ) [px::bind(&expr::logical_or, _val, _1)] ); >> *( ((kw["or"] | "||") > logical_and_expression(_r1) ) [px::bind(&expr::logical_or, _val, _1)] );
logical_or_expression.name("logical_or_expression"); logical_or_expression.name("logical_or_expression");
logical_and_expression = logical_and_expression =
equality_expression(_r1) [_val = _1] equality_expression(_r1) [_val = _1]
>> *( ((kw["and"] | "&&") > equality_expression(_r1) ) [px::bind(&expr::logical_and, _val, _1)] ); >> *( ((kw["and"] | "&&") > equality_expression(_r1) ) [px::bind(&expr::logical_and, _val, _1)] );
logical_and_expression.name("logical_and_expression"); logical_and_expression.name("logical_and_expression");
@@ -2082,7 +2089,7 @@ namespace client
bool_expr_eval = conditional_expression(_r1) [ px::bind(&expr::evaluate_boolean, _1, _val) ]; bool_expr_eval = conditional_expression(_r1) [ px::bind(&expr::evaluate_boolean, _1, _val) ];
bool_expr_eval.name("bool_expr_eval"); bool_expr_eval.name("bool_expr_eval");
relational_expression = relational_expression =
additive_expression(_r1) [_val = _1] additive_expression(_r1) [_val = _1]
>> *( ("<=" > additive_expression(_r1) ) [px::bind(&expr::leq, _val, _1)] >> *( ("<=" > additive_expression(_r1) ) [px::bind(&expr::leq, _val, _1)]
| (">=" > additive_expression(_r1) ) [px::bind(&expr::geq, _val, _1)] | (">=" > additive_expression(_r1) ) [px::bind(&expr::geq, _val, _1)]
@@ -2150,11 +2157,11 @@ namespace client
| (lit('-') > unary_expression(_r1) ) [ px::bind(&FactorActions::minus_, _1, _val) ] | (lit('-') > unary_expression(_r1) ) [ px::bind(&FactorActions::minus_, _1, _val) ]
| (lit('+') > unary_expression(_r1) > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ] | (lit('+') > unary_expression(_r1) > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _val) ]
| ((kw["not"] | '!') > unary_expression(_r1) > iter_pos) [ px::bind(&FactorActions::not_, _1, _val) ] | ((kw["not"] | '!') > unary_expression(_r1) > iter_pos) [ px::bind(&FactorActions::not_, _1, _val) ]
| (kw["min"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')') | (kw["min"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')')
[ px::bind(&expr::min, _val, _2) ] [ px::bind(&expr::min, _val, _2) ]
| (kw["max"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')') | (kw["max"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')')
[ px::bind(&expr::max, _val, _2) ] [ px::bind(&expr::max, _val, _2) ]
| (kw["random"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')') | (kw["random"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > ')')
[ px::bind(&MyContext::random, _r1, _val, _2) ] [ px::bind(&MyContext::random, _r1, _val, _2) ]
| (kw["digits"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > optional_parameter(_r1)) | (kw["digits"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > optional_parameter(_r1))
[ px::bind(&expr::digits<false>, _val, _2, _3) ] [ px::bind(&expr::digits<false>, _val, _2, _3) ]

View File

@@ -2603,6 +2603,15 @@ std::vector<int> Print::get_filament_maps() const
return m_config.filament_map.values; return m_config.filament_map.values;
} }
size_t Print::get_extruder_id(unsigned int filament_id) const
{
std::vector<int> filament_map = get_filament_maps();
if (filament_id < filament_map.size()) {
return filament_map[filament_id];
}
return 0;
}
// Wipe tower support. // Wipe tower support.
bool Print::has_wipe_tower() const bool Print::has_wipe_tower() const
{ {

View File

@@ -936,6 +936,7 @@ public:
void update_filament_maps_to_config(std::vector<int> f_maps); void update_filament_maps_to_config(std::vector<int> f_maps);
std::vector<int> get_filament_maps() const; std::vector<int> get_filament_maps() const;
size_t get_extruder_id(unsigned int filament_id) const;
bool enable_timelapse_print() const; bool enable_timelapse_print() const;

View File

@@ -53,9 +53,11 @@ namespace Slic3r {
#define L(s) (s) #define L(s) (s)
#define _(s) Slic3r::I18N::translate(s) #define _(s) Slic3r::I18N::translate(s)
size_t get_extruder_index(unsigned int filament_id) size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id)
{ {
// todo multi_extruders: if (filament_id < config.filament_map.size()) {
return config.filament_map.get_at(filament_id);
}
return 0; return 0;
} }

View File

@@ -462,7 +462,6 @@ static std::string get_bed_temp_1st_layer_key(const BedType type)
return ""; return "";
} }
size_t get_extruder_index(unsigned int filament_id);
#define CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NAME) \ #define CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NAME) \
template<> const t_config_enum_names& ConfigOptionEnum<NAME>::get_enum_names(); \ template<> const t_config_enum_names& ConfigOptionEnum<NAME>::get_enum_names(); \
template<> const t_config_enum_values& ConfigOptionEnum<NAME>::get_enum_values(); template<> const t_config_enum_values& ConfigOptionEnum<NAME>::get_enum_values();
@@ -1969,6 +1968,8 @@ static void set_flush_volumes_matrix(std::vector<T> &out_matrix, const std::vect
} }
} }
size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id);
} // namespace Slic3r } // namespace Slic3r
// Serialization through the Cereal library // Serialization through the Cereal library

View File

@@ -10,8 +10,9 @@ namespace Slic3r {
float CalibPressureAdvance::find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx) float CalibPressureAdvance::find_optimal_PA_speed(const DynamicPrintConfig &config, double line_width, double layer_height, int filament_idx)
{ {
const double general_suggested_min_speed = 100.0; const double general_suggested_min_speed = 100.0;
double filament_max_volumetric_speed = config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(0); double filament_max_volumetric_speed = config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(filament_idx);
const float nozzle_diameter = config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0); // todo multi_extruders:
const float nozzle_diameter = config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0/*get_extruder_index(filament_idx)*/);
if (line_width <= 0.) line_width = Flow::auto_extrusion_width(frPerimeter, nozzle_diameter); if (line_width <= 0.) line_width = Flow::auto_extrusion_width(frPerimeter, nozzle_diameter);
Flow pattern_line = Flow(line_width, layer_height, nozzle_diameter); Flow pattern_line = Flow(line_width, layer_height, nozzle_diameter);
auto pa_speed = std::min(std::max(general_suggested_min_speed, config.option<ConfigOptionFloat>("outer_wall_speed")->value), auto pa_speed = std::min(std::max(general_suggested_min_speed, config.option<ConfigOptionFloat>("outer_wall_speed")->value),

View File

@@ -303,6 +303,7 @@ public:
Vec3d get_start_offset(); Vec3d get_start_offset();
protected: protected:
// todo multi_extruders:
double speed_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_speed")->value; }; double speed_first_layer() const { return m_config.option<ConfigOptionFloat>("initial_layer_speed")->value; };
double speed_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_speed")->value; }; double speed_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_speed")->value; };
double accel_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_acceleration")->value; } double accel_perimeter() const { return m_config.option<ConfigOptionFloat>("outer_wall_acceleration")->value; }

View File

@@ -31,7 +31,7 @@
#define SLIC3R_SNAPSHOTS_DIR "snapshots" #define SLIC3R_SNAPSHOTS_DIR "snapshots"
#define SLIC3R_SNAPSHOT_FILE "snapshot.ini" #define SLIC3R_SNAPSHOT_FILE "snapshot.ini"
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
namespace Config { namespace Config {
@@ -132,7 +132,7 @@ void Snapshot::load_ini(const std::string &path)
vc.name = section.first.substr(group_name_vendor.size()); vc.name = section.first.substr(group_name_vendor.size());
for (auto &kvp : section.second) { for (auto &kvp : section.second) {
if (kvp.first == "version" || kvp.first == "min_slic3r_version" || kvp.first == "max_slic3r_version") { if (kvp.first == "version" || kvp.first == "min_slic3r_version" || kvp.first == "max_slic3r_version") {
// Version of the vendor specific config bundle bundled with this snapshot. // Version of the vendor specific config bundle bundled with this snapshot.
auto semver = Semver::parse(kvp.second.data()); auto semver = Semver::parse(kvp.second.data());
if (! semver) if (! semver)
throw_on_parse_error("invalid " + kvp.first + " format for " + section.first); throw_on_parse_error("invalid " + kvp.first + " format for " + section.first);
@@ -155,11 +155,11 @@ void Snapshot::load_ini(const std::string &path)
} }
} }
// Sort the vendors lexicographically. // Sort the vendors lexicographically.
std::sort(this->vendor_configs.begin(), this->vendor_configs.begin(), std::sort(this->vendor_configs.begin(), this->vendor_configs.begin(),
[](const VendorConfig &cfg1, const VendorConfig &cfg2) { return cfg1.name < cfg2.name; }); [](const VendorConfig &cfg1, const VendorConfig &cfg2) { return cfg1.name < cfg2.name; });
} }
static std::string reason_string(const Snapshot::Reason reason) static std::string reason_string(const Snapshot::Reason reason)
{ {
switch (reason) { switch (reason) {
case Snapshot::SNAPSHOT_UPGRADE: case Snapshot::SNAPSHOT_UPGRADE:
@@ -372,7 +372,7 @@ static void copy_config_dir_single_level(const boost::filesystem::path &path_src
{ {
//BBS: remove snapshots function currently //BBS: remove snapshots function currently
#if 0 #if 0
if (! boost::filesystem::is_directory(path_dst) && if (! boost::filesystem::is_directory(path_dst) &&
! boost::filesystem::create_directory(path_dst)) ! boost::filesystem::create_directory(path_dst))
throw Slic3r::RuntimeError(std::string("OrcaSlicer was unable to create a directory at ") + path_dst.string()); throw Slic3r::RuntimeError(std::string("OrcaSlicer was unable to create a directory at ") + path_dst.string());
@@ -521,7 +521,7 @@ SnapshotDB::const_iterator SnapshotDB::snapshot_with_vendor_preset(const std::st
key.name = vendor_name; key.name = vendor_name;
for (auto it = m_snapshots.begin(); it != m_snapshots.end(); ++ it) { for (auto it = m_snapshots.begin(); it != m_snapshots.end(); ++ it) {
const Snapshot &snapshot = *it; const Snapshot &snapshot = *it;
auto it_vendor_config = std::lower_bound(snapshot.vendor_configs.begin(), snapshot.vendor_configs.end(), auto it_vendor_config = std::lower_bound(snapshot.vendor_configs.begin(), snapshot.vendor_configs.end(),
key, [](const Snapshot::VendorConfig &cfg1, const Snapshot::VendorConfig &cfg2) { return cfg1.name < cfg2.name; }); key, [](const Snapshot::VendorConfig &cfg1, const Snapshot::VendorConfig &cfg2) { return cfg1.name < cfg2.name; });
if (it_vendor_config != snapshot.vendor_configs.end() && it_vendor_config->name == vendor_name && if (it_vendor_config != snapshot.vendor_configs.end() && it_vendor_config->name == vendor_name &&
config_version == it_vendor_config->version.config_version) { config_version == it_vendor_config->version.config_version) {
@@ -548,7 +548,7 @@ boost::filesystem::path SnapshotDB::create_db_dir()
for (const boost::filesystem::path &path : { data_dir, snapshots_dir }) { for (const boost::filesystem::path &path : { data_dir, snapshots_dir }) {
boost::filesystem::path subdir = path; boost::filesystem::path subdir = path;
subdir.make_preferred(); subdir.make_preferred();
if (! boost::filesystem::is_directory(subdir) && if (! boost::filesystem::is_directory(subdir) &&
! boost::filesystem::create_directory(subdir)) ! boost::filesystem::create_directory(subdir))
throw Slic3r::RuntimeError(std::string("Slic3r was unable to create a directory at ") + subdir.string()); throw Slic3r::RuntimeError(std::string("Slic3r was unable to create a directory at ") + subdir.string());
} }
@@ -580,7 +580,7 @@ const Snapshot* take_config_snapshot_report_error(const AppConfig &app_config, S
try { try {
return &SnapshotDB::singleton().take_snapshot(app_config, reason, comment); return &SnapshotDB::singleton().take_snapshot(app_config, reason, comment);
} catch (std::exception &err) { } catch (std::exception &err) {
show_error(static_cast<wxWindow*>(wxGetApp().mainframe), show_error(static_cast<wxWindow*>(wxGetApp().mainframe),
_L("Taking a configuration snapshot failed.") + "\n\n" + from_u8(err.what())); _L("Taking a configuration snapshot failed.") + "\n\n" + from_u8(err.what()));
return nullptr; return nullptr;
} }

View File

@@ -48,12 +48,14 @@ int get_extruder_idx(const DynamicPrintConfig& config, const std::string &opt_ke
NozzleVolumeType nozzle_volume_type = (NozzleVolumeType) (opt_nozzle_volume_type->get_at(cur_extruder_id)); NozzleVolumeType nozzle_volume_type = (NozzleVolumeType) (opt_nozzle_volume_type->get_at(cur_extruder_id));
std::string id_name, variant_name; std::string id_name, variant_name;
unsigned int stride = 1;
if (printer_options_with_variant_1.count(opt_key) > 0) { // printer parameter if (printer_options_with_variant_1.count(opt_key) > 0) { // printer parameter
id_name = "printer_extruder_id"; id_name = "printer_extruder_id";
variant_name = "printer_extruder_variant"; variant_name = "printer_extruder_variant";
} else if (printer_options_with_variant_2.count(opt_key) > 0) { } else if (printer_options_with_variant_2.count(opt_key) > 0) {
id_name = "printer_extruder_id"; id_name = "printer_extruder_id";
variant_name = "printer_extruder_variant"; variant_name = "printer_extruder_variant";
stride = 2;
} else if (filament_options_with_variant.count(opt_key) > 0) { } else if (filament_options_with_variant.count(opt_key) > 0) {
//filament don't use id anymore //filament don't use id anymore
//id_name = "filament_extruder_id"; //id_name = "filament_extruder_id";
@@ -66,7 +68,7 @@ int get_extruder_idx(const DynamicPrintConfig& config, const std::string &opt_ke
} }
// variant index // variant index
int variant_index = config.get_index_for_extruder(cur_extruder_id + 1, id_name, extruder_type, nozzle_volume_type, variant_name); int variant_index = config.get_index_for_extruder(cur_extruder_id + 1, id_name, extruder_type, nozzle_volume_type, variant_name, stride);
if (variant_index < 0) { if (variant_index < 0) {
assert(false); assert(false);
return 0; return 0;

View File

@@ -60,7 +60,7 @@ void SidePopup::Popup(wxWindow* focus)
#ifdef __APPLE__ #ifdef __APPLE__
pos.x = pos.x - FromDIP(20); pos.x = pos.x - FromDIP(20);
#endif // __APPLE__ #endif // __APPLE__
if (pos.x + max_width > screenwidth) if (pos.x + max_width > screenwidth)
Position({pos.x - (pos.x + max_width - screenwidth),pos.y}, {0, focus->GetSize().y + 12}); Position({pos.x - (pos.x + max_width - screenwidth),pos.y}, {0, focus->GetSize().y + 12});
else else
@@ -88,7 +88,7 @@ void SidePopup::Create()
size.x = max_width; size.x = max_width;
btn->SetMinSize(size); btn->SetMinSize(size);
btn->SetSize(size); btn->SetSize(size);
sizer->Add(btn, 0, 0, 0); sizer->Add(btn, 0, 0, 0);
} }
SetSize(wxSize(max_width, height)); SetSize(wxSize(max_width, height));

View File

@@ -110,7 +110,7 @@ static bool is_same_nozzle_diameters(const DynamicPrintConfig &full_config, cons
error_msg = _L("Your nozzle diameter in preset is not consistent with memorized nozzle diameter. Did you change your nozzle lately?") + "\n " + nozzle_in_preset + error_msg = _L("Your nozzle diameter in preset is not consistent with memorized nozzle diameter. Did you change your nozzle lately?") + "\n " + nozzle_in_preset +
"\n " + nozzle_in_printer + "\n"; "\n " + nozzle_in_printer + "\n";
return false; return false;
} }
} }
} catch (...) {} } catch (...) {}
@@ -615,7 +615,7 @@ void CalibUtils::calib_pa_pattern(const CalibInfo &calib_info, Model& model)
new ConfigOptionFloat(CalibPressureAdvance::find_optimal_PA_speed( new ConfigOptionFloat(CalibPressureAdvance::find_optimal_PA_speed(
full_config, print_config.get_abs_value("line_width"), full_config, print_config.get_abs_value("line_width"),
print_config.get_abs_value("layer_height"), 0))); print_config.get_abs_value("layer_height"), 0)));
for (const auto& opt : SuggestedConfigCalibPAPattern().nozzle_ratio_pairs) { for (const auto& opt : SuggestedConfigCalibPAPattern().nozzle_ratio_pairs) {
print_config.set_key_value(opt.first, new ConfigOptionFloatOrPercent(nozzle_diameter * opt.second / 100, false)); print_config.set_key_value(opt.first, new ConfigOptionFloatOrPercent(nozzle_diameter * opt.second / 100, false));
} }