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)
{
reset();
// cache values that are going to be called often
m_e_per_mm3 = this->filament_flow_ratio();
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
{
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)
@ -47,7 +51,7 @@ double Extruder::extrude(double dE)
/* This method makes sure the extruder is retracted by the specified amount
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.
The restart_extra argument sets the extra length to be used for
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)
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;
// 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;
for (const auto& extruder : m_writer.extruders())
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
);
@ -1821,6 +1821,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
{
PROFILE_FUNC();
m_print = &print;
// modifies 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();
@ -2155,7 +2157,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
m_cooling_buffer = make_unique<CoolingBuffer>(*this);
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
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:
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
// 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)
{
int extruder_id = get_extruder_index(filament_id);
int extruder_id = get_extruder_id(filament_id);
if (!m_writer.need_toolchange(filament_id))
return "";

View file

@ -93,7 +93,8 @@ public:
m_plate_origin(plate_origin),
m_single_extruder_multi_material(print_config.single_extruder_multi_material),
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);
@ -136,6 +137,7 @@ private:
bool m_single_extruder_multi_material;
bool m_enable_timelapse_print;
bool m_is_first_print;
const PrintConfig * m_print_config;
};
class ColorPrintColors
@ -352,6 +354,7 @@ private:
//BBS
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; }
bool last_pos_defined() const { return m_last_pos_defined; }
@ -584,6 +587,8 @@ private:
bool m_silent_time_estimator_enabled;
Print *m_print{nullptr};
// 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) {}
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->time < this->time_max;
}
@ -105,7 +105,7 @@ struct CoolingLine
};
// Calculate the required per extruder time stretches.
struct PerExtruderAdjustments
struct PerExtruderAdjustments
{
// Calculate the total elapsed time per this extruder, adjusted for the slowdown.
float elapsed_time_total() const {
@ -114,7 +114,7 @@ struct PerExtruderAdjustments
time_total += line.time;
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.
float maximum_time_after_slowdown(bool slowdown_external_perimeters) const {
float time_total = 0.f;
@ -185,7 +185,7 @@ struct PerExtruderAdjustments
bool adj2 = l2.adjustable();
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);
time_non_adjustable = 0.f;
@ -242,7 +242,7 @@ struct PerExtruderAdjustments
// The following two values are set by sort_lines_by_decreasing_feedrate():
// Number of adjustable lines, at the start of lines.
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;
// Current total time for this extruder.
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.
// Used by non-proportional slow down.
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 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) {
const CoolingLine &line = (*it)->lines[i];
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.
// 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.
@ -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.
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)
++ line_end;
@ -574,7 +574,7 @@ static inline void extruder_range_slow_down_non_proportional(
}
assert(feedrate > 0.f);
// 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; });
// Slow down, fast moves first.
for (;;) {
@ -696,7 +696,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
// Source G-code for the current layer.
const std::string &gcode,
// 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.
float layer_time,
// 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);
for (auto layerm : first_layer->regions()) {
int extruder_id = layerm->region().config().option("wall_filament")->getInt();
for (auto expoly : layerm->raw_slices) {
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);
@ -486,7 +486,7 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
for (auto layer : object.layers()) {
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)
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);
const_cast<PrintObject&>(object).object_first_layer_wall_extruders = firstLayerExtruders;
for (auto& layer : m_layer_tools) {
// Sort and remove duplicates
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();
if (nozzle_nums > 1) {
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);
m_print->update_filament_maps_to_config(filament_maps);
return;
}
@ -1177,7 +1181,7 @@ void ToolOrdering::reorder_extruders_for_minimum_flush_volume_multi_extruder(con
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 {
uint32_t hash_key = 0;
// 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;
};
std::optional<unsigned int> current_extruder_id;
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());
for (unsigned int extruder_id : extruder_ids)
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
(even if prints only uses that one) since we need to output Tx commands
first extruder has index 0 */
@ -61,7 +61,7 @@ void GCodeWriter::set_extruders(std::vector<unsigned int> extruder_ids)
std::string GCodeWriter::preamble()
{
std::ostringstream gcode;
if (FLAVOR_IS_NOT(gcfMakerWare)) {
gcode << "G90\n";
gcode << "G21\n";
@ -82,7 +82,7 @@ std::string GCodeWriter::preamble()
}
gcode << this->reset_e(true);
}
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 ;
if (acceleration == 0 || acceleration == last_value)
return std::string();
last_value = acceleration;
std::ostringstream gcode;
if (FLAVOR_IS(gcfRepetier))
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";
gcode << "\n";
return gcode.str();
}
@ -406,7 +406,7 @@ std::string GCodeWriter::reset_e(bool force)
|| FLAVOR_IS(gcfMakerWare)
|| FLAVOR_IS(gcfSailfish))
return "";
if (m_extruder != nullptr) {
if (is_zero(m_extruder->E()) && ! force)
return "";
@ -433,10 +433,10 @@ std::string GCodeWriter::update_progress(unsigned int num, unsigned int tot, boo
if (config.disable_m73) {
return "";
}
unsigned int percent = (unsigned int)floor(100.0 * num / tot + 0.5);
if (!allow_100) percent = std::min(percent, (unsigned int)99);
std::ostringstream gcode;
gcode << "M73 P" << percent;
//BBS
@ -499,7 +499,7 @@ std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &com
this->set_current_position_clear(true);
//BBS: take plate offset into consider
Vec2d point_on_plate = { point(0) - m_x_offset, point(1) - m_y_offset };
GCodeG1Formatter w;
w.emit_xy(point_on_plate);
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
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. */
// BBS
Vec3d dest_point = point;
@ -557,7 +557,7 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
}
//BBS: 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()) {
//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. */
m_lifted = 0;
}
//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) };
std::string out_string;
@ -649,7 +649,7 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment)
m_lifted = 0.;
return "";
}
/* In all the other cases, we perform an actual Z move and cancel
the lift. */
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")
: this->config.travel_speed.value;
}
GCodeG1Formatter w;
w.emit_z(z);
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")
: this->config.travel_speed.value;
}
std::string output = "G17\n";
GCodeG2G3Formatter w(true);
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);
if(std::abs(dE) <= std::numeric_limits<double>::epsilon())
force_no_extrusion = true;
if (!force_no_extrusion)
m_extruder->extrude(dE);
@ -761,7 +761,7 @@ std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std
m_lifted = 0;
if (!force_no_extrusion)
m_extruder->extrude(dE);
//BBS: take plate offset into consider
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();
}
}
if (FLAVOR_IS(gcfMakerWare))
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 gcode;
if (FLAVOR_IS(gcfMakerWare))
gcode = "M101 ; extruder on\n";
if (double dE = m_extruder->unretract(); !is_zero(dE)) {
if (this->config.use_firmware_retraction) {
gcode += FLAVOR_IS(gcfMachinekit) ? "G23 ; unretract\n" : "G11 ; unretract\n";
@ -849,7 +849,7 @@ std::string GCodeWriter::unretract()
gcode += w.string();
}
}
return gcode;
}
@ -919,7 +919,7 @@ std::string GCodeWriter::set_fan(const GCodeFlavor gcode_flavor, unsigned int sp
default:
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 << "\n";
}

View file

@ -47,19 +47,19 @@ void Layer::make_slices()
polygons_append(slices_p, to_polygons(layerm->slices.surfaces));
slices = union_safety_offset_ex(slices_p);
}
this->lslices.clear();
this->lslices.reserve(slices.size());
// prepare ordering points
Points ordering_points;
ordering_points.reserve(slices.size());
for (const ExPolygon &ex : slices)
ordering_points.push_back(ex.contour.first_point());
// sort slices
std::vector<Points::size_type> order = chain_points(ordering_points);
// populate slices vector
for (size_t i : order)
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()
{
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id();
// keep track of regions whose perimeters we have already generated
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()) {
(*layerm)->perimeters.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;
done[region_id] = true;
const PrintRegion &this_region = (*layerm)->region();
// find compatible regions
LayerRegionPtrs layerms;
layerms.push_back(*layerm);
@ -211,7 +211,7 @@ void Layer::make_perimeters()
done[it - m_regions.begin()] = true;
}
}
if (layerms.size() == 1) { // optimization
(*layerm)->fill_surfaces.surfaces.clear();
(*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)
new_slices.append(offset_ex(surfaces_with_extra_perimeters.second, ClipperSafetyOffset), surfaces_with_extra_perimeters.second.front());
}
// make perimeters
SurfaceCollection fill_surfaces;
//BBS
@ -241,7 +241,7 @@ void Layer::make_perimeters()
layerm_config->make_perimeters(new_slices, layerms, &fill_surfaces, &fill_no_overlap);
// 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) {
// Separate the fill 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)
svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency);
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.
@ -422,6 +422,15 @@ coordf_t Layer::get_sparse_infill_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 bbox;

View file

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

View file

@ -43,7 +43,7 @@ public:
unsigned short depth;
// Children contour, may be both CCW and CW oriented (outer contours or holes).
std::vector<PerimeterGeneratorLoop> children;
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) {}
// 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) {
bool is_external = loop.is_external();
bool is_small_width = loop.is_smaller_width_perimeter;
ExtrusionRole role;
ExtrusionLoopRole loop_role;
role = is_external ? erExternalPerimeter : erPerimeter;
@ -225,13 +225,13 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
coll.append(ExtrusionLoop(std::move(paths), loop_role));
}
// Append thin walls to the nearest-neighbor search (only for first iteration)
if (! thin_walls.empty()) {
variable_width(thin_walls, erExternalPerimeter, perimeter_generator.ext_perimeter_flow, coll.entities);
thin_walls.clear();
}
// Traverse children and build the final collection.
Point zero_point(0, 0);
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()));
else
ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
// overhang perimeters
m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
// solid infill
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);
m_lower_slices_polygons = offset(*this->lower_slices, float(scale_(+nozzle_diameter / 2)));
}
// Calculate the minimum required spacing between two adjacent traces.
// This should be equal to the nominal flow spacing but we experiment
// 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
// 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
// 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.
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));
@ -1275,16 +1275,16 @@ void PerimeterGenerator::process_classic()
coord_t distance = (i == 1) ? ext_perimeter_spacing2 : perimeter_spacing;
//BBS
//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
// 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.
// Also the offset2(perimeter, -x, x) may sometimes lead to a perimeter, which is larger than
// the original.
//offset2_ex(last,
// - float(distance + 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
//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)) {
// 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;
}
}
@ -1545,7 +1545,7 @@ void PerimeterGenerator::process_classic()
// fill gaps
if (! gaps.empty()) {
// collapse
// collapse
double min = 0.2 * perimeter_width * (1 - INSET_OVERLAP_TOLERANCE);
double max = 2. * perimeter_spacing;
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)
// and then we offset back and forth by half the infill spacing to only consider the
// non-collapsing regions
coord_t inset =
coord_t inset =
(loop_number < 0) ? 0 :
(loop_number == 0) ?
// one loop

View file

@ -80,7 +80,7 @@ void PlaceholderParser::update_timestamp(DynamicConfig &config)
time_t rawtime;
time(&rawtime);
struct tm* timeinfo = localtime(&rawtime);
{
std::ostringstream ss;
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 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(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); }
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;
}
expr &operator=(expr &&rhs)
{
expr &operator=(expr &&rhs)
{
if (this != &rhs) {
this->reset();
m_type = rhs.type();
@ -245,7 +245,7 @@ namespace client
return *this;
}
void reset()
void reset()
{
if (this->type() == TYPE_STRING)
delete m_data.s;
@ -298,8 +298,8 @@ namespace client
else
this->set_s_take_ownership(new std::string(s));
}
std::string to_string() const
std::string to_string() const
{
std::string out;
switch (this->type()) {
@ -308,7 +308,7 @@ namespace client
break;
case TYPE_BOOL: out = this->b() ? "true" : "false"; break;
case TYPE_INT: out = std::to_string(this->i()); break;
case TYPE_DOUBLE:
case TYPE_DOUBLE:
#if 0
// The default converter produces trailing zeros after the decimal point.
out = std::to_string(data.d);
@ -333,7 +333,7 @@ namespace client
IteratorRange it_range;
expr unary_minus(const Iterator start_pos) const
{
{
switch (this->type()) {
case TYPE_EMPTY:
// Inside an if / else block to be skipped.
@ -351,7 +351,7 @@ namespace client
}
expr unary_integer(const Iterator start_pos) const
{
{
switch (this->type()) {
case TYPE_EMPTY:
// Inside an if / else block to be skipped.
@ -369,7 +369,7 @@ namespace client
}
expr round(const Iterator start_pos) const
{
{
switch (this->type()) {
case TYPE_EMPTY:
// Inside an if / else block to be skipped.
@ -387,7 +387,7 @@ namespace client
}
expr unary_not(const Iterator start_pos) const
{
{
switch (this->type()) {
case TYPE_EMPTY:
// Inside an if / else block to be skipped.
@ -403,7 +403,7 @@ namespace client
}
expr &operator+=(const expr &rhs)
{
{
if (this->type() == TYPE_EMPTY) {
// Inside an if / else block to be skipped.
} else if (this->type() == TYPE_STRING) {
@ -426,7 +426,7 @@ namespace client
}
expr &operator-=(const expr &rhs)
{
{
if (this->type() == TYPE_EMPTY) {
// Inside an if / else block to be skipped.
this->reset();
@ -444,7 +444,7 @@ namespace client
}
expr &operator*=(const expr &rhs)
{
{
if (this->type() == TYPE_EMPTY) {
// Inside an if / else block to be skipped.
this->reset();
@ -535,16 +535,16 @@ namespace client
// Both types are numeric.
switch (op) {
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());
break;
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());
break;
case '>':
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());
break;
}
@ -556,7 +556,7 @@ namespace client
value = lhs.b() == rhs.b();
} else if (lhs.type() == TYPE_STRING || rhs.type() == TYPE_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());
} else {
boost::throw_exception(qi::expectation_failure<Iterator>(
@ -576,7 +576,7 @@ namespace client
static void throw_if_not_numeric(const expr &param)
{
const char *err_msg = "Not a numeric type.";
param.throw_if_not_numeric(err_msg);
param.throw_if_not_numeric(err_msg);
}
enum Function2ParamsType {
@ -585,7 +585,7 @@ namespace client
};
// Store the result into param1.
static void function_2params(expr &param1, expr &param2, Function2ParamsType fun)
{
{
if (param1.type() == TYPE_EMPTY)
// Inside an if / else block to be skipped
return;
@ -615,7 +615,7 @@ namespace client
// Store the result into param1.
static void random(expr &param1, expr &param2, std::mt19937 &rng)
{
{
if (param1.type() == TYPE_EMPTY)
// Inside an if / else block to be skipped
return;
@ -631,7 +631,7 @@ namespace client
// param3 is optional
template<bool leading_zeros>
static void digits(expr &param1, expr &param2, expr &param3)
{
{
if (param1.type() == TYPE_EMPTY)
// Inside an if / else block to be skipped
return;
@ -738,13 +738,13 @@ namespace client
static void logical_or (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>(
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())
this->throw_exception(message);
@ -794,7 +794,7 @@ namespace client
mutable DynamicConfig *config_outputs = nullptr;
// Local variables, read / write
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.
PlaceholderParser::ContextData *context_data = nullptr;
// 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.
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; }
// Entering a conditional block.
@ -908,7 +915,7 @@ namespace client
}
static void legacy_variable_expansion2(
const MyContext *ctx,
const MyContext *ctx,
IteratorRange &opt_key,
IteratorRange &opt_vector_index,
std::string &output)
@ -1546,7 +1553,7 @@ namespace client
static void evaluate_index(expr &expr_index, int &output)
{
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.");
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.
// If an invalid UTF-8 sequence is encountered, a qi::expectation_failure is thrown.
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>
struct attribute
{
{
typedef wchar_t type;
};
@ -1750,7 +1757,7 @@ namespace client
// Also it throws if it encounters valid or invalid UTF-8 sequence.
template <typename Iterator, typename Context , typename Skipper, typename Attribute>
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.
// skip_over(first, last, skipper);
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.
template <typename Context>
spirit::info what(Context&) const
{
{
return spirit::info("unicode_char");
}
};
@ -2039,7 +2046,7 @@ namespace client
legacy_variable_expansion =
(identifier >> &lit(']'))
[ 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) ]
;
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)]);
conditional_expression.name("conditional_expression");
logical_or_expression =
logical_or_expression =
logical_and_expression(_r1) [_val = _1]
>> *( ((kw["or"] | "||") > logical_and_expression(_r1) ) [px::bind(&expr::logical_or, _val, _1)] );
logical_or_expression.name("logical_or_expression");
logical_and_expression =
logical_and_expression =
equality_expression(_r1) [_val = _1]
>> *( ((kw["and"] | "&&") > equality_expression(_r1) ) [px::bind(&expr::logical_and, _val, _1)] );
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.name("bool_expr_eval");
relational_expression =
relational_expression =
additive_expression(_r1) [_val = _1]
>> *( ("<=" > additive_expression(_r1) ) [px::bind(&expr::leq, _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) > iter_pos) [ px::bind(&FactorActions::expr_, _1, _2, _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) ]
| (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) ]
| (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) ]
| (kw["digits"] > '(' > conditional_expression(_r1) [_val = _1] > ',' > conditional_expression(_r1) > optional_parameter(_r1))
[ 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;
}
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.
bool Print::has_wipe_tower() const
{

View file

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

View file

@ -53,9 +53,11 @@ namespace Slic3r {
#define L(s) (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;
}

View file

@ -462,7 +462,6 @@ static std::string get_bed_temp_1st_layer_key(const BedType type)
return "";
}
size_t get_extruder_index(unsigned int filament_id);
#define CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NAME) \
template<> const t_config_enum_names& ConfigOptionEnum<NAME>::get_enum_names(); \
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
// 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)
{
const double general_suggested_min_speed = 100.0;
double filament_max_volumetric_speed = config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(0);
const float nozzle_diameter = config.option<ConfigOptionFloats>("nozzle_diameter")->get_at(0);
double filament_max_volumetric_speed = config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(filament_idx);
// 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);
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),

View file

@ -303,6 +303,7 @@ public:
Vec3d get_start_offset();
protected:
// todo multi_extruders:
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 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_SNAPSHOT_FILE "snapshot.ini"
namespace Slic3r {
namespace Slic3r {
namespace GUI {
namespace Config {
@ -132,7 +132,7 @@ void Snapshot::load_ini(const std::string &path)
vc.name = section.first.substr(group_name_vendor.size());
for (auto &kvp : section.second) {
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());
if (! semver)
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.
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; });
}
static std::string reason_string(const Snapshot::Reason reason)
static std::string reason_string(const Snapshot::Reason reason)
{
switch (reason) {
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
#if 0
if (! boost::filesystem::is_directory(path_dst) &&
if (! boost::filesystem::is_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());
@ -521,7 +521,7 @@ SnapshotDB::const_iterator SnapshotDB::snapshot_with_vendor_preset(const std::st
key.name = vendor_name;
for (auto it = m_snapshots.begin(); it != m_snapshots.end(); ++ 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; });
if (it_vendor_config != snapshot.vendor_configs.end() && it_vendor_config->name == vendor_name &&
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 }) {
boost::filesystem::path subdir = path;
subdir.make_preferred();
if (! boost::filesystem::is_directory(subdir) &&
if (! boost::filesystem::is_directory(subdir) &&
! boost::filesystem::create_directory(subdir))
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 {
return &SnapshotDB::singleton().take_snapshot(app_config, reason, comment);
} 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()));
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));
std::string id_name, variant_name;
unsigned int stride = 1;
if (printer_options_with_variant_1.count(opt_key) > 0) { // printer parameter
id_name = "printer_extruder_id";
variant_name = "printer_extruder_variant";
} else if (printer_options_with_variant_2.count(opt_key) > 0) {
id_name = "printer_extruder_id";
variant_name = "printer_extruder_variant";
stride = 2;
} else if (filament_options_with_variant.count(opt_key) > 0) {
//filament don't use id anymore
//id_name = "filament_extruder_id";
@ -66,7 +68,7 @@ int get_extruder_idx(const DynamicPrintConfig& config, const std::string &opt_ke
}
// 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) {
assert(false);
return 0;

View file

@ -60,7 +60,7 @@ void SidePopup::Popup(wxWindow* focus)
#ifdef __APPLE__
pos.x = pos.x - FromDIP(20);
#endif // __APPLE__
if (pos.x + max_width > screenwidth)
Position({pos.x - (pos.x + max_width - screenwidth),pos.y}, {0, focus->GetSize().y + 12});
else
@ -88,7 +88,7 @@ void SidePopup::Create()
size.x = max_width;
btn->SetMinSize(size);
btn->SetSize(size);
sizer->Add(btn, 0, 0, 0);
sizer->Add(btn, 0, 0, 0);
}
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 +
"\n " + nozzle_in_printer + "\n";
return false;
}
}
}
} catch (...) {}
@ -615,7 +615,7 @@ void CalibUtils::calib_pa_pattern(const CalibInfo &calib_info, Model& model)
new ConfigOptionFloat(CalibPressureAdvance::find_optimal_PA_speed(
full_config, print_config.get_abs_value("line_width"),
print_config.get_abs_value("layer_height"), 0)));
for (const auto& opt : SuggestedConfigCalibPAPattern().nozzle_ratio_pairs) {
print_config.set_key_value(opt.first, new ConfigOptionFloatOrPercent(nozzle_diameter * opt.second / 100, false));
}