mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2026-01-03 05:20:29 -07:00
FIX: backend get the extruder id based on filament_map
Change-Id: Ib7679c0fc67336e462467dab9f5b4d4684d6eb19 (cherry picked from commit dcd9fd501354da33baea2adc0f645fabe8880cf1)
This commit is contained in:
parent
f5d2a1bc0c
commit
8db3e3cd54
20 changed files with 193 additions and 131 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 "";
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>&);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ¶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<bool leading_zeros>
|
||||
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<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) ]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue