From 8db3e3cd546c348a30ae5684a969bbd006f35daf Mon Sep 17 00:00:00 2001 From: "zhimin.zeng" Date: Tue, 2 Jul 2024 19:26:52 +0800 Subject: [PATCH] FIX: backend get the extruder id based on filament_map Change-Id: Ib7679c0fc67336e462467dab9f5b4d4684d6eb19 (cherry picked from commit dcd9fd501354da33baea2adc0f645fabe8880cf1) --- src/libslic3r/Extruder.cpp | 10 ++- src/libslic3r/GCode.cpp | 22 ++++-- src/libslic3r/GCode.hpp | 7 +- src/libslic3r/GCode/CoolingBuffer.cpp | 20 +++--- src/libslic3r/GCode/ToolOrdering.cpp | 14 ++-- src/libslic3r/GCodeWriter.cpp | 46 ++++++------ src/libslic3r/Layer.cpp | 33 +++++---- src/libslic3r/Layer.hpp | 2 + src/libslic3r/PerimeterGenerator.cpp | 28 ++++---- src/libslic3r/PlaceholderParser.cpp | 89 +++++++++++++----------- src/libslic3r/Print.cpp | 9 +++ src/libslic3r/Print.hpp | 1 + src/libslic3r/PrintConfig.cpp | 6 +- src/libslic3r/PrintConfig.hpp | 3 +- src/libslic3r/calib.cpp | 5 +- src/libslic3r/calib.hpp | 1 + src/slic3r/Config/Snapshot.cpp | 16 ++--- src/slic3r/GUI/OptionsGroup.cpp | 4 +- src/slic3r/GUI/Widgets/SideMenuPopup.cpp | 4 +- src/slic3r/Utils/CalibUtils.cpp | 4 +- 20 files changed, 193 insertions(+), 131 deletions(-) diff --git a/src/libslic3r/Extruder.cpp b/src/libslic3r/Extruder.cpp index 664b5e9ae1..3f10f0b1d0 100644 --- a/src/libslic3r/Extruder.cpp +++ b/src/libslic3r/Extruder.cpp @@ -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 diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index c36fdb5321..ddcd56a0a1 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -435,7 +435,7 @@ static std::vector 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(*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(*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 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 ""; diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index c7f46a01f6..8490e793a4 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -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; diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp index 9541d68034..6bf6034101 100644 --- a/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/src/libslic3r/GCode/CoolingBuffer.cpp @@ -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::const_iterator it_begin, std::vector::const_iterator it_end, + std::vector::const_iterator it_begin, std::vector::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 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. diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index a177cf3a68..55051e6ad6 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -354,7 +354,7 @@ std::vector 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(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 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 &extruders, std::optional 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 current_extruder_id; std::vector> nozzle_to_cur_filaments; diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index fbf9bb5cf6..c0b8891f75 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -51,7 +51,7 @@ void GCodeWriter::set_extruders(std::vector 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 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::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(255.5 * speed / 100.0); break; } - if (GCodeWriter::full_gcode_comment) + if (GCodeWriter::full_gcode_comment) gcode << " ; enable fan"; gcode << "\n"; } diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index c5fe201d10..0d684accca 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -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 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 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 &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 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; diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 1c325034cd..4e9fdad059 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -241,6 +241,8 @@ public: return idx; } + size_t get_extruder_id(unsigned int filament_id) const; + protected: friend class PrintObject; friend std::vector new_layers(PrintObject*, const std::vector&); diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index c67f0cf3f3..7aabd0c658 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -43,7 +43,7 @@ public: unsigned short depth; // Children contour, may be both CCW and CW oriented (outer contours or holes). std::vector 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> chain = chain_extrusion_entities(coll.entities, &zero_point); @@ -1133,10 +1133,10 @@ void PerimeterGenerator::process_classic() ext_perimeter_spacing2 = scaled(0.5f * (this->ext_perimeter_flow.width() + this->perimeter_flow.width())); else ext_perimeter_spacing2 = scaled(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 diff --git a/src/libslic3r/PlaceholderParser.cpp b/src/libslic3r/PlaceholderParser.cpp index 5cc18345f3..a07b35d40b 100644 --- a/src/libslic3r/PlaceholderParser.cpp +++ b/src/libslic3r/PlaceholderParser.cpp @@ -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( @@ -576,7 +576,7 @@ namespace client static void throw_if_not_numeric(const expr ¶m) { 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 ¶m1, expr ¶m2, 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 ¶m1, expr ¶m2, 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 static void digits(expr ¶m1, expr ¶m2, expr ¶m3) - { + { 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( 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 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("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 - { - // Define the attribute type exposed by this parser component + { + // Define the attribute type exposed by this parser component template 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 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 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, _val, _2, _3) ] diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index b2b0fcb08d..12f2a30243 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -2603,6 +2603,15 @@ std::vector Print::get_filament_maps() const return m_config.filament_map.values; } +size_t Print::get_extruder_id(unsigned int filament_id) const +{ + std::vector 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 { diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 92e37322dc..537b1a722f 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -936,6 +936,7 @@ public: void update_filament_maps_to_config(std::vector f_maps); std::vector get_filament_maps() const; + size_t get_extruder_id(unsigned int filament_id) const; bool enable_timelapse_print() const; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 2819c4ad57..739b682154 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -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; } diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 31a411ef1d..f0a676cea7 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -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::get_enum_names(); \ template<> const t_config_enum_values& ConfigOptionEnum::get_enum_values(); @@ -1969,6 +1968,8 @@ static void set_flush_volumes_matrix(std::vector &out_matrix, const std::vect } } +size_t get_extruder_index(const GCodeConfig& config, unsigned int filament_id); + } // namespace Slic3r // Serialization through the Cereal library diff --git a/src/libslic3r/calib.cpp b/src/libslic3r/calib.cpp index e7cc7a8932..f38df539e4 100644 --- a/src/libslic3r/calib.cpp +++ b/src/libslic3r/calib.cpp @@ -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("filament_max_volumetric_speed")->get_at(0); - const float nozzle_diameter = config.option("nozzle_diameter")->get_at(0); + double filament_max_volumetric_speed = config.option("filament_max_volumetric_speed")->get_at(filament_idx); + // todo multi_extruders: + const float nozzle_diameter = config.option("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("outer_wall_speed")->value), diff --git a/src/libslic3r/calib.hpp b/src/libslic3r/calib.hpp index d7db10fd81..f07fbd6478 100644 --- a/src/libslic3r/calib.hpp +++ b/src/libslic3r/calib.hpp @@ -303,6 +303,7 @@ public: Vec3d get_start_offset(); protected: + // todo multi_extruders: double speed_first_layer() const { return m_config.option("initial_layer_speed")->value; }; double speed_perimeter() const { return m_config.option("outer_wall_speed")->value; }; double accel_perimeter() const { return m_config.option("outer_wall_acceleration")->value; } diff --git a/src/slic3r/Config/Snapshot.cpp b/src/slic3r/Config/Snapshot.cpp index d995e3a6cc..4b071994fc 100644 --- a/src/slic3r/Config/Snapshot.cpp +++ b/src/slic3r/Config/Snapshot.cpp @@ -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(wxGetApp().mainframe), + show_error(static_cast(wxGetApp().mainframe), _L("Taking a configuration snapshot failed.") + "\n\n" + from_u8(err.what())); return nullptr; } diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index c5523d6074..4ef1fd87e6 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -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; diff --git a/src/slic3r/GUI/Widgets/SideMenuPopup.cpp b/src/slic3r/GUI/Widgets/SideMenuPopup.cpp index cde4fba39d..392d62e547 100644 --- a/src/slic3r/GUI/Widgets/SideMenuPopup.cpp +++ b/src/slic3r/GUI/Widgets/SideMenuPopup.cpp @@ -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)); diff --git a/src/slic3r/Utils/CalibUtils.cpp b/src/slic3r/Utils/CalibUtils.cpp index aa548df4f8..603adab05c 100644 --- a/src/slic3r/Utils/CalibUtils.cpp +++ b/src/slic3r/Utils/CalibUtils.cpp @@ -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)); }