mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-29 22:02:10 +00:00
ENH: add wrapping detection
jira: STUDIO-13192 Change-Id: I0fb5692b18cdb3b7af624a831dcfb0f635b165f0 (cherry picked from commit 89a8b6ea5e34340cba3750416ce3100dcc39f5c2) (cherry picked from commit 50bc8c10a7b4ddc0b2dfe9cbab438b9d307b7fc0)
This commit is contained in:
@@ -5639,7 +5639,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
||||
upgrade_display_hold_count = HOLD_COUNT_MAX;
|
||||
BOOST_LOG_TRIVIAL(info) << "ack of upgrade_confirm";
|
||||
}
|
||||
|
||||
|
||||
if (j["upgrade"].contains("err_code")) {
|
||||
if (j["upgrade"]["err_code"].is_number()) {
|
||||
add_command_error_code_dlg(j["upgrade"]["err_code"].get<int>());
|
||||
@@ -7110,7 +7110,7 @@ void MachineObject::add_command_error_code_dlg(int command_err)
|
||||
if (!token.expired()) { m_command_error_code_dlgs.erase((GUI::DeviceErrorDialog*)event.GetEventObject());}
|
||||
event.Skip();
|
||||
});
|
||||
|
||||
|
||||
device_error_dialog->show_error_code(command_err);
|
||||
m_command_error_code_dlgs.insert(device_error_dialog);
|
||||
});
|
||||
@@ -7912,6 +7912,11 @@ std::string DeviceManager::get_printer_ext_img(std::string type_str, int pos) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
bool DeviceManager::support_wrapping_detection(const std::string &type_str)
|
||||
{
|
||||
return get_value_from_config<bool>(type_str, "support_wrapping_deteciton");
|
||||
}
|
||||
|
||||
bool DeviceManager::get_printer_is_enclosed(std::string type_str) {
|
||||
return get_value_from_config<bool>(type_str, "printer_is_enclosed"); }
|
||||
|
||||
|
||||
@@ -1603,6 +1603,7 @@ public:
|
||||
static bool get_printer_is_enclosed(std::string type_str);
|
||||
static bool get_printer_can_set_nozzle(std::string type_str);// can set nozzle from studio
|
||||
static bool load_filaments_blacklist_config();
|
||||
static bool support_wrapping_detection(const std::string& type_str);
|
||||
|
||||
static string get_fan_text(const std::string& type_str, const std::string& key);
|
||||
|
||||
|
||||
@@ -2908,9 +2908,14 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
|
||||
const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
auto timelapse_type = dconfig.option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
|
||||
bool timelapse_enabled = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
|
||||
bool need_wipe_tower = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
|
||||
|
||||
if (wt && (timelapse_enabled || filaments_count > 1) && !wxGetApp().plater()->only_gcode_mode() && !wxGetApp().plater()->is_gcode_3mf()) {
|
||||
const DynamicPrintConfig & printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||
if (printer_config.has("enable_wrapping_detection")) {
|
||||
need_wipe_tower |= dynamic_cast<const ConfigOptionBool*>(printer_config.option("enable_wrapping_detection"))->value;
|
||||
}
|
||||
|
||||
if (wt && (need_wipe_tower || filaments_count > 1) && !wxGetApp().plater()->only_gcode_mode() && !wxGetApp().plater()->is_gcode_3mf()) {
|
||||
for (int plate_id = 0; plate_id < n_plates; plate_id++) {
|
||||
// If print ByObject and there is only one object in the plate, the wipe tower is allowed to be generated.
|
||||
PartPlate* part_plate = ppl.get_plate(plate_id);
|
||||
@@ -2931,14 +2936,14 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
|
||||
const Print* print = m_process->fff_print();
|
||||
const Print* current_print = part_plate->fff_print();
|
||||
if (!timelapse_enabled && part_plate->get_extruders(true).size() < 2) continue;
|
||||
if (!need_wipe_tower && part_plate->get_extruders(true).size() < 2) continue;
|
||||
if (part_plate->get_objects_on_this_plate().empty()) continue;
|
||||
|
||||
float brim_width = print->wipe_tower_data(filaments_count).brim_width;
|
||||
const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
double wipe_vol = get_max_element(v);
|
||||
int nozzle_nums = wxGetApp().preset_bundle->get_printer_extruder_count();
|
||||
Vec3d wipe_tower_size = ppl.get_plate(plate_id)->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums);
|
||||
Vec3d wipe_tower_size = ppl.get_plate(plate_id)->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums, 0, false, dynamic_cast<const ConfigOptionBool*>(printer_config.option("enable_wrapping_detection"))->value);
|
||||
|
||||
{
|
||||
const float margin = WIPE_TOWER_MARGIN + brim_width;
|
||||
|
||||
@@ -1094,6 +1094,8 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
||||
if (opt_key == "printable_area")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else if (opt_key == "bed_exclude_area")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else if (opt_key == "wrapping_detection_path")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
|
||||
@@ -1230,6 +1232,8 @@ boost::any ConfigOptionsGroup::get_config_value2(const DynamicPrintConfig& confi
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else if (opt_key == "bed_exclude_area")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else if (opt_key == "wrapping_detection_path")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
|
||||
break;
|
||||
|
||||
@@ -1905,7 +1905,7 @@ bool PartPlate::check_compatible_of_nozzle_and_filament(const DynamicPrintConfig
|
||||
return wipe_tower_size;
|
||||
}*/
|
||||
|
||||
Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count, int plate_extruder_size, bool use_global_objects) const
|
||||
Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count, int plate_extruder_size, bool use_global_objects, bool enable_wrapping_detection) const
|
||||
{
|
||||
Vec3d wipe_tower_size;
|
||||
double layer_height = 0.08f; // hard code layer height
|
||||
@@ -1935,7 +1935,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con
|
||||
wipe_tower_size(2) = max_height;
|
||||
//const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
auto timelapse_type = config.option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
|
||||
bool timelapse_enabled = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
|
||||
bool need_wipe_tower = (timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false) | enable_wrapping_detection;
|
||||
double extra_spacing = config.option("prime_tower_infill_gap")->getFloat() / 100.;
|
||||
const ConfigOptionBool* use_rib_wall_opt = config.option<ConfigOptionBool>("prime_tower_rib_wall");
|
||||
bool use_rib_wall = use_rib_wall_opt ? use_rib_wall_opt->value: true;
|
||||
@@ -1958,7 +1958,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con
|
||||
if (extruder_count == 2) volume += filament_change_volume * (int) (plate_extruder_size / 2);
|
||||
if (use_rib_wall) {
|
||||
depth = std::sqrt(volume / layer_height * extra_spacing);
|
||||
if (timelapse_enabled || plate_extruder_size > 1) {
|
||||
if (need_wipe_tower || plate_extruder_size > 1) {
|
||||
float min_wipe_tower_depth = WipeTower::get_limit_depth_by_height(max_height);
|
||||
depth = std::max((double) min_wipe_tower_depth, depth);
|
||||
depth += rib_width / std::sqrt(2) + m_print->config().prime_tower_extra_rib_length.value;
|
||||
@@ -1967,7 +1967,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con
|
||||
}
|
||||
else {
|
||||
depth = volume/ (layer_height * w) *extra_spacing;
|
||||
if (timelapse_enabled || depth > EPSILON) {
|
||||
if (need_wipe_tower || depth > EPSILON) {
|
||||
float min_wipe_tower_depth = WipeTower::get_limit_depth_by_height(max_height);
|
||||
depth = std::max((double)min_wipe_tower_depth, depth);
|
||||
}
|
||||
@@ -1986,7 +1986,9 @@ arrangement::ArrangePolygon PartPlate::estimate_wipe_tower_polygon(const Dynamic
|
||||
//float a = dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value;
|
||||
std::vector<double> v = dynamic_cast<const ConfigOptionFloats*>(config.option("filament_prime_volume"))->values;
|
||||
float tower_brim_width = dynamic_cast<const ConfigOptionFloat*>(config.option("prime_tower_brim_width"))->value;
|
||||
wt_size = estimate_wipe_tower_size(config, w, get_max_element(v), extruder_count, plate_extruder_size, use_global_objects);
|
||||
const ConfigOptionBool * wrapping_opt = dynamic_cast<const ConfigOptionBool *>(config.option("enable_wrapping_detection"));
|
||||
bool enable_wrapping = (wrapping_opt != nullptr) && wrapping_opt->value;
|
||||
wt_size = estimate_wipe_tower_size(config, w, get_max_element(v), extruder_count, plate_extruder_size, use_global_objects, enable_wrapping);
|
||||
int plate_width=m_width, plate_depth=m_depth;
|
||||
float depth = wt_size(1);
|
||||
float margin = WIPE_TOWER_MARGIN + tower_brim_width, wp_brim_width = 0.f;
|
||||
|
||||
@@ -322,7 +322,7 @@ public:
|
||||
|
||||
Vec3d get_origin() { return m_origin; }
|
||||
//Vec3d calculate_wipe_tower_size(const DynamicPrintConfig &config, const double w, const double wipe_volume, int plate_extruder_size = 0, bool use_global_objects = false) const;
|
||||
Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count = 1, int plate_extruder_size = 0, bool use_global_objects = false) const;
|
||||
Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count = 1, int plate_extruder_size = 0, bool use_global_objects = false, bool enable_wrapping_detection = false) const;
|
||||
arrangement::ArrangePolygon estimate_wipe_tower_polygon(const DynamicPrintConfig & config, int plate_index, Vec3d& wt_pos, Vec3d& wt_size, int extruder_count = 1, int plate_extruder_size = 0, bool use_global_objects = false) const;
|
||||
bool check_objects_empty_and_gcode3mf(std::vector<int> &result) const;
|
||||
// get used filaments from config, 1 based idx
|
||||
|
||||
@@ -956,7 +956,8 @@ void Tab::init_options_list()
|
||||
|
||||
for (const std::string& opt_key : m_config->keys())
|
||||
{
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "thumbnails") {
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "thumbnails"
|
||||
|| opt_key == "wrapping_detection_path") {
|
||||
m_options_list.emplace(opt_key, m_opt_status_value);
|
||||
continue;
|
||||
}
|
||||
@@ -1569,13 +1570,31 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
||||
if (opt_key == "enable_prime_tower") {
|
||||
auto timelapse_type = m_config->option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
|
||||
bool timelapse_enabled = timelapse_type->value == TimelapseType::tlSmooth;
|
||||
if (!boost::any_cast<bool>(value) && timelapse_enabled) {
|
||||
MessageDialog dlg(wxGetApp().plater(), _L("A prime tower is required for smooth timelapse. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?"),
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_NO) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true));
|
||||
m_config_manipulation.apply(m_config, &new_conf);
|
||||
if (!boost::any_cast<bool>(value)) {
|
||||
bool set_enable_prime_tower = false;
|
||||
if (timelapse_enabled) {
|
||||
MessageDialog
|
||||
dlg(wxGetApp().plater(),
|
||||
_L("A prime tower is required for smooth timelapse. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?"),
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_NO) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true));
|
||||
m_config_manipulation.apply(m_config, &new_conf);
|
||||
set_enable_prime_tower = true;
|
||||
}
|
||||
}
|
||||
bool enable_wrapping = m_preset_bundle->printers.get_edited_preset().config.option<ConfigOptionBool>("enable_wrapping_detection")->value;
|
||||
if (enable_wrapping && !set_enable_prime_tower) {
|
||||
MessageDialog dlg(wxGetApp().plater(),
|
||||
_L("A prime tower is required for wrapping detection. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?"),
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_NO) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true));
|
||||
m_config_manipulation.apply(m_config, &new_conf);
|
||||
set_enable_prime_tower = true;
|
||||
}
|
||||
}
|
||||
wxGetApp().plater()->update();
|
||||
}
|
||||
@@ -1593,6 +1612,23 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
||||
update_wiping_button_visibility();
|
||||
}
|
||||
|
||||
if (opt_key == "enable_wrapping_detection") {
|
||||
bool wipe_tower_enabled = m_preset_bundle->prints.get_edited_preset().config.option<ConfigOptionBool>("enable_prime_tower")->value;
|
||||
if (boost::any_cast<bool>(value) && !wipe_tower_enabled) {
|
||||
MessageDialog dlg(wxGetApp().plater(),
|
||||
_L("Prime tower is required for wrapping detection. There may be flaws on the model without prime tower. Do you still want to enable wrapping detection?"),
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_NO) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value("enable_wrapping_detection", new ConfigOptionBool(false));
|
||||
m_config_manipulation.apply(m_config, &new_conf);
|
||||
wxGetApp().plater()->update();
|
||||
}
|
||||
} else {
|
||||
wxGetApp().plater()->update();
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_key == "precise_z_height") {
|
||||
bool wipe_tower_enabled = m_config->option<ConfigOptionBool>("enable_prime_tower")->value;
|
||||
if (boost::any_cast<bool>(value) && wipe_tower_enabled) {
|
||||
@@ -4162,6 +4198,9 @@ void TabPrinter::build_fff()
|
||||
optgroup->append_single_option_line("pellet_modded_printer", "pellet-flow-coefficient");
|
||||
optgroup->append_single_option_line("bbl_use_printhost");
|
||||
optgroup->append_single_option_line("scan_first_layer");
|
||||
optgroup->append_single_option_line("enable_wrapping_detection");
|
||||
optgroup->append_single_option_line("wrapping_detection_layers");
|
||||
//optgroup->append_single_option_line("wrapping_detection_path");
|
||||
optgroup->append_single_option_line("disable_m73");
|
||||
option = optgroup->get_option("thumbnails");
|
||||
option.opt.full_width = true;
|
||||
@@ -4306,6 +4345,17 @@ void TabPrinter::build_fff()
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
optgroup = page->new_optgroup(L("Wrapping Detection 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);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("wrapping_detection_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_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
@@ -4975,6 +5025,16 @@ void TabPrinter::toggle_options()
|
||||
// SoftFever: hide non-BBL settings
|
||||
for (auto el : {"use_firmware_retraction", "use_relative_e_distances", "support_multi_bed_types", "pellet_modded_printer", "bed_mesh_max", "bed_mesh_min", "bed_mesh_probe_distance", "adaptive_bed_mesh_margin", "thumbnails"})
|
||||
toggle_line(el, !is_BBL_printer);
|
||||
|
||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||
std::string printer_type = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||
toggle_line("enable_wrapping_detection", DeviceManager::support_wrapping_detection(printer_type));
|
||||
}
|
||||
|
||||
if (m_active_page->title() == L("Machine G-code")) {
|
||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||
std::string printer_type = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||
toggle_line("wrapping_detection_gcode", DeviceManager::support_wrapping_detection(printer_type));
|
||||
}
|
||||
|
||||
if (m_active_page->title() == L("Multimaterial")) {
|
||||
|
||||
@@ -1363,6 +1363,9 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
|
||||
else if (opt_key == "head_wrap_detect_zone") {
|
||||
return get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
}
|
||||
else if (opt_key == "wrapping_detection_path") {
|
||||
return get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
}
|
||||
Vec2d val = config.opt<ConfigOptionPoints>(opt_key)->get_at(opt_idx);
|
||||
return from_u8((boost::format("[%1%]") % ConfigOptionPoint(val).serialize()).str());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user