mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-16 05:35:56 +08:00
Add lift_min: minimum height to travel between objects
Also change other behaviors to be compliant: * At the first move don't split the travel * At the first move, if start_gcode_manual and no layer_gcode, don't lift the nozzle so the printer won't "z-dance", whatever where the nozzle is. Note:it's a hack, please redo it properly when reworking gcode-writer. * retract_lift_first_layer is gone back to the old simple behavior (revert b16ecbfc) * removed auto extra lift for first layer, now that lift_min exists. * with complete_object, don't unlift at object/first layer change, to avoid Z-dance * lift_min will be used between brims, skirts, objects but not between object-skirt, object-brim and their object supermerill/SuperSlicer#1783 supermerill/SuperSlicer#1775 supermerill/SuperSlicer#1575 supermerill/SuperSlicer#599 supermerill/SuperSlicer#429 supermerill/SuperSlicer#395 supermerill/SuperSlicer#241
This commit is contained in:
parent
b8e173aa30
commit
f2a9945435
@ -5,6 +5,7 @@ group:Size and coordinates
|
||||
setting:max_print_height
|
||||
setting:z_offset
|
||||
setting:z_step
|
||||
setting:lift_min
|
||||
group:extruders_count_event:milling_count_event:Capabilities
|
||||
extruders_count
|
||||
setting:single_extruder_multi_material
|
||||
|
@ -219,16 +219,23 @@ std::string Wipe::wipe(GCode& gcodegen, bool toolchange)
|
||||
}
|
||||
|
||||
//if first layer, ask for a bigger lift for travel to object, to be on the safe side
|
||||
static inline void set_extra_lift(const Layer& layer, const Print& print, GCodeWriter & writer, int extruder_id) {
|
||||
static inline void set_extra_lift(const float previous_print_z, const int layer_id, const PrintConfig& print_config, GCodeWriter & writer, int extruder_id) {
|
||||
//if first layer, ask for a bigger lift for travel to object, to be on the safe side
|
||||
if (layer.id() == 0 &&
|
||||
(print.config().retract_lift.get_at(extruder_id) != 0 || print.config().retract_lift_first_layer.get_at(extruder_id))) {
|
||||
//get biggest first layer height and set extra lift for first travel, to be safe.
|
||||
double extra_lift_value = 0;
|
||||
for (const PrintObject* obj : print.objects())
|
||||
extra_lift_value = std::max(extra_lift_value, print.get_object_first_layer_height(*obj));
|
||||
writer.set_extra_lift(extra_lift_value * 2);
|
||||
double extra_lift_value = 0;
|
||||
if (print_config.lift_min.value > 0) {
|
||||
double retract_lift = 0;
|
||||
//get the current lift (imo, should be given by the writer... i'm duplicating stuff here)
|
||||
if(//(previous_print_z == 0 && print_config.retract_lift_above.get_at(writer.tool()->id()) == 0) ||
|
||||
print_config.retract_lift_above.get_at(writer.tool()->id()) <= previous_print_z + EPSILON
|
||||
|| (layer_id == 0 && print_config.retract_lift_first_layer.get_at(writer.tool()->id())))
|
||||
retract_lift = writer.tool()->retract_lift();
|
||||
// see if it's positive
|
||||
if (previous_print_z + extra_lift_value + retract_lift < print_config.lift_min.value) {
|
||||
extra_lift_value = print_config.lift_min.value - previous_print_z - retract_lift;
|
||||
}
|
||||
}
|
||||
if(extra_lift_value > 0)
|
||||
writer.set_extra_lift(extra_lift_value);
|
||||
}
|
||||
|
||||
static inline Point wipe_tower_point_to_object_point(GCode &gcodegen, const Vec2f &wipe_tower_pt)
|
||||
@ -1398,6 +1405,8 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
|
||||
// Write the custom start G-code
|
||||
_writeln(file, start_gcode);
|
||||
m_last_pos_defined = false;
|
||||
|
||||
//flush FanMover buffer to avoid modifying the start gcode if it's manual.
|
||||
if (this->config().start_gcode_manual && this->m_fan_mover.get() != nullptr) {
|
||||
std::string to_write = this->m_fan_mover.get()->process_gcode("", true);
|
||||
@ -1514,8 +1523,10 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
// This happens before Z goes down to layer 0 again, so that no collision happens hopefully.
|
||||
m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer
|
||||
m_avoid_crossing_perimeters.use_external_mp_once();
|
||||
set_extra_lift(m_last_layer_z, 0, print.config(), m_writer, initial_extruder_id);
|
||||
_write(file, this->retract());
|
||||
std::string gcode;
|
||||
//go to origin of the next object (it's 0,0 because we shifted the origin to it)
|
||||
Polyline polyline = this->travel_to(gcode, Point(0, 0), erNone);
|
||||
this->write_travel_to(gcode, polyline, "move to origin position for next object");
|
||||
_write(file, gcode);
|
||||
@ -1531,6 +1542,8 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false);
|
||||
this->_print_first_layer_extruder_temperatures(file, print, between_objects_gcode, initial_extruder_id, false);
|
||||
_writeln(file, between_objects_gcode);
|
||||
} else {
|
||||
set_extra_lift(0, 0, print.config(), m_writer, initial_extruder_id);
|
||||
}
|
||||
//reinit the seam placer on the new object
|
||||
m_seam_placer.init(print);
|
||||
@ -1555,6 +1568,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||
m_second_layer_things_done = false;
|
||||
prev_object = &object;
|
||||
}
|
||||
set_extra_lift(m_last_layer_z, prev_object->layers().back()->id(), print.config(), m_writer, initial_extruder_id /* osef, it's only for the lift_min */);
|
||||
} else {
|
||||
// Sort layers by Z.
|
||||
// All extrusion moves with the same top layer height are extruded uninterrupted.
|
||||
@ -2263,7 +2277,22 @@ void GCode::process_layer(
|
||||
print.config().before_layer_gcode.value, m_writer.tool()->id(), &config)
|
||||
+ "\n";
|
||||
}
|
||||
gcode += this->change_layer(print_z); // this will increase m_layer_index
|
||||
// print z move to next layer UNLESS
|
||||
// if it's going to the first layer, then we may want to dealy the move in these condition:
|
||||
// there is no "after layer change gcode" and it's the first move from the unknown
|
||||
if (print.config().layer_gcode.value.empty() && !m_last_pos_defined && m_config.start_gcode_manual && (
|
||||
// there is a lift (on the first llyer, so the first move will bring us to the required height
|
||||
(m_writer.tool()->retract_lift() > 0 && (m_config.retract_lift_above.get_at(m_writer.tool()->id()) == 0 || BOOL_EXTRUDER_CONFIG(retract_lift_first_layer)))
|
||||
|| // or lift_min is higher than the first layer height.
|
||||
m_config.lift_min.value > layer.print_z
|
||||
))
|
||||
m_delayed_layer_change = this->change_layer(print_z); //HACK for superslicer#1775
|
||||
else {
|
||||
//extra lift on layer change if multiple objects
|
||||
if(single_object_instance_idx == size_t(-1) && (support_layer != nullptr || layers.size() > 1))
|
||||
set_extra_lift(m_last_layer_z, layer.id(), print.config(), m_writer, first_extruder_id);
|
||||
gcode += this->change_layer(print_z); // this will increase m_layer_index
|
||||
}
|
||||
m_layer = &layer;
|
||||
if (! print.config().layer_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
@ -2478,9 +2507,12 @@ void GCode::process_layer(
|
||||
m_last_processor_extrusion_role = erWipeTower;
|
||||
|
||||
//if first layer, ask for a bigger lift for travel to object, to be on the safe side
|
||||
set_extra_lift(layer, print, m_writer, extruder_id);
|
||||
if(single_object_instance_idx == size_t(-1) && m_layer_index == 0)
|
||||
set_extra_lift(m_last_layer_z, layer.id(), print.config(), m_writer, extruder_id);
|
||||
|
||||
if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) {
|
||||
// before going to and from a global skirt, please ensure you are a a safe height
|
||||
set_extra_lift(m_last_layer_z, layer.id(), print.config(), m_writer, extruder_id);
|
||||
const std::pair<size_t, size_t> loops = loops_it->second;
|
||||
this->set_origin(0., 0.);
|
||||
m_avoid_crossing_perimeters.use_external_mp();
|
||||
@ -2504,27 +2536,30 @@ void GCode::process_layer(
|
||||
// Allow a straight travel move to the first object point if this is the first layer (but don't in next layers).
|
||||
if (first_layer && loops.first == 0)
|
||||
m_avoid_crossing_perimeters.disable_once();
|
||||
// before going to and from a global skirt, please ensure you are a a safe height
|
||||
set_extra_lift(m_last_layer_z, layer.id(), print.config(), m_writer, extruder_id);
|
||||
}
|
||||
|
||||
// Extrude brim with the extruder of the 1st region.
|
||||
if (! m_brim_done) {
|
||||
//if first layer, ask for a bigger lift for travel to object, to be on the safe side
|
||||
set_extra_lift(layer, print, m_writer, extruder_id);
|
||||
|
||||
this->set_origin(0., 0.);
|
||||
m_avoid_crossing_perimeters.use_external_mp();
|
||||
gcode += this->extrude_entity(print.brim(), "Brim", m_config.support_material_speed.value);
|
||||
for (const ExtrusionEntity* brim_entity : print.brim().entities) {
|
||||
//if first layer, ask for a bigger lift for travel to each brim, to be on the safe side
|
||||
set_extra_lift(m_last_layer_z, layer.id(), print.config(), m_writer, extruder_id);
|
||||
gcode += this->extrude_entity(*brim_entity, "Brim", m_config.support_material_speed.value);
|
||||
}
|
||||
m_brim_done = true;
|
||||
m_avoid_crossing_perimeters.use_external_mp(false);
|
||||
// Allow a straight travel move to the first object point.
|
||||
m_avoid_crossing_perimeters.disable_once();
|
||||
//to go to the object-only skirt or brim, or to the object (May be overriden here but I don't care)
|
||||
set_extra_lift(m_last_layer_z, layer.id(), print.config(), m_writer, extruder_id);
|
||||
}
|
||||
//extrude object-only skirt
|
||||
//TODO: use it also for wiping like the other one (as they are exlusiev)
|
||||
if (single_object_instance_idx != size_t(-1) && !layers.front().object()->skirt().empty()
|
||||
&& extruder_id == layer_tools.extruders.front()) {
|
||||
//if first layer, ask for a bigger lift for travel to object, to be on the safe side
|
||||
set_extra_lift(layer, print, m_writer, extruder_id);
|
||||
|
||||
const PrintObject *print_object = layers.front().object();
|
||||
this->set_origin(unscale(print_object->instances()[single_object_instance_idx].shift));
|
||||
@ -2540,8 +2575,6 @@ void GCode::process_layer(
|
||||
//extrude object-only brim
|
||||
if (single_object_instance_idx != size_t(-1) && !layers.front().object()->brim().empty()
|
||||
&& extruder_id == layer_tools.extruders.front()) {
|
||||
//if first layer, ask for a bigger lift for travel to object, to be on the safe side
|
||||
set_extra_lift(layer, print, m_writer, extruder_id);
|
||||
|
||||
const PrintObject *print_object = layers.front().object();
|
||||
this->set_origin(unscale(print_object->instances()[single_object_instance_idx].shift));
|
||||
@ -2566,7 +2599,7 @@ void GCode::process_layer(
|
||||
for (int print_wipe_extrusions = is_anything_overridden; print_wipe_extrusions>=0; --print_wipe_extrusions) {
|
||||
if (is_anything_overridden && print_wipe_extrusions == 0)
|
||||
gcode+="; PURGING FINISHED\n";
|
||||
|
||||
bool first_object = true;
|
||||
for (InstanceToPrint &instance_to_print : instances_to_print) {
|
||||
m_config.apply(instance_to_print.print_object.config(), true);
|
||||
m_layer = layers[instance_to_print.layer_id].layer();
|
||||
@ -2592,8 +2625,11 @@ void GCode::process_layer(
|
||||
m_gcode_label_objects_start += std::string("M486 S") + std::to_string(instance_plater_id) + "\n";
|
||||
}
|
||||
}
|
||||
//if first layer, ask for a bigger lift for travel to object, to be on the safe side
|
||||
set_extra_lift(layer, print, m_writer, extruder_id);
|
||||
// ask for a bigger lift for travel to object when moving to another object
|
||||
if (single_object_instance_idx == size_t(-1) && !first_object)
|
||||
set_extra_lift(m_last_layer_z, layer.id(), print.config(), m_writer, extruder_id);
|
||||
else
|
||||
first_object = false;
|
||||
// When starting a new object, use the external motion planner for the first travel move.
|
||||
const Point &offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift;
|
||||
std::pair<const PrintObject*, Point> this_object_copy(&instance_to_print.print_object, offset);
|
||||
@ -3902,7 +3938,10 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
|
||||
if (m_config.travel_acceleration.value > 0)
|
||||
travel_acceleration = m_config.travel_acceleration.get_abs_value(acceleration);
|
||||
}
|
||||
|
||||
if (m_writer.get_max_acceleration() > 0) {
|
||||
acceleration = std::min((double)m_writer.get_max_acceleration(), acceleration);
|
||||
travel_acceleration = std::min((double)m_writer.get_max_acceleration(), travel_acceleration);
|
||||
}
|
||||
if (travel_acceleration == acceleration) {
|
||||
m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5));
|
||||
// go to first point of extrusion path (stop at midpoint to let us set the decel speed)
|
||||
@ -3915,7 +3954,10 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
|
||||
if (!m_last_pos_defined || m_last_pos != path.first_point()) {
|
||||
Polyline poly_start = this->travel_to(gcode, path.first_point(), path.role());
|
||||
coordf_t length = poly_start.length();
|
||||
if (length > SCALED_EPSILON) {
|
||||
// if length is enough, it's not the hack for first move, and the travel accel is different than the normal accel
|
||||
// then cut the travel in two to change the accel in-between
|
||||
// TODO: compute the real point where it should be cut, considering an infinite max speed.
|
||||
if (length > std::max(scale_d(EPSILON), scale_d(m_config.min_length)) && m_last_pos_defined && floor(travel_acceleration) != floor(acceleration)) {
|
||||
Polyline poly_end;
|
||||
coordf_t min_length = scale_d(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0.5)) * 20;
|
||||
if (poly_start.size() > 2 && length > min_length * 3) {
|
||||
@ -3954,7 +3996,18 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
|
||||
_add_object_change_labels(gcode);
|
||||
|
||||
// compensate retraction
|
||||
gcode += this->unretract();
|
||||
if (m_delayed_layer_change.empty()) {
|
||||
gcode += m_writer.unlift();//this->unretract();
|
||||
} else {
|
||||
//check if an unlift happens
|
||||
std::string unlift = m_writer.unlift();
|
||||
if (unlift.empty()) {
|
||||
unlift = m_delayed_layer_change;
|
||||
}
|
||||
m_delayed_layer_change.clear();
|
||||
gcode += unlift;
|
||||
}
|
||||
gcode += m_writer.unretract();
|
||||
|
||||
speed = _compute_speed_mm_per_sec(path, speed);
|
||||
double F = speed * 60; // convert mm/sec to mm/min
|
||||
@ -4185,7 +4238,9 @@ std::string GCode::retract(bool toolchange)
|
||||
methods even if we performed wipe, since this will ensure the entire retraction
|
||||
length is honored in case wipe path was too short. */
|
||||
gcode += toolchange ? m_writer.retract_for_toolchange() : m_writer.retract();
|
||||
bool need_lift = !m_writer.tool_is_extruder() || toolchange || (BOOL_EXTRUDER_CONFIG(retract_lift_first_layer) && m_config.print_retract_lift.value != 0 && this->m_layer_index == 0);
|
||||
bool need_lift = !m_writer.tool_is_extruder() || toolchange
|
||||
|| (BOOL_EXTRUDER_CONFIG(retract_lift_first_layer) && m_config.print_retract_lift.value != 0 && this->m_layer_index == 0)
|
||||
|| this->m_writer.get_extra_lift() > 0;
|
||||
bool last_fill_extusion_role_top_infill = (this->m_last_extrusion_role == ExtrusionRole::erTopSolidInfill || this->m_last_extrusion_role == ExtrusionRole::erIroning);
|
||||
if(this->m_last_extrusion_role == ExtrusionRole::erGapFill)
|
||||
last_fill_extusion_role_top_infill = (this->m_last_notgapfill_extrusion_role == ExtrusionRole::erTopSolidInfill || this->m_last_notgapfill_extrusion_role == ExtrusionRole::erIroning);
|
||||
@ -4198,12 +4253,7 @@ std::string GCode::retract(bool toolchange)
|
||||
need_lift = true;
|
||||
}
|
||||
if (need_lift)
|
||||
if (m_writer.tool()->retract_length() > 0
|
||||
|| m_config.use_firmware_retraction
|
||||
|| (!m_writer.tool_is_extruder() && m_writer.tool()->retract_lift() != 0)
|
||||
|| (BOOL_EXTRUDER_CONFIG(retract_lift_first_layer) && this->m_layer_index == 0)
|
||||
)
|
||||
gcode += m_writer.lift();
|
||||
gcode += m_writer.lift(this->m_layer_index);
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
@ -349,6 +349,8 @@ private:
|
||||
// Markers for the Pressure Equalizer to recognize the extrusion type.
|
||||
// The Pressure Equalizer removes the markers from the final G-code.
|
||||
bool m_enable_extrusion_role_markers;
|
||||
// HACK to avoid multiple Z move.
|
||||
std::string m_delayed_layer_change;
|
||||
// Keeps track of the last extrusion role passed to the processor
|
||||
ExtrusionRole m_last_processor_extrusion_role;
|
||||
// How many times will change_layer() be called?
|
||||
|
@ -510,14 +510,14 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment)
|
||||
/* If target Z is lower than current Z but higher than nominal Z
|
||||
we don't perform the move but we only adjust the nominal Z by
|
||||
reducing the lift amount that will be used for unlift. */
|
||||
if (!this->will_move_z(z)) {
|
||||
// note that if we move but it's lower and we are lifted, we can wait a bit for unlifting, to avoid possible dance on layer change.
|
||||
if (!this->will_move_z(z) || z < m_pos.z() && m_lifted > EPSILON) {
|
||||
double nominal_z = m_pos.z() - m_lifted;
|
||||
m_lifted -= (z - nominal_z);
|
||||
if (std::abs(m_lifted) < EPSILON)
|
||||
m_lifted = 0.;
|
||||
return "";
|
||||
}
|
||||
|
||||
/* In all the other cases, we perform an actual Z move and cancel
|
||||
the lift. */
|
||||
m_lifted = 0;
|
||||
@ -548,7 +548,7 @@ bool GCodeWriter::will_move_z(double z) const
|
||||
we don't perform an actual Z move. */
|
||||
if (m_lifted > 0) {
|
||||
double nominal_z = m_pos.z() - m_lifted;
|
||||
if (z >= nominal_z && z <= m_pos.z())
|
||||
if (z >= nominal_z + EPSILON && z <= m_pos.z() - EPSILON)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -698,15 +698,19 @@ std::string GCodeWriter::unretract()
|
||||
/* If this method is called more than once before calling unlift(),
|
||||
it will not perform subsequent lifts, even if Z was raised manually
|
||||
(i.e. with travel_to_z()) and thus _lifted was reduced. */
|
||||
std::string GCodeWriter::lift()
|
||||
std::string GCodeWriter::lift(int layer_id)
|
||||
{
|
||||
// check whether the above/below conditions are met
|
||||
double target_lift = 0;
|
||||
if(this->tool_is_extruder()){
|
||||
//these two should be in the Tool class methods....
|
||||
double above = this->config.retract_lift_above.get_at(m_tool->id());
|
||||
double below = this->config.retract_lift_below.get_at(m_tool->id());
|
||||
if (m_pos.z() >= above && (below == 0 || m_pos.z() <= below))
|
||||
bool can_lift = this->config.retract_lift_first_layer.get_at(m_tool->id()) && layer_id == 0;
|
||||
if (!can_lift) {
|
||||
//these two should be in the Tool class methods....
|
||||
double above = this->config.retract_lift_above.get_at(m_tool->id());
|
||||
double below = this->config.retract_lift_below.get_at(m_tool->id());
|
||||
can_lift = (m_pos.z() >= above - EPSILON && (below == 0 || m_pos.z() <= below + EPSILON));
|
||||
}
|
||||
if(can_lift)
|
||||
target_lift = m_tool->retract_lift();
|
||||
} else {
|
||||
target_lift = m_tool->retract_lift();
|
||||
@ -717,17 +721,19 @@ std::string GCodeWriter::lift()
|
||||
target_lift = config_region->print_retract_lift.value;
|
||||
}
|
||||
|
||||
if (this->extra_lift > 0) {
|
||||
target_lift += this->extra_lift;
|
||||
this->extra_lift = 0;
|
||||
// one-time extra lift (often for dangerous travels)
|
||||
if (this->m_extra_lift > 0) {
|
||||
target_lift += this->m_extra_lift;
|
||||
this->m_extra_lift = 0;
|
||||
}
|
||||
|
||||
// compare against epsilon because travel_to_z() does math on it
|
||||
// and subtracting layer_height from retract_lift might not give
|
||||
// exactly zero
|
||||
if (std::abs(m_lifted) < EPSILON && target_lift > 0) {
|
||||
if (std::abs(m_lifted) < target_lift - EPSILON && target_lift > 0) {
|
||||
std::string str = this->_travel_to_z(m_pos.z() + target_lift - m_lifted, "lift Z");
|
||||
m_lifted = target_lift;
|
||||
return this->_travel_to_z(m_pos.z() + target_lift, "lift Z");
|
||||
return str;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
std::string set_fan(uint8_t speed, bool dont_save = false, uint16_t default_tool = 0);
|
||||
void set_acceleration(uint32_t acceleration);
|
||||
uint32_t get_acceleration() const;
|
||||
uint32_t get_max_acceleration() { return this->m_max_acceleration; }
|
||||
std::string write_acceleration();
|
||||
std::string reset_e(bool force = false);
|
||||
std::string update_progress(uint32_t num, uint32_t tot, bool allow_100 = false) const;
|
||||
@ -73,11 +74,12 @@ public:
|
||||
std::string retract(bool before_wipe = false);
|
||||
std::string retract_for_toolchange(bool before_wipe = false);
|
||||
std::string unretract();
|
||||
std::string lift();
|
||||
void set_extra_lift(double extra_zlift) { this->m_extra_lift = extra_zlift; }
|
||||
double get_extra_lift() { return this->m_extra_lift; }
|
||||
std::string lift(int layer_id);
|
||||
std::string unlift();
|
||||
Vec3d get_position() const { return m_pos; }
|
||||
|
||||
void set_extra_lift(double extra_zlift) { this->extra_lift = extra_zlift; }
|
||||
private:
|
||||
// Extruders are sorted by their ID, so that binary search is possible.
|
||||
std::vector<Extruder> m_extruders;
|
||||
@ -96,14 +98,15 @@ private:
|
||||
int16_t m_last_temperature_with_offset;
|
||||
int16_t m_last_bed_temperature;
|
||||
bool m_last_bed_temperature_reached;
|
||||
// if positive, it's set, and the next lift wil have this extra lift
|
||||
double m_extra_lift = 0;
|
||||
// current lift, to remove from m_pos to have the current height.
|
||||
double m_lifted;
|
||||
Vec3d m_pos = Vec3d::Zero();
|
||||
|
||||
std::string _travel_to_z(double z, const std::string &comment);
|
||||
std::string _retract(double length, double restart_extra, double restart_extra_toolchange, const std::string &comment);
|
||||
|
||||
// if positive, it's set, and the next lift wil have this extra lift
|
||||
double extra_lift = 0;
|
||||
};
|
||||
|
||||
} /* namespace Slic3r */
|
||||
|
@ -735,6 +735,7 @@ const std::vector<std::string>& Preset::printer_options()
|
||||
"gcode_precision_e",
|
||||
"use_relative_e_distances",
|
||||
"use_firmware_retraction", "use_volumetric_e", "variable_layer_height",
|
||||
"lift_min",
|
||||
"min_length",
|
||||
"max_gcode_per_second",
|
||||
//FIXME the print host keys are left here just for conversion from the Printer preset to Physical Printer preset.
|
||||
|
@ -2590,6 +2590,18 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("lift_min", coFloat);
|
||||
def->label = L("Min height for travel");
|
||||
def->category = OptionCategory::extruders;
|
||||
def->tooltip = L("When an extruder travels to an object (from the start position or from an object to another), the nozzle height is guaranteed to be at least at this value."
|
||||
"\nIt's made to ensure the nozzle won't hit clips or things you have on your bed. But be careful to not put a clip in the 'convex shape' of an object."
|
||||
"\nSet to 0 to disable.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->is_vector_extruder = true;
|
||||
def->set_default_value(new ConfigOptionFloat(0));
|
||||
|
||||
def = this->add("machine_limits_usage", coEnum);
|
||||
def->label = L("How to apply limits");
|
||||
def->full_label = L("Purpose of Machine Limits");
|
||||
@ -4036,7 +4048,7 @@ void PrintConfigDef::init_fff_params()
|
||||
"(1+, 0 to use the current extruder to minimize tool changes).");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
def = this->add("support_material_extrusion_width", coFloatOrPercent);
|
||||
def->label = L("Support material");
|
||||
@ -4068,7 +4080,7 @@ void PrintConfigDef::init_fff_params()
|
||||
"(1+, 0 to use the current extruder to minimize tool changes). This affects raft too.");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
def->set_default_value(new ConfigOptionInt(0));
|
||||
|
||||
def = this->add("support_material_interface_layers", coInt);
|
||||
def->label = L("Interface layers");
|
||||
@ -5915,6 +5927,7 @@ std::unordered_set<std::string> prusa_export_to_remove_keys = {
|
||||
"infill_dense_algo",
|
||||
"infill_dense",
|
||||
"infill_extrusion_spacing",
|
||||
"lift_min",
|
||||
"machine_max_acceleration_travel",
|
||||
"max_speed_reduction",
|
||||
"milling_after_z",
|
||||
|
@ -1338,6 +1338,7 @@ public:
|
||||
ConfigOptionInts first_layer_temperature;
|
||||
ConfigOptionInts full_fan_speed_layer;
|
||||
ConfigOptionFloatOrPercent infill_acceleration;
|
||||
ConfigOptionFloat lift_min;
|
||||
ConfigOptionInts max_fan_speed;
|
||||
ConfigOptionFloatsOrPercents max_layer_height;
|
||||
ConfigOptionFloat max_print_height;
|
||||
@ -1442,6 +1443,7 @@ protected:
|
||||
OPT_PTR(first_layer_temperature);
|
||||
OPT_PTR(full_fan_speed_layer);
|
||||
OPT_PTR(infill_acceleration);
|
||||
OPT_PTR(lift_min);
|
||||
OPT_PTR(max_fan_speed);
|
||||
OPT_PTR(max_layer_height);
|
||||
OPT_PTR(max_print_height);
|
||||
|
@ -986,71 +986,70 @@ void Control::draw_ruler(wxDC& dc)
|
||||
wxCoord pos = get_position_from_value(tick);
|
||||
draw_ticks_pair(dc, pos, mid, 5);
|
||||
draw_tick_text(dc, wxPoint(mid, pos), tick);
|
||||
}
|
||||
else {
|
||||
auto draw_short_ticks = [this, mid](wxDC& dc, double& current_tick, int max_tick) {
|
||||
while (current_tick < max_tick) {
|
||||
wxCoord pos = get_position_from_value(lround(current_tick));
|
||||
draw_ticks_pair(dc, pos, mid, 2);
|
||||
current_tick += m_ruler.short_step;
|
||||
if (current_tick > m_max_value)
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
double short_tick = std::nan("");
|
||||
int tick = 0;
|
||||
double value = 0.0;
|
||||
int sequence = 0;
|
||||
|
||||
int prev_y_pos = -1;
|
||||
wxCoord label_height = dc.GetMultiLineTextExtent("0").y - 2;
|
||||
int values_size = (int)m_values.size();
|
||||
|
||||
while (tick <= m_max_value) {
|
||||
value += m_ruler.long_step;
|
||||
if (value > m_values.back() && sequence < m_ruler.count) {
|
||||
value = m_ruler.long_step;
|
||||
for (; tick < values_size; tick++)
|
||||
if (m_values[tick] < value)
|
||||
} else {
|
||||
auto draw_short_ticks = [this, mid](wxDC& dc, double& current_tick, int max_tick) {
|
||||
while (current_tick < max_tick) {
|
||||
wxCoord pos = get_position_from_value(lround(current_tick));
|
||||
draw_ticks_pair(dc, pos, mid, 2);
|
||||
current_tick += m_ruler.short_step;
|
||||
if (current_tick > m_max_value)
|
||||
break;
|
||||
// short ticks from the last tick to the end of current sequence
|
||||
assert(! std::isnan(short_tick));
|
||||
}
|
||||
};
|
||||
|
||||
double short_tick = std::nan("");
|
||||
int tick = 0;
|
||||
double value = 0.0;
|
||||
int sequence = 0;
|
||||
|
||||
int prev_y_pos = -1;
|
||||
wxCoord label_height = dc.GetMultiLineTextExtent("0").y - 2;
|
||||
int values_size = (int)m_values.size();
|
||||
|
||||
while (tick <= m_max_value) {
|
||||
value += m_ruler.long_step;
|
||||
if (value > m_values.back() && sequence < m_ruler.count) {
|
||||
value = m_ruler.long_step;
|
||||
for (; tick < values_size; tick++)
|
||||
if (m_values[tick] < value)
|
||||
break;
|
||||
// short ticks from the last tick to the end of current sequence
|
||||
//assert(!std::isnan(short_tick));
|
||||
draw_short_ticks(dc, short_tick, tick);
|
||||
sequence++;
|
||||
}
|
||||
short_tick = tick;
|
||||
|
||||
for (; tick < values_size; tick++) {
|
||||
if (m_values[tick] == value)
|
||||
break;
|
||||
if (m_values[tick] > value) {
|
||||
if (tick > 0)
|
||||
tick--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tick > m_max_value)
|
||||
break;
|
||||
|
||||
wxCoord pos = get_position_from_value(tick);
|
||||
draw_ticks_pair(dc, pos, mid, 5);
|
||||
if (prev_y_pos < 0 || prev_y_pos - pos >= label_height) {
|
||||
draw_tick_text(dc, wxPoint(mid, pos), tick);
|
||||
prev_y_pos = pos;
|
||||
}
|
||||
|
||||
draw_short_ticks(dc, short_tick, tick);
|
||||
sequence++;
|
||||
}
|
||||
short_tick = tick;
|
||||
|
||||
for (; tick < values_size; tick++) {
|
||||
if (m_values[tick] == value)
|
||||
break;
|
||||
if (m_values[tick] > value) {
|
||||
if (tick > 0)
|
||||
tick--;
|
||||
break;
|
||||
if (value == m_values.back() && sequence < m_ruler.count) {
|
||||
value = 0.0;
|
||||
sequence++;
|
||||
tick++;
|
||||
}
|
||||
}
|
||||
// short ticks from the last tick to the end
|
||||
draw_short_ticks(dc, short_tick, m_max_value);
|
||||
}
|
||||
if (tick > m_max_value)
|
||||
break;
|
||||
|
||||
wxCoord pos = get_position_from_value(tick);
|
||||
draw_ticks_pair(dc, pos, mid, 5);
|
||||
if (prev_y_pos < 0 || prev_y_pos - pos >= label_height) {
|
||||
draw_tick_text(dc, wxPoint(mid, pos), tick);
|
||||
prev_y_pos = pos;
|
||||
}
|
||||
|
||||
draw_short_ticks(dc, short_tick, tick);
|
||||
|
||||
if (value == m_values.back() && sequence < m_ruler.count) {
|
||||
value = 0.0;
|
||||
sequence++;
|
||||
tick++;
|
||||
}
|
||||
}
|
||||
// short ticks from the last tick to the end
|
||||
draw_short_ticks(dc, short_tick, m_max_value);
|
||||
}
|
||||
|
||||
dc.SetTextForeground(old_clr);
|
||||
}
|
||||
|
@ -2965,7 +2965,7 @@ void TabPrinter::toggle_options()
|
||||
|
||||
// retract lift above / below only applies if using retract lift
|
||||
vec.resize(0);
|
||||
vec = { "retract_lift_above", "retract_lift_below", "retract_lift_top" };
|
||||
vec = { "retract_lift_above", "retract_lift_below", "retract_lift_top", "retract_lift_first_layer" };
|
||||
for (auto el : vec) {
|
||||
field = get_field(el, i);
|
||||
if (field)
|
||||
|
Loading…
x
Reference in New Issue
Block a user