mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-19 12:47:50 -06:00
Merge branch 'master' into SoftFever
# Conflicts: # bbl/i18n/zh_cn/BambuStudio_zh_CN.po # resources/i18n/de/BambuStudio.mo # resources/i18n/en/BambuStudio.mo # resources/i18n/es/BambuStudio.mo # resources/i18n/fr/BambuStudio.mo # resources/i18n/hu/BambuStudio.mo # resources/i18n/nl/BambuStudio.mo # resources/i18n/sv/BambuStudio.mo # resources/i18n/zh_cn/BambuStudio.mo # resources/profiles/Creality.json # resources/profiles/Voron.json # resources/web/guide/3/index.html # src/libslic3r/AppConfig.cpp # src/libslic3r/GCode.cpp # src/libslic3r/GCode/GCodeProcessor.cpp # src/libslic3r/LayerRegion.cpp # src/libslic3r/Preset.cpp # src/libslic3r/Print.cpp # src/libslic3r/PrintConfig.cpp # src/libslic3r/PrintConfig.hpp # src/libslic3r/PrintObject.cpp # src/slic3r/GUI/AboutDialog.cpp # src/slic3r/GUI/BBLTopbar.cpp # src/slic3r/GUI/ConfigManipulation.cpp # src/slic3r/GUI/ConfigWizard.cpp # src/slic3r/GUI/GCodeViewer.cpp # src/slic3r/GUI/GUI_App.cpp # src/slic3r/GUI/GUI_Factories.cpp # src/slic3r/GUI/MainFrame.cpp # src/slic3r/GUI/Plater.cpp # src/slic3r/GUI/Tab.cpp # version.inc
This commit is contained in:
commit
bf8a9fee1f
689 changed files with 46784 additions and 10006 deletions
|
@ -722,7 +722,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
|||
new_gcode.reserve(gcode.size() * 2);
|
||||
bool overhang_fan_control= false;
|
||||
int overhang_fan_speed = 0;
|
||||
auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &overhang_fan_control, &overhang_fan_speed]() {
|
||||
auto change_extruder_set_fan = [ this, layer_id, layer_time, &new_gcode, &overhang_fan_control, &overhang_fan_speed](bool immediately_apply) {
|
||||
#define EXTRUDER_CONFIG(OPT) m_config.OPT.get_at(m_current_extruder)
|
||||
int fan_min_speed = EXTRUDER_CONFIG(fan_min_speed);
|
||||
int fan_speed_new = EXTRUDER_CONFIG(reduce_fan_stop_start_freq) ? fan_min_speed : 0;
|
||||
|
@ -771,18 +771,20 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
|||
m_fan_speed = fan_speed_new;
|
||||
//BBS
|
||||
m_current_fan_speed = fan_speed_new;
|
||||
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_fan_speed);
|
||||
if (immediately_apply)
|
||||
new_gcode += GCodeWriter::set_fan(m_config.gcode_flavor, m_fan_speed);
|
||||
}
|
||||
//BBS
|
||||
if (additional_fan_speed_new != m_additional_fan_speed && m_config.auxiliary_fan.value) {
|
||||
m_additional_fan_speed = additional_fan_speed_new;
|
||||
new_gcode += GCodeWriter::set_additional_fan(m_additional_fan_speed);
|
||||
if (immediately_apply)
|
||||
new_gcode += GCodeWriter::set_additional_fan(m_additional_fan_speed);
|
||||
}
|
||||
};
|
||||
|
||||
const char *pos = gcode.c_str();
|
||||
int current_feedrate = 0;
|
||||
change_extruder_set_fan();
|
||||
change_extruder_set_fan(true);
|
||||
for (const CoolingLine *line : lines) {
|
||||
const char *line_start = gcode.c_str() + line->line_start;
|
||||
const char *line_end = gcode.c_str() + line->line_end;
|
||||
|
@ -792,7 +794,7 @@ std::string CoolingBuffer::apply_layer_cooldown(
|
|||
unsigned int new_extruder = (unsigned int)atoi(line_start + m_toolchange_prefix.size());
|
||||
if (new_extruder != m_current_extruder) {
|
||||
m_current_extruder = new_extruder;
|
||||
change_extruder_set_fan();
|
||||
change_extruder_set_fan(false); //BBS: will force to resume fan speed when filament change is finished
|
||||
}
|
||||
new_gcode.append(line_start, line_end - line_start);
|
||||
} else if (line->type & CoolingLine::TYPE_OVERHANG_FAN_START) {
|
||||
|
|
|
@ -36,6 +36,7 @@ static const float DEFAULT_TRAVEL_ACCELERATION = 1250.0f;
|
|||
|
||||
static const size_t MIN_EXTRUDERS_COUNT = 5;
|
||||
static const float DEFAULT_FILAMENT_DIAMETER = 1.75f;
|
||||
static const int DEFAULT_FILAMENT_HRC = 0;
|
||||
static const float DEFAULT_FILAMENT_DENSITY = 1.245f;
|
||||
static const int DEFAULT_FILAMENT_VITRIFICATION_TEMPERATURE = 0;
|
||||
static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero();
|
||||
|
@ -472,7 +473,16 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
|
|||
PrintEstimatedStatistics::ETimeMode mode = static_cast<PrintEstimatedStatistics::ETimeMode>(i);
|
||||
if (mode == PrintEstimatedStatistics::ETimeMode::Normal || machine.enabled) {
|
||||
char buf[128];
|
||||
sprintf(buf, "; estimated printing time: %s\n", get_time_dhms(machine.time).c_str());
|
||||
if(!s_IsBBLPrinter)
|
||||
sprintf(buf, "; estimated printing time: %s\n", get_time_dhms(machine.time).c_str());
|
||||
else {
|
||||
//sprintf(buf, "; estimated printing time (%s mode) = %s\n",
|
||||
// (mode == PrintEstimatedStatistics::ETimeMode::Normal) ? "normal" : "silent",
|
||||
// get_time_dhms(machine.time).c_str());
|
||||
sprintf(buf, "; model printing time: %s; total estimated time: %s\n",
|
||||
get_time_dhms(machine.time - machine.roles_time[ExtrusionRole::erCustom]).c_str(),
|
||||
get_time_dhms(machine.time).c_str());
|
||||
}
|
||||
ret += buf;
|
||||
}
|
||||
}
|
||||
|
@ -794,6 +804,7 @@ void GCodeProcessorResult::reset() {
|
|||
extruders_count = 0;
|
||||
extruder_colors = std::vector<std::string>();
|
||||
filament_diameters = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DIAMETER);
|
||||
required_nozzle_HRC = std::vector<int>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_HRC);
|
||||
filament_densities = std::vector<float>(MIN_EXTRUDERS_COUNT, DEFAULT_FILAMENT_DENSITY);
|
||||
custom_gcode_per_print_z = std::vector<CustomGCode::Item>();
|
||||
warnings.clear();
|
||||
|
@ -899,14 +910,17 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
m_extruder_offsets.resize(extruders_count);
|
||||
m_extruder_colors.resize(extruders_count);
|
||||
m_result.filament_diameters.resize(extruders_count);
|
||||
m_result.required_nozzle_HRC.resize(extruders_count);
|
||||
m_result.filament_densities.resize(extruders_count);
|
||||
m_result.filament_vitrification_temperature.resize(extruders_count);
|
||||
m_extruder_temps.resize(extruders_count);
|
||||
m_result.nozzle_hrc = static_cast<int>(config.nozzle_hrc.getInt());
|
||||
|
||||
for (size_t i = 0; i < extruders_count; ++ i) {
|
||||
m_extruder_offsets[i] = to_3d(config.extruder_offset.get_at(i).cast<float>().eval(), 0.f);
|
||||
m_extruder_colors[i] = static_cast<unsigned char>(i);
|
||||
m_result.filament_diameters[i] = static_cast<float>(config.filament_diameter.get_at(i));
|
||||
m_result.required_nozzle_HRC[i] = static_cast<int>(config.required_nozzle_HRC.get_at(i));
|
||||
m_result.filament_densities[i] = static_cast<float>(config.filament_density.get_at(i));
|
||||
m_result.filament_vitrification_temperature[i] = static_cast<float>(config.temperature_vitrification.get_at(i));
|
||||
}
|
||||
|
@ -958,6 +972,9 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
|||
if (nozzle_volume != nullptr)
|
||||
m_nozzle_volume = nozzle_volume->value;
|
||||
|
||||
const ConfigOptionInt *nozzle_HRC = config.option<ConfigOptionInt>("nozzle_hrc");
|
||||
if (nozzle_HRC != nullptr) m_result.nozzle_hrc = nozzle_HRC->value;
|
||||
|
||||
const ConfigOptionEnum<GCodeFlavor>* gcode_flavor = config.option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor");
|
||||
if (gcode_flavor != nullptr)
|
||||
m_flavor = gcode_flavor->value;
|
||||
|
@ -1001,6 +1018,18 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
|||
}
|
||||
}
|
||||
|
||||
const ConfigOptionInts *filament_HRC = config.option<ConfigOptionInts>("required_nozzle_HRC");
|
||||
if (filament_HRC != nullptr) {
|
||||
m_result.required_nozzle_HRC.clear();
|
||||
m_result.required_nozzle_HRC.resize(filament_HRC->values.size());
|
||||
for (size_t i = 0; i < filament_HRC->values.size(); ++i) { m_result.required_nozzle_HRC[i] = static_cast<float>(filament_HRC->values[i]); }
|
||||
}
|
||||
|
||||
if (m_result.required_nozzle_HRC.size() < m_result.extruders_count) {
|
||||
for (size_t i = m_result.required_nozzle_HRC.size(); i < m_result.extruders_count; ++i) { m_result.required_nozzle_HRC.emplace_back(DEFAULT_FILAMENT_HRC);
|
||||
}
|
||||
}
|
||||
|
||||
const ConfigOptionFloats* filament_densities = config.option<ConfigOptionFloats>("filament_density");
|
||||
if (filament_densities != nullptr) {
|
||||
m_result.filament_densities.clear();
|
||||
|
@ -2720,10 +2749,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||
get_retract_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)) :
|
||||
get_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)));
|
||||
|
||||
//BBS
|
||||
for (unsigned char a = X; a <= E; ++a) {
|
||||
float axis_max_acceleration = get_axis_max_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||
if (acceleration * std::abs(delta_pos[a]) * inv_distance > axis_max_acceleration)
|
||||
acceleration = axis_max_acceleration;
|
||||
acceleration = axis_max_acceleration / (std::abs(delta_pos[a]) * inv_distance);
|
||||
}
|
||||
|
||||
block.acceleration = acceleration;
|
||||
|
@ -2752,23 +2782,30 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||
float v_factor = 1.0f;
|
||||
bool limited = false;
|
||||
|
||||
//BBS: currently jerk in x,y,z axis are combined to one value and be limited together in MC side
|
||||
//So we only need to handle Z axis
|
||||
for (unsigned char a = X; a <= E; ++a) {
|
||||
// Limit an axis. We have to differentiate coasting from the reversal of an axis movement, or a full stop.
|
||||
//BBS
|
||||
float jerk = 0;
|
||||
if (a == X) {
|
||||
Vec3f exit_v = prev.feedrate * (prev.exit_direction);
|
||||
exit_v(2, 0) = 0;
|
||||
if (prev_speed_larger)
|
||||
exit_v *= smaller_speed_factor;
|
||||
Vec3f entry_v = block.feedrate_profile.cruise * (curr.enter_direction);
|
||||
Vec3f jerk_v = entry_v - exit_v;
|
||||
jerk = jerk_v.norm();
|
||||
} else if (a == Y || a == Z) {
|
||||
jerk_v = Vec3f(abs(jerk_v.x()), abs(jerk_v.y()), abs(jerk_v.z()));
|
||||
Vec3f max_xyz_jerk_v = get_xyz_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i));
|
||||
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
if (jerk_v[i] > max_xyz_jerk_v[i]) {
|
||||
v_factor *= max_xyz_jerk_v[i] / jerk_v[i];
|
||||
jerk_v *= v_factor;
|
||||
limited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (a == Y || a == Z) {
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
float v_exit = prev.axis_feedrate[a];
|
||||
float v_entry = curr.axis_feedrate[a];
|
||||
|
||||
|
@ -2781,7 +2818,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||
}
|
||||
|
||||
// Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
|
||||
jerk =
|
||||
float jerk =
|
||||
(v_exit > v_entry) ?
|
||||
(((v_entry > 0.0f) || (v_exit < 0.0f)) ?
|
||||
// coasting
|
||||
|
@ -2794,12 +2831,13 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||
(v_entry - v_exit) :
|
||||
// axis reversal
|
||||
std::max(-v_exit, v_entry));
|
||||
}
|
||||
|
||||
float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||
if (jerk > axis_max_jerk) {
|
||||
v_factor *= axis_max_jerk / jerk;
|
||||
limited = true;
|
||||
|
||||
float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||
if (jerk > axis_max_jerk) {
|
||||
v_factor *= axis_max_jerk / jerk;
|
||||
limited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2866,7 +2904,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||
}
|
||||
else if (type == EMoveType::Extrude && m_extrusion_role == erExternalPerimeter) {
|
||||
m_seams_detector.activate(true);
|
||||
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id]);
|
||||
Vec3f plate_offset = {(float) m_x_offset, (float) m_y_offset, 0.0f};
|
||||
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id] - plate_offset);
|
||||
}
|
||||
|
||||
// store move
|
||||
|
@ -3147,22 +3186,30 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
|
|||
float v_factor = 1.0f;
|
||||
bool limited = false;
|
||||
|
||||
//BBS: currently jerk in x,y,z axis are combined to one value and be limited together in MC side
|
||||
//So we only need to handle Z axis
|
||||
for (unsigned char a = X; a <= E; ++a) {
|
||||
//BBS: Limit an axis. We have to differentiate coasting from the reversal of an axis movement, or a full stop.
|
||||
float jerk = 0;
|
||||
if (a == X) {
|
||||
Vec3f exit_v = prev.feedrate * (prev.exit_direction);
|
||||
exit_v(2, 0) = 0;
|
||||
if (prev_speed_larger)
|
||||
exit_v *= smaller_speed_factor;
|
||||
Vec3f entry_v = block.feedrate_profile.cruise * (curr.enter_direction);
|
||||
Vec3f jerk_v = entry_v - exit_v;
|
||||
jerk = jerk_v.norm();
|
||||
} else if (a == Y || a == Z) {
|
||||
jerk_v = Vec3f(abs(jerk_v.x()), abs(jerk_v.y()), abs(jerk_v.z()));
|
||||
Vec3f max_xyz_jerk_v = get_xyz_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i));
|
||||
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
{
|
||||
if (jerk_v[i] > max_xyz_jerk_v[i]) {
|
||||
v_factor *= max_xyz_jerk_v[i] / jerk_v[i];
|
||||
jerk_v *= v_factor;
|
||||
limited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (a == Y || a == Z) {
|
||||
continue;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
float v_exit = prev.axis_feedrate[a];
|
||||
float v_entry = curr.axis_feedrate[a];
|
||||
|
||||
|
@ -3175,7 +3222,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
|
|||
}
|
||||
|
||||
//BBS: Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
|
||||
jerk =
|
||||
float jerk =
|
||||
(v_exit > v_entry) ?
|
||||
(((v_entry > 0.0f) || (v_exit < 0.0f)) ?
|
||||
//BBS: coasting
|
||||
|
@ -3187,12 +3234,13 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
|
|||
(v_entry - v_exit) :
|
||||
//BBS: axis reversal
|
||||
std::max(-v_exit, v_entry));
|
||||
}
|
||||
|
||||
float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||
if (jerk > axis_max_jerk) {
|
||||
v_factor *= axis_max_jerk / jerk;
|
||||
limited = true;
|
||||
|
||||
float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||
if (jerk > axis_max_jerk) {
|
||||
v_factor *= axis_max_jerk / jerk;
|
||||
limited = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3229,18 +3277,20 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
|
|||
}
|
||||
|
||||
//BBS: seam detector
|
||||
Vec3f plate_offset = {(float) m_x_offset, (float) m_y_offset, 0.0f};
|
||||
|
||||
if (m_seams_detector.is_active()) {
|
||||
//BBS: check for seam starting vertex
|
||||
if (type == EMoveType::Extrude && m_extrusion_role == erExternalPerimeter && !m_seams_detector.has_first_vertex())
|
||||
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id]);
|
||||
if (type == EMoveType::Extrude && m_extrusion_role == erExternalPerimeter && !m_seams_detector.has_first_vertex()) {
|
||||
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id] - plate_offset);
|
||||
}
|
||||
//BBS: check for seam ending vertex and store the resulting move
|
||||
else if ((type != EMoveType::Extrude || (m_extrusion_role != erExternalPerimeter && m_extrusion_role != erOverhangPerimeter)) && m_seams_detector.has_first_vertex()) {
|
||||
auto set_end_position = [this](const Vec3f& pos) {
|
||||
m_end_position[X] = pos.x(); m_end_position[Y] = pos.y(); m_end_position[Z] = pos.z();
|
||||
};
|
||||
|
||||
const Vec3f curr_pos(m_end_position[X], m_end_position[Y], m_end_position[Z]);
|
||||
const Vec3f new_pos = m_result.moves.back().position - m_extruder_offsets[m_extruder_id];
|
||||
const Vec3f new_pos = m_result.moves.back().position - m_extruder_offsets[m_extruder_id] - plate_offset;
|
||||
const std::optional<Vec3f> first_vertex = m_seams_detector.get_first_vertex();
|
||||
//BBS: the threshold value = 0.0625f == 0.25 * 0.25 is arbitrary, we may find some smarter condition later
|
||||
|
||||
|
@ -3255,7 +3305,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line)
|
|||
}
|
||||
else if (type == EMoveType::Extrude && m_extrusion_role == erExternalPerimeter) {
|
||||
m_seams_detector.activate(true);
|
||||
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id]);
|
||||
m_seams_detector.set_first_vertex(m_result.moves.back().position - m_extruder_offsets[m_extruder_id] - plate_offset);
|
||||
}
|
||||
//BBS: store move
|
||||
store_move_vertex(type, m_move_path_type);
|
||||
|
@ -3821,7 +3871,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type, EMovePathType path_type)
|
|||
m_interpolation_points[i] =
|
||||
Vec3f(m_interpolation_points[i].x() + m_x_offset,
|
||||
m_interpolation_points[i].y() + m_y_offset,
|
||||
m_processing_start_custom_gcode ? m_zero_layer_height : m_interpolation_points[i].z()) +
|
||||
m_processing_start_custom_gcode ? m_first_layer_height : m_interpolation_points[i].z()) +
|
||||
m_extruder_offsets[m_extruder_id];
|
||||
}
|
||||
|
||||
|
@ -3832,7 +3882,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type, EMovePathType path_type)
|
|||
m_extruder_id,
|
||||
m_cp_color.current,
|
||||
//BBS: add plate's offset to the rendering vertices
|
||||
Vec3f(m_end_position[X] + m_x_offset, m_end_position[Y] + m_y_offset, m_processing_start_custom_gcode ? m_zero_layer_height : m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
|
||||
Vec3f(m_end_position[X] + m_x_offset, m_end_position[Y] + m_y_offset, m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
|
||||
static_cast<float>(m_end_position[E] - m_start_position[E]),
|
||||
m_feedrate,
|
||||
m_width,
|
||||
|
@ -3917,6 +3967,13 @@ float GCodeProcessor::get_axis_max_jerk(PrintEstimatedStatistics::ETimeMode mode
|
|||
}
|
||||
}
|
||||
|
||||
Vec3f GCodeProcessor::get_xyz_max_jerk(PrintEstimatedStatistics::ETimeMode mode) const
|
||||
{
|
||||
return Vec3f(get_option_value(m_time_processor.machine_limits.machine_max_jerk_x, static_cast<size_t>(mode)),
|
||||
get_option_value(m_time_processor.machine_limits.machine_max_jerk_y, static_cast<size_t>(mode)),
|
||||
get_option_value(m_time_processor.machine_limits.machine_max_jerk_z, static_cast<size_t>(mode)));
|
||||
}
|
||||
|
||||
float GCodeProcessor::get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const
|
||||
{
|
||||
size_t id = static_cast<size_t>(mode);
|
||||
|
@ -4074,7 +4131,27 @@ void GCodeProcessor::update_slice_warnings()
|
|||
}
|
||||
|
||||
if (!warning.params.empty()) {
|
||||
warning.msg = BED_TEMP_TOO_HIGH_THAN_FILAMENT;
|
||||
warning.msg = BED_TEMP_TOO_HIGH_THAN_FILAMENT;
|
||||
warning.error_code = "1000C001";
|
||||
m_result.warnings.push_back(warning);
|
||||
}
|
||||
|
||||
//bbs:HRC checker
|
||||
warning.params.clear();
|
||||
warning.level=1;
|
||||
if (m_result.nozzle_hrc!=0) {
|
||||
for (size_t i = 0; i < used_extruders.size(); i++) {
|
||||
int HRC=0;
|
||||
if (used_extruders[i] < m_result.required_nozzle_HRC.size())
|
||||
HRC = m_result.required_nozzle_HRC[used_extruders[i]];
|
||||
if (HRC != 0 && (m_result.nozzle_hrc<HRC))
|
||||
warning.params.push_back(std::to_string(used_extruders[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (!warning.params.empty()) {
|
||||
warning.msg = NOZZLE_HRC_CHECKER;
|
||||
warning.error_code = "1000C002";
|
||||
m_result.warnings.push_back(warning);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
namespace Slic3r {
|
||||
|
||||
// slice warnings enum strings
|
||||
#define BED_TEMP_TOO_HIGH_THAN_FILAMENT "bed_temperature_too_high_than_filament"
|
||||
#define NOZZLE_HRC_CHECKER "the_actual_nozzle_hrc_smaller_than_the_required_nozzle_hrc"
|
||||
#define BED_TEMP_TOO_HIGH_THAN_FILAMENT "bed_temperature_too_high_than_filament"
|
||||
|
||||
enum class EMoveType : unsigned char
|
||||
{
|
||||
|
@ -86,6 +87,7 @@ namespace Slic3r {
|
|||
|
||||
struct GCodeProcessorResult
|
||||
{
|
||||
|
||||
struct SettingsIds
|
||||
{
|
||||
std::string print;
|
||||
|
@ -134,6 +136,7 @@ namespace Slic3r {
|
|||
struct SliceWarning {
|
||||
int level; // 0: normal tips, 1: warning; 2: error
|
||||
std::string msg; // enum string
|
||||
std::string error_code; // error code for studio
|
||||
std::vector<std::string> params; // extra msg info
|
||||
};
|
||||
|
||||
|
@ -152,12 +155,14 @@ namespace Slic3r {
|
|||
size_t extruders_count;
|
||||
std::vector<std::string> extruder_colors;
|
||||
std::vector<float> filament_diameters;
|
||||
std::vector<int> required_nozzle_HRC;
|
||||
std::vector<float> filament_densities;
|
||||
std::vector<int> filament_vitrification_temperature;
|
||||
PrintEstimatedStatistics print_statistics;
|
||||
std::vector<CustomGCode::Item> custom_gcode_per_print_z;
|
||||
//BBS
|
||||
std::vector<SliceWarning> warnings;
|
||||
int nozzle_hrc;
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_STATISTICS
|
||||
int64_t time{ 0 };
|
||||
|
@ -578,7 +583,6 @@ namespace Slic3r {
|
|||
std::vector<Vec3f> m_extruder_offsets;
|
||||
GCodeFlavor m_flavor;
|
||||
float m_nozzle_volume;
|
||||
|
||||
AxisCoords m_start_position; // mm
|
||||
AxisCoords m_end_position; // mm
|
||||
AxisCoords m_origin; // mm
|
||||
|
@ -829,6 +833,7 @@ namespace Slic3r {
|
|||
float get_axis_max_feedrate(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
|
||||
float get_axis_max_acceleration(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
|
||||
float get_axis_max_jerk(PrintEstimatedStatistics::ETimeMode mode, Axis axis) const;
|
||||
Vec3f get_xyz_max_jerk(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||
float get_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||
void set_retract_acceleration(PrintEstimatedStatistics::ETimeMode mode, float value);
|
||||
float get_acceleration(PrintEstimatedStatistics::ETimeMode mode) const;
|
||||
|
@ -838,7 +843,6 @@ namespace Slic3r {
|
|||
float get_filament_load_time(size_t extruder_id);
|
||||
float get_filament_unload_time(size_t extruder_id);
|
||||
int get_filament_vitrification_temperature(size_t extrude_id);
|
||||
|
||||
void process_custom_gcode_time(CustomGCode::Type code);
|
||||
void process_filaments(CustomGCode::Type code);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ void ThumbnailData::set(unsigned int w, unsigned int h)
|
|||
width = w;
|
||||
height = h;
|
||||
// defaults to white texture
|
||||
pixels.clear();
|
||||
pixels = std::vector<unsigned char>(width * height * 4, 255);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ struct PlateBBoxData
|
|||
bool is_seq_print = false;
|
||||
int first_extruder = 0;
|
||||
float nozzle_diameter = 0.4;
|
||||
std::string bed_type;
|
||||
// version 1: use view type ColorPrint (filament color)
|
||||
// version 2: use view type FilamentId (filament id)
|
||||
int version = 2;
|
||||
|
@ -88,6 +89,7 @@ struct PlateBBoxData
|
|||
j["first_extruder"] = first_extruder;
|
||||
j["nozzle_diameter"] = nozzle_diameter;
|
||||
j["version"] = version;
|
||||
j["bed_type"] = bed_type;
|
||||
for (const auto& bbox : bbox_objs) {
|
||||
nlohmann::json j_bbox;
|
||||
bbox.to_json(j_bbox);
|
||||
|
@ -102,6 +104,7 @@ struct PlateBBoxData
|
|||
j.at("first_extruder").get_to(first_extruder);
|
||||
j.at("nozzle_diameter").get_to(nozzle_diameter);
|
||||
j.at("version").get_to(version);
|
||||
j.at("bed_type").get_to(bed_type);
|
||||
for (auto& bbox_j : j.at("bbox_objects")) {
|
||||
BBoxData bbox_data;
|
||||
bbox_data.from_json(bbox_j);
|
||||
|
|
|
@ -244,6 +244,45 @@ public:
|
|||
return (*this);
|
||||
}
|
||||
|
||||
WipeTowerWriter &rectangle_fill_box(const WipeTower* wipe_tower, const Vec2f &ld, float width, float height, const float f = 0.f)
|
||||
{
|
||||
bool need_change_flow = wipe_tower->need_thick_bridge_flow(ld.y());
|
||||
|
||||
Vec2f corners[4];
|
||||
corners[0] = ld;
|
||||
corners[1] = ld + Vec2f(width, 0.f);
|
||||
corners[2] = ld + Vec2f(width, height);
|
||||
corners[3] = ld + Vec2f(0.f, height);
|
||||
int index_of_closest = 0;
|
||||
if (x() - ld.x() > ld.x() + width - x()) // closer to the right
|
||||
index_of_closest = 1;
|
||||
if (y() - ld.y() > ld.y() + height - y()) // closer to the top
|
||||
index_of_closest = (index_of_closest == 0 ? 3 : 2);
|
||||
|
||||
travel(corners[index_of_closest].x(), y()); // travel to the closest corner
|
||||
travel(x(), corners[index_of_closest].y());
|
||||
|
||||
int i = index_of_closest;
|
||||
bool flow_changed = false;
|
||||
do {
|
||||
++i;
|
||||
if (i == 4) i = 0;
|
||||
if (need_change_flow) {
|
||||
if (i == 1) {
|
||||
// using bridge flow in bridge area, and add notes for gcode-check when flow changed
|
||||
set_extrusion_flow(wipe_tower->extrusion_flow(0.2));
|
||||
append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(0.2) + "\n");
|
||||
flow_changed = true;
|
||||
} else if (i == 2 && flow_changed) {
|
||||
set_extrusion_flow(wipe_tower->get_extrusion_flow());
|
||||
append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(m_layer_height) + "\n");
|
||||
}
|
||||
}
|
||||
extrude(corners[i], f);
|
||||
} while (i != index_of_closest);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
WipeTowerWriter& rectangle(const WipeTower::box_coordinates& box, const float f = 0.f)
|
||||
{
|
||||
rectangle(Vec2f(box.ld.x(), box.ld.y()),
|
||||
|
@ -664,7 +703,7 @@ std::vector<WipeTower::ToolChangeResult> WipeTower::prime(
|
|||
return std::vector<ToolChangeResult>();
|
||||
}
|
||||
|
||||
WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool extrude_perimeter)
|
||||
WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool extrude_perimeter, bool first_toolchange_to_nonsoluble)
|
||||
{
|
||||
size_t old_tool = m_current_tool;
|
||||
|
||||
|
@ -733,6 +772,12 @@ WipeTower::ToolChangeResult WipeTower::tool_change(size_t tool, bool extrude_per
|
|||
writer.rectangle(wt_box);
|
||||
writer.travel(initial_position);
|
||||
}
|
||||
|
||||
if (first_toolchange_to_nonsoluble) {
|
||||
writer.travel(Vec2f(0, 0));
|
||||
writer.travel(initial_position);
|
||||
}
|
||||
|
||||
toolchange_Wipe(writer, cleaning_box, wipe_length); // Wipe the newly loaded filament until the end of the assigned wipe area.
|
||||
++ m_num_tool_changes;
|
||||
} else
|
||||
|
@ -974,6 +1019,12 @@ void WipeTower::toolchange_Wipe(
|
|||
// Increase flow on first layer, slow down print.
|
||||
writer.set_extrusion_flow(m_extrusion_flow * (is_first_layer() ? 1.15f : 1.f))
|
||||
.append("; CP TOOLCHANGE WIPE\n");
|
||||
|
||||
// BBS: add the note for gcode-check, when the flow changed, the width should follow the change
|
||||
if (is_first_layer()) {
|
||||
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Width) + std::to_string(1.15 * m_perimeter_width) + "\n");
|
||||
}
|
||||
|
||||
const float& xl = cleaning_box.ld.x();
|
||||
const float& xr = cleaning_box.rd.x();
|
||||
|
||||
|
@ -1005,6 +1056,7 @@ void WipeTower::toolchange_Wipe(
|
|||
writer.travel(xl, writer.y() + dy);
|
||||
#endif
|
||||
|
||||
bool need_change_flow = false;
|
||||
// now the wiping itself:
|
||||
for (int i = 0; true; ++i) {
|
||||
if (i!=0) {
|
||||
|
@ -1014,11 +1066,24 @@ void WipeTower::toolchange_Wipe(
|
|||
else wipe_speed = std::min(target_speed, wipe_speed + 50.f);
|
||||
}
|
||||
|
||||
// BBS: check the bridging area and use the bridge flow
|
||||
if (need_change_flow || need_thick_bridge_flow(writer.y())) {
|
||||
writer.set_extrusion_flow(extrusion_flow(0.2));
|
||||
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(0.2) + "\n");
|
||||
need_change_flow = true;
|
||||
}
|
||||
|
||||
if (m_left_to_right)
|
||||
writer.extrude(xr + 0.25f * m_perimeter_width, writer.y(), wipe_speed);
|
||||
else
|
||||
writer.extrude(xl - 0.25f * m_perimeter_width, writer.y(), wipe_speed);
|
||||
|
||||
// BBS: recover the flow in non-bridging area
|
||||
if (need_change_flow) {
|
||||
writer.set_extrusion_flow(m_extrusion_flow);
|
||||
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Height) + std::to_string(m_layer_height) + "\n");
|
||||
}
|
||||
|
||||
if (writer.y() - float(EPSILON) > cleaning_box.lu.y())
|
||||
break; // in case next line would not fit
|
||||
|
||||
|
@ -1044,6 +1109,10 @@ void WipeTower::toolchange_Wipe(
|
|||
m_left_to_right = !m_left_to_right;
|
||||
|
||||
writer.set_extrusion_flow(m_extrusion_flow); // Reset the extrusion flow.
|
||||
// BBS: add the note for gcode-check when the flow changed
|
||||
if (is_first_layer()) {
|
||||
writer.append(";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Width) + std::to_string(m_perimeter_width) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1099,7 +1168,7 @@ WipeTower::ToolChangeResult WipeTower::finish_layer(bool extrude_perimeter, bool
|
|||
|
||||
// inner perimeter of the sparse section, if there is space for it:
|
||||
if (fill_box.ru.y() - fill_box.rd.y() > m_perimeter_width - WT_EPSILON)
|
||||
writer.rectangle(fill_box.ld, fill_box.rd.x() - fill_box.ld.x(), fill_box.ru.y() - fill_box.rd.y(), feedrate);
|
||||
writer.rectangle_fill_box(this, fill_box.ld, fill_box.rd.x() - fill_box.ld.x(), fill_box.ru.y() - fill_box.rd.y(), feedrate);
|
||||
|
||||
// we are in one of the corners, travel to ld along the perimeter:
|
||||
if (writer.x() > fill_box.ld.x() + EPSILON) writer.travel(fill_box.ld.x(), writer.y());
|
||||
|
@ -1241,6 +1310,10 @@ void WipeTower::plan_toolchange(float z_par, float layer_height_par, unsigned in
|
|||
float depth = 0.f;
|
||||
float width = m_wipe_tower_width - 2 * m_perimeter_width;
|
||||
|
||||
// BBS: if the wipe tower width is too small, the depth will be infinity
|
||||
if (width <= EPSILON)
|
||||
return;
|
||||
|
||||
// BBS: remove old filament ramming and first line
|
||||
#if 0
|
||||
float length_to_extrude = volume_to_length(0.25f * std::accumulate(m_filpar[old_tool].ramming_speed.begin(), m_filpar[old_tool].ramming_speed.end(), 0.f),
|
||||
|
@ -1518,7 +1591,11 @@ void WipeTower::generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &
|
|||
finish_layer_tcr = finish_layer(false, layer.extruder_fill);
|
||||
}
|
||||
else {
|
||||
layer_result.emplace_back(tool_change(layer.tool_changes[i].new_tool));
|
||||
if (idx == -1 && i == 0) {
|
||||
layer_result.emplace_back(tool_change(layer.tool_changes[i].new_tool, false, true));
|
||||
} else {
|
||||
layer_result.emplace_back(tool_change(layer.tool_changes[i].new_tool));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1585,4 +1662,30 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall()
|
|||
return construct_tcr(writer, false, old_tool, true, 0.f);
|
||||
}
|
||||
|
||||
bool WipeTower::get_floating_area(float &start_pos_y, float &end_pos_y) const {
|
||||
if (m_layer_info == m_plan.begin() || (m_layer_info - 1) == m_plan.begin())
|
||||
return false;
|
||||
|
||||
float last_layer_fill_box_y = (m_layer_info - 1)->toolchanges_depth() + m_perimeter_width;
|
||||
float last_layer_wipe_depth = (m_layer_info - 1)->depth;
|
||||
if (last_layer_wipe_depth - last_layer_fill_box_y <= 2 * m_perimeter_width)
|
||||
return false;
|
||||
|
||||
start_pos_y = last_layer_fill_box_y + m_perimeter_width;
|
||||
end_pos_y = last_layer_wipe_depth - m_perimeter_width;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WipeTower::need_thick_bridge_flow(float pos_y) const {
|
||||
if (m_extrusion_flow >= extrusion_flow(0.2))
|
||||
return false;
|
||||
|
||||
float y_min = 0., y_max = 0.;
|
||||
if (get_floating_area(y_min, y_max)) {
|
||||
return pos_y > y_min && pos_y < y_max;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -217,12 +217,23 @@ public:
|
|||
// Returns gcode for a toolchange and a final print head position.
|
||||
// On the first layer, extrude a brim around the future wipe tower first.
|
||||
// BBS
|
||||
ToolChangeResult tool_change(size_t new_tool, bool extrude_perimeter = false);
|
||||
ToolChangeResult tool_change(size_t new_tool, bool extrude_perimeter = false, bool first_toolchange_to_nonsoluble = false);
|
||||
|
||||
// Fill the unfilled space with a sparse infill.
|
||||
// Call this method only if layer_finished() is false.
|
||||
ToolChangeResult finish_layer(bool extruder_perimeter = true, bool extruder_fill = true);
|
||||
|
||||
// Calculates extrusion flow needed to produce required line width for given layer height
|
||||
float extrusion_flow(float layer_height = -1.f) const // negative layer_height - return current m_extrusion_flow
|
||||
{
|
||||
if (layer_height < 0) return m_extrusion_flow;
|
||||
return layer_height * (m_perimeter_width - layer_height * (1.f - float(M_PI) / 4.f)) / filament_area();
|
||||
}
|
||||
|
||||
bool get_floating_area(float& start_pos_y, float& end_pos_y) const;
|
||||
bool need_thick_bridge_flow(float pos_y) const;
|
||||
float get_extrusion_flow() const { return m_extrusion_flow; }
|
||||
|
||||
// Is the current layer finished?
|
||||
bool layer_finished() const {
|
||||
return m_current_layer_finished;
|
||||
|
@ -336,14 +347,6 @@ private:
|
|||
|
||||
bool is_first_layer() const { return size_t(m_layer_info - m_plan.begin()) == m_first_layer_idx; }
|
||||
|
||||
// Calculates extrusion flow needed to produce required line width for given layer height
|
||||
float extrusion_flow(float layer_height = -1.f) const // negative layer_height - return current m_extrusion_flow
|
||||
{
|
||||
if ( layer_height < 0 )
|
||||
return m_extrusion_flow;
|
||||
return layer_height * ( m_perimeter_width - layer_height * (1.f-float(M_PI)/4.f)) / filament_area();
|
||||
}
|
||||
|
||||
// Calculates length of extrusion line to extrude given volume
|
||||
float volume_to_length(float volume, float line_width, float layer_height) const {
|
||||
return std::max(0.f, volume / (layer_height * (line_width - layer_height * (1.f - float(M_PI) / 4.f))));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue