mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 15:07:31 -06:00
ENH: support traditional timelapse for i3 structure
Jira: 3935 Change-Id: I38a270f7d9060ea1b271c69fd0d427205817e705 (cherry picked from commit 3f50b94adef5e48b169ad72e777135389d0e4ebf)
This commit is contained in:
parent
dcf3e736fe
commit
433a48cd00
11 changed files with 174 additions and 5 deletions
|
@ -289,6 +289,7 @@ static constexpr const char* TIMELAPSE_TYPE_ATTR = "timelapse_type";
|
|||
static constexpr const char* OUTSIDE_ATTR = "outside";
|
||||
static constexpr const char* SUPPORT_USED_ATTR = "support_used";
|
||||
static constexpr const char* LABEL_OBJECT_ENABLED_ATTR = "label_object_enabled";
|
||||
static constexpr const char* TIMELAPSE_TYPE_ATTR = "timelapse_type";
|
||||
static constexpr const char* SKIPPED_ATTR = "skipped";
|
||||
|
||||
static constexpr const char* OBJECT_TYPE = "object";
|
||||
|
|
|
@ -736,6 +736,33 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
|||
return gcode;
|
||||
}
|
||||
|
||||
bool WipeTowerIntegration::is_empty_wipe_tower_gcode(GCode &gcodegen, int extruder_id, bool finish_layer)
|
||||
{
|
||||
assert(m_layer_idx >= 0);
|
||||
if (m_layer_idx >= (int) m_tool_changes.size())
|
||||
return true;
|
||||
|
||||
bool ignore_sparse = false;
|
||||
if (gcodegen.config().wipe_tower_no_sparse_layers.value) {
|
||||
ignore_sparse = (m_tool_changes[m_layer_idx].size() == 1 && m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool);
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print && m_is_first_print) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
|
||||
if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
|
||||
throw Slic3r::RuntimeError("Wipe tower generation failed, possibly due to empty first layer.");
|
||||
|
||||
if (!ignore_sparse) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Print is finished. Now it remains to unload the filament safely with ramming over the wipe tower.
|
||||
std::string WipeTowerIntegration::finalize(GCode& gcodegen)
|
||||
{
|
||||
|
@ -1011,6 +1038,7 @@ namespace DoExport {
|
|||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Machine end G-code")), config.machine_end_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Before layer change G-code")), config.before_layer_change_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Layer change G-code")), config.layer_change_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Time lapse G-code")), config.time_lapse_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Change filament G-code")), config.change_filament_gcode.value);
|
||||
//BBS
|
||||
//if (ret.size() < MAX_TAGS_COUNT) check(_(L("Printing by object G-code")), config.printing_by_object_gcode.value);
|
||||
|
@ -1132,6 +1160,8 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu
|
|||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info();
|
||||
// Post-process the G-code to update time stamps.
|
||||
|
||||
m_processor.result().timelapse_warning_code = m_timelapse_warning_code;
|
||||
m_processor.finalize(true);
|
||||
// DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics);
|
||||
DoExport::update_print_estimated_stats(m_processor, m_writer.extruders(), print->m_print_statistics);
|
||||
|
@ -2827,10 +2857,35 @@ GCode::LayerResult GCode::process_layer(
|
|||
+ "\n";
|
||||
}
|
||||
|
||||
PrinterStructure printer_structure = m_config.printer_structure.value;
|
||||
bool need_insert_timelapse_gcode_for_traditional = false;
|
||||
if (printer_structure == PrinterStructure::psI3 && (!m_wipe_tower || !m_wipe_tower->enable_timelapse_print())) {
|
||||
need_insert_timelapse_gcode_for_traditional = true;
|
||||
}
|
||||
bool has_insert_timelapse_gcode = false;
|
||||
bool has_wipe_tower = (layer_tools.has_wipe_tower && m_wipe_tower);
|
||||
|
||||
auto insert_timelapse_gcode = [this, print_z, &print]() -> std::string {
|
||||
std::string gcode_res;
|
||||
if (!print.config().time_lapse_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
gcode_res = this->placeholder_parser_process("timelapse_gcode", print.config().time_lapse_gcode.value, m_writer.extruder()->id(), &config) + "\n";
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
}
|
||||
return gcode_res;
|
||||
};
|
||||
|
||||
// BBS: don't use lazy_raise when enable spiral vase
|
||||
gcode += this->change_layer(print_z); // this will increase m_layer_index
|
||||
m_layer = &layer;
|
||||
m_object_layer_over_raft = false;
|
||||
if (printer_structure == PrinterStructure::psI3 && !need_insert_timelapse_gcode_for_traditional) {
|
||||
gcode += insert_timelapse_gcode();
|
||||
//todo: get the last position of timelapse_gcode, and set into m_writer. Then delete the m_writer.set_current_position_clear(false)
|
||||
m_writer.set_current_position_clear(false);
|
||||
}
|
||||
if (! print.config().layer_change_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
|
@ -3137,9 +3192,21 @@ GCode::LayerResult GCode::process_layer(
|
|||
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
|
||||
for (unsigned int extruder_id : layer_tools.extruders)
|
||||
{
|
||||
gcode += (layer_tools.has_wipe_tower && m_wipe_tower) ?
|
||||
m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back()) :
|
||||
this->set_extruder(extruder_id, print_z);
|
||||
if (has_wipe_tower) {
|
||||
if (!m_wipe_tower->is_empty_wipe_tower_gcode(*this, extruder_id, extruder_id == layer_tools.extruders.back())) {
|
||||
if (need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) {
|
||||
gcode += this->retract(false, false, LiftType::NormalLift);
|
||||
m_writer.add_object_change_labels(gcode);
|
||||
gcode += insert_timelapse_gcode();
|
||||
//todo: get the last position of timelapse_gcode, and set into m_writer. Then delete the m_writer.set_current_position_clear(false)
|
||||
m_writer.set_current_position_clear(false);
|
||||
has_insert_timelapse_gcode = true;
|
||||
}
|
||||
gcode += m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back());
|
||||
}
|
||||
} else {
|
||||
gcode += this->set_extruder(extruder_id, print_z);
|
||||
}
|
||||
|
||||
// let analyzer tag generator aware of a role type change
|
||||
if (layer_tools.has_wipe_tower && m_wipe_tower)
|
||||
|
@ -3234,12 +3301,15 @@ GCode::LayerResult GCode::process_layer(
|
|||
m_object_layer_over_raft = object_layer_over_raft;
|
||||
if (m_config.reduce_crossing_wall)
|
||||
m_avoid_crossing_perimeters.init_layer(*m_layer);
|
||||
|
||||
std::string temp_start_str;
|
||||
if (m_enable_label_object) {
|
||||
std::string start_str = std::string("; start printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n";
|
||||
if (print.is_BBL_Printer()) {
|
||||
start_str += ("M624 " + _encode_label_ids_to_base64({ instance_to_print.label_object_id }));
|
||||
start_str += "\n";
|
||||
}
|
||||
temp_start_str = start_str;
|
||||
m_writer.set_object_start_str(start_str);
|
||||
}
|
||||
//Orca's implementation for skipping object, for klipper firmware printer only
|
||||
|
@ -3325,13 +3395,58 @@ GCode::LayerResult GCode::process_layer(
|
|||
//FIXME the following code prints regions in the order they are defined, the path is not optimized in any way.
|
||||
bool is_infill_first = print.config().wall_infill_order == WallInfillOrder::InfillInnerOuter ||
|
||||
print.config().wall_infill_order == WallInfillOrder::InfillOuterInner;
|
||||
|
||||
auto has_infill = [](const std::vector<ObjectByExtruder::Island::Region> &by_region) {
|
||||
for (auto region : by_region) {
|
||||
if (!region.infills.empty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
//BBS: for first layer, we always print wall firstly to get better bed adhesive force
|
||||
//This behaviour is same with cura
|
||||
if (is_infill_first && !first_layer) {
|
||||
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode && has_infill(by_region_specific)) {
|
||||
gcode += this->retract(false, false, LiftType::NormalLift);
|
||||
if (!temp_start_str.empty() && m_writer.empty_object_start_str()) {
|
||||
std::string end_str = std::string("; stop printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n";
|
||||
if (print.is_BBL_Printer())
|
||||
end_str += "M625\n";
|
||||
gcode += end_str;
|
||||
}
|
||||
|
||||
gcode += insert_timelapse_gcode();
|
||||
//todo: get the last position of timelapse_gcode, and set into m_writer. Then delete the m_writer.set_current_position_clear(false)
|
||||
m_writer.set_current_position_clear(false);
|
||||
|
||||
if (!temp_start_str.empty() && m_writer.empty_object_start_str())
|
||||
gcode += temp_start_str;
|
||||
temp_start_str.clear();
|
||||
has_insert_timelapse_gcode = true;
|
||||
}
|
||||
gcode += this->extrude_infill(print, by_region_specific, false);
|
||||
gcode += this->extrude_perimeters(print, by_region_specific);
|
||||
} else {
|
||||
gcode += this->extrude_perimeters(print, by_region_specific);
|
||||
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode && has_infill(by_region_specific)) {
|
||||
gcode += this->retract(false, false, LiftType::NormalLift);
|
||||
if (!temp_start_str.empty() && m_writer.empty_object_start_str()) {
|
||||
std::string end_str = std::string("; stop printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n";
|
||||
if (print.is_BBL_Printer())
|
||||
end_str += "M625\n";
|
||||
gcode += end_str;
|
||||
}
|
||||
|
||||
gcode += insert_timelapse_gcode();
|
||||
//todo: get the last position of timelapse_gcode, and set into m_writer. Then delete the m_writer.set_current_position_clear(false)
|
||||
m_writer.set_current_position_clear(false);
|
||||
|
||||
if (!temp_start_str.empty() && m_writer.empty_object_start_str())
|
||||
gcode += temp_start_str;
|
||||
temp_start_str.clear();
|
||||
has_insert_timelapse_gcode = true;
|
||||
}
|
||||
gcode += this->extrude_infill(print,by_region_specific, false);
|
||||
}
|
||||
// ironing
|
||||
|
@ -3387,6 +3502,16 @@ GCode::LayerResult GCode::process_layer(
|
|||
BOOST_LOG_TRIVIAL(trace) << "Exported layer " << layer.id() << " print_z " << print_z <<
|
||||
log_memory_info();
|
||||
|
||||
if (!has_wipe_tower && need_insert_timelapse_gcode_for_traditional && !has_insert_timelapse_gcode) {
|
||||
if (m_timelapse_warning_code == 0)
|
||||
m_timelapse_warning_code = 1;
|
||||
gcode += this->retract(false, false, LiftType::NormalLift);
|
||||
m_writer.add_object_change_labels(gcode);
|
||||
gcode += insert_timelapse_gcode();
|
||||
//todo: get the last position of timelapse_gcode, and set into m_writer. Then delete the m_writer.set_current_position_clear(false)
|
||||
m_writer.set_current_position_clear(false);
|
||||
}
|
||||
|
||||
result.gcode = std::move(gcode);
|
||||
result.cooling_buffer_flush = object_layer || raft_layer || last_layer;
|
||||
return result;
|
||||
|
|
|
@ -91,6 +91,7 @@ public:
|
|||
std::string prime(GCode &gcodegen);
|
||||
void next_layer() { ++ m_layer_idx; m_tool_change_idx = 0; }
|
||||
std::string tool_change(GCode &gcodegen, int extruder_id, bool finish_layer);
|
||||
bool is_empty_wipe_tower_gcode(GCode &gcodegen, int extruder_id, bool finish_layer);
|
||||
std::string finalize(GCode &gcodegen);
|
||||
std::vector<float> used_filament_length() const;
|
||||
|
||||
|
@ -490,6 +491,8 @@ private:
|
|||
std::vector<size_t> m_label_objects_ids;
|
||||
std::string _encode_label_ids_to_base64(std::vector<size_t> ids);
|
||||
|
||||
int m_timelapse_warning_code = 0;
|
||||
|
||||
bool m_silent_time_estimator_enabled;
|
||||
|
||||
// Processor
|
||||
|
|
|
@ -788,6 +788,7 @@ void GCodeProcessorResult::reset() {
|
|||
toolpath_outside = false;
|
||||
//BBS: add label_object_enabled
|
||||
label_object_enabled = false;
|
||||
timelapse_warning_code = 0;
|
||||
printable_height = 0.0f;
|
||||
settings_ids.reset();
|
||||
extruders_count = 0;
|
||||
|
@ -815,6 +816,7 @@ void GCodeProcessorResult::reset() {
|
|||
toolpath_outside = false;
|
||||
//BBS: add label_object_enabled
|
||||
label_object_enabled = false;
|
||||
timelapse_warning_code = 0;
|
||||
printable_height = 0.0f;
|
||||
settings_ids.reset();
|
||||
extruders_count = 0;
|
||||
|
@ -4320,6 +4322,15 @@ void GCodeProcessor::update_slice_warnings()
|
|||
m_result.warnings.push_back(warning);
|
||||
}
|
||||
|
||||
// bbs:HRC checker
|
||||
warning.params.clear();
|
||||
warning.level = 1;
|
||||
if (m_result.timelapse_warning_code != 0) {
|
||||
warning.msg = NOT_SUPPORT_TRADITIONAL_TIMELAPSE;
|
||||
warning.error_code = "1000C003";
|
||||
m_result.warnings.push_back(warning);
|
||||
}
|
||||
|
||||
m_result.warnings.shrink_to_fit();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace Slic3r {
|
|||
// slice warnings enum strings
|
||||
#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"
|
||||
#define NOT_SUPPORT_TRADITIONAL_TIMELAPSE "not_support_traditional_timelapse"
|
||||
|
||||
enum class EMoveType : unsigned char
|
||||
{
|
||||
|
@ -179,6 +180,7 @@ namespace Slic3r {
|
|||
bool toolpath_outside;
|
||||
//BBS: add object_label_enabled
|
||||
bool label_object_enabled;
|
||||
int timelapse_warning_code {0};
|
||||
float printable_height;
|
||||
SettingsIds settings_ids;
|
||||
size_t extruders_count;
|
||||
|
@ -211,6 +213,7 @@ namespace Slic3r {
|
|||
bed_exclude_area = other.bed_exclude_area;
|
||||
toolpath_outside = other.toolpath_outside;
|
||||
label_object_enabled = other.label_object_enabled;
|
||||
timelapse_warning_code = other.timelapse_warning_code;
|
||||
printable_height = other.printable_height;
|
||||
settings_ids = other.settings_ids;
|
||||
extruders_count = other.extruders_count;
|
||||
|
@ -709,6 +712,7 @@ namespace Slic3r {
|
|||
void reset();
|
||||
|
||||
const GCodeProcessorResult& get_result() const { return m_result; }
|
||||
GCodeProcessorResult& result() { return m_result; }
|
||||
GCodeProcessorResult&& extract_result() { return std::move(m_result); }
|
||||
|
||||
// Load a G-code into a stand-alone G-code viewer.
|
||||
|
|
|
@ -846,7 +846,7 @@ static std::vector<std::string> s_Preset_machine_limits_options {
|
|||
static std::vector<std::string> s_Preset_printer_options {
|
||||
"printer_technology",
|
||||
"printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
|
||||
"single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "change_filament_gcode",
|
||||
"single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "time_lapse_gcode", "change_filament_gcode",
|
||||
"printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_max_radius","extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
|
||||
"default_print_profile", "inherits",
|
||||
"silent_mode",
|
||||
|
|
|
@ -117,6 +117,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
|||
"textured_plate_temp_initial_layer",
|
||||
"gcode_add_line_number",
|
||||
"layer_change_gcode",
|
||||
"time_lapse_gcode",
|
||||
"fan_min_speed",
|
||||
"fan_max_speed",
|
||||
"printable_height",
|
||||
|
|
|
@ -2011,6 +2011,14 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("time_lapse_gcode",coString);
|
||||
def->label = L("Time lapse G-code");
|
||||
def->multiline = true;
|
||||
def->full_width = true;
|
||||
def->height =5;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("silent_mode", coBool);
|
||||
def->label = L("Supports silent mode");
|
||||
def->tooltip = L("Whether the machine supports silent mode in which machine use lower acceleration to print");
|
||||
|
|
|
@ -857,6 +857,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionBool, bbl_bed_temperature_gcode))
|
||||
((ConfigOptionEnum<GCodeFlavor>, gcode_flavor))
|
||||
((ConfigOptionString, layer_change_gcode))
|
||||
((ConfigOptionString, time_lapse_gcode))
|
||||
//#ifdef HAS_PRESSURE_EQUALIZER
|
||||
// ((ConfigOptionFloat, max_volumetric_extrusion_rate_slope_positive))
|
||||
// ((ConfigOptionFloat, max_volumetric_extrusion_rate_slope_negative))
|
||||
|
|
|
@ -2839,6 +2839,8 @@ wxString Plater::get_slice_warning_string(GCodeProcessorResult::SliceWarning& wa
|
|||
return _L("The bed temperature exceeds filament's vitrification temperature. Please open the front door of printer before printing to avoid nozzle clog.");
|
||||
} else if (warning.msg == NOZZLE_HRC_CHECKER) {
|
||||
return _L("The nozzle hardness required by the filament is higher than the default nozzle hardness of the printer. Please replace the hardened nozzle or filament, otherwise, the nozzle will be attrited or damaged.");
|
||||
} else if (warning.msg == NOT_SUPPORT_TRADITIONAL_TIMELAPSE) {
|
||||
return _L("Enable traditional timelapse will cause artifacts on this model.");
|
||||
} else {
|
||||
return wxString(warning.msg);
|
||||
}
|
||||
|
|
|
@ -3155,6 +3155,16 @@ void TabPrinter::build_fff()
|
|||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
optgroup = page->new_optgroup(L("Time lapse G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup, opt_key, value);
|
||||
};
|
||||
option = optgroup->get_option("time_lapse_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
optgroup = page->new_optgroup(L("Change filament G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup, opt_key, value);
|
||||
|
@ -3680,6 +3690,9 @@ void TabPrinter::toggle_options()
|
|||
toggle_option(el, !is_BBL_printer);
|
||||
}
|
||||
|
||||
if (m_active_page->title() == "Machine gcode") {
|
||||
toggle_line("time_lapse_gcode", m_preset_bundle->printers.get_edited_preset().config.opt_enum<PrinterStructure>("printer_structure") == PrinterStructure::psI3);
|
||||
}
|
||||
wxString extruder_number;
|
||||
long val = 1;
|
||||
if ( m_active_page->title().IsSameAs("Extruder") ||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue