diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 1e8297b669..ec38f8e120 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -553,23 +553,30 @@ bool GCode::gcode_label_objects = false; std::string WipeTowerIntegration::tool_change(GCode& gcodegen, int extruder_id, bool finish_layer) { std::string gcode; + + // Calculate where the wipe tower layer will be printed. -1 means that print z will not change, + // resulting in a wipe tower with sparse layers. + double wipe_tower_z = -1; + bool ignore_sparse = false; + if (gcodegen.config().wipe_tower_no_sparse_layers.value) { + wipe_tower_z = m_last_wipe_tower_print_z; + 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_tool_change_idx == 0 && !ignore_sparse) + wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height; + } + + if (m_enable_timelapse_print && m_is_first_print) { + gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][0], m_tool_changes[m_layer_idx][0].new_tool, wipe_tower_z); + m_tool_change_idx++; + m_is_first_print = false; + } + assert(m_layer_idx >= 0); if (gcodegen.writer().need_toolchange(extruder_id) || finish_layer) { if (m_layer_idx < (int)m_tool_changes.size()) { 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."); - // Calculate where the wipe tower layer will be printed. -1 means that print z will not change, - // resulting in a wipe tower with sparse layers. - double wipe_tower_z = -1; - bool ignore_sparse = false; - if (gcodegen.config().wipe_tower_no_sparse_layers.value) { - wipe_tower_z = m_last_wipe_tower_print_z; - 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_tool_change_idx == 0 && !ignore_sparse) - wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height; - } - if (!ignore_sparse) { gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][m_tool_change_idx++], extruder_id, wipe_tower_z); m_last_wipe_tower_print_z = wipe_tower_z; @@ -2781,6 +2788,9 @@ GCode::LayerResult GCode::process_layer( } } // for objects + if (m_wipe_tower) + m_wipe_tower->set_is_first_print(true); + // Extrude the skirt, brim, support, perimeters, infill ordered by the extruders. std::vector> lower_layer_edge_grids(layers.size()); for (unsigned int extruder_id : layer_tools.extruders) diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 5963fe484d..702f47fe73 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -82,7 +82,9 @@ public: m_layer_idx(-1), m_tool_change_idx(0), m_plate_origin(plate_origin), - m_single_extruder_multi_material(print_config.single_extruder_multi_material) + m_single_extruder_multi_material(print_config.single_extruder_multi_material), + m_enable_timelapse_print(print_config.timelapse_no_toolhead.value), + m_is_first_print(true) {} std::string prime(GCode &gcodegen); @@ -91,6 +93,11 @@ public: std::string finalize(GCode &gcodegen); std::vector used_filament_length() const; + bool is_first_print() const { return m_is_first_print;} + void set_is_first_print(bool is) { m_is_first_print = is; } + + bool enable_timelapse_print() const { return m_enable_timelapse_print; } + private: WipeTowerIntegration& operator=(const WipeTowerIntegration&); std::string append_tcr(GCode &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z = -1.) const; @@ -117,6 +124,8 @@ private: // BBS Vec3d m_plate_origin; bool m_single_extruder_multi_material; + bool m_enable_timelapse_print; + bool m_is_first_print; }; class ColorPrintColors diff --git a/src/libslic3r/GCode/WipeTower.cpp b/src/libslic3r/GCode/WipeTower.cpp index 208df103bf..f0795ea7bb 100644 --- a/src/libslic3r/GCode/WipeTower.cpp +++ b/src/libslic3r/GCode/WipeTower.cpp @@ -544,7 +544,8 @@ WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origi m_travel_speed(config.travel_speed), m_current_tool(initial_tool), //wipe_volumes(flush_matrix) - m_wipe_volume(prime_volume) + m_wipe_volume(prime_volume), + m_enable_timelapse_print(config.timelapse_no_toolhead.value) { // Read absolute value of first layer speed, if given as percentage, // it is taken over following default. Speeds from config are not @@ -1304,7 +1305,10 @@ void WipeTower::plan_tower() } } - { + { + if (m_enable_timelapse_print && max_depth < EPSILON) + max_depth = min_wipe_tower_depth; + if (max_depth + EPSILON < min_wipe_tower_depth) m_extra_spacing = min_wipe_tower_depth / max_depth; else @@ -1343,9 +1347,13 @@ void WipeTower::plan_tower() for (auto& layer : m_plan) layer.depth = 0.f; + float max_depth_for_all = 0; for (int layer_index = int(m_plan.size()) - 1; layer_index >= 0; --layer_index) { float this_layer_depth = std::max(m_plan[layer_index].depth, m_plan[layer_index].toolchanges_depth()); + if (m_enable_timelapse_print && this_layer_depth < EPSILON) + this_layer_depth = min_wipe_tower_depth; + m_plan[layer_index].depth = this_layer_depth; if (this_layer_depth > m_wipe_tower_depth - m_perimeter_width) @@ -1356,7 +1364,16 @@ void WipeTower::plan_tower() if (m_plan[i].depth - this_layer_depth < 2*m_perimeter_width ) m_plan[i].depth = this_layer_depth; } - } + + if (m_enable_timelapse_print && layer_index == 0) + max_depth_for_all = m_plan[0].depth; + } + + if (m_enable_timelapse_print) { + for (int i = int(m_plan.size()) - 1; i >= 0; i--) { + m_plan[i].depth = max_depth_for_all; + } + } } void WipeTower::save_on_last_wipe() @@ -1474,17 +1491,25 @@ void WipeTower::generate(std::vector> & // BBS: consider both soluable and support properties int idx = first_toolchange_to_nonsoluble_nonsupport (layer.tool_changes); ToolChangeResult finish_layer_tcr; + ToolChangeResult timelapse_wall; if (idx == -1) { // if there is no toolchange switching to non-soluble, finish layer // will be called at the very beginning. That's the last possibility // where a nonsoluble tool can be. - finish_layer_tcr = finish_layer(); + if (m_enable_timelapse_print) { + timelapse_wall = only_generate_out_wall(); + } + finish_layer_tcr = finish_layer(m_enable_timelapse_print ? false : true); } for (int i=0; i> & layer_result[idx] = merge_tcr(layer_result[idx], finish_layer_tcr); } + if (m_enable_timelapse_print) { + layer_result.insert(layer_result.begin(), std::move(timelapse_wall)); + } + result.emplace_back(std::move(layer_result)); } } +WipeTower::ToolChangeResult WipeTower::only_generate_out_wall() +{ + size_t old_tool = m_current_tool; + + m_extrusion_flow = 0.038f; // hard code + WipeTowerWriter writer(m_layer_height, m_perimeter_width, m_gcode_flavor, m_filpar); + writer.set_extrusion_flow(m_extrusion_flow) + .set_z(m_z_pos) + .set_initial_tool(m_current_tool) + .set_y_shift(m_y_shift - (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f)); + + // Slow down on the 1st layer. + bool first_layer = is_first_layer(); + // BBS: speed up perimeter speed to 90mm/s for non-first layer + float feedrate = first_layer ? std::min(m_first_layer_speed * 60.f, 5400.f) : 5400.f; + float fill_box_y = m_layer_info->toolchanges_depth() + m_perimeter_width; + box_coordinates fill_box(Vec2f(m_perimeter_width, fill_box_y), m_wipe_tower_width - 2 * m_perimeter_width, m_layer_info->depth - fill_box_y); + + writer.set_initial_position((m_left_to_right ? fill_box.ru : fill_box.lu), // so there is never a diagonal travel + m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); + + bool toolchanges_on_layer = m_layer_info->toolchanges_depth() > WT_EPSILON; + + // 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()); + if (writer.y() > fill_box.ld.y() + EPSILON) writer.travel(writer.x(), fill_box.ld.y()); + + // outer perimeter (always): + // BBS + box_coordinates wt_box(Vec2f(0.f, (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f)), m_wipe_tower_width, m_layer_info->depth + m_perimeter_width); + wt_box = align_perimeter(wt_box); + writer.rectangle(wt_box, feedrate); + + // Now prepare future wipe. box contains rectangle that was extruded last (ccw). + Vec2f target = (writer.pos() == wt_box.ld ? wt_box.rd : (writer.pos() == wt_box.rd ? wt_box.ru : (writer.pos() == wt_box.ru ? wt_box.lu : wt_box.ld))); + writer.add_wipe_point(writer.pos()).add_wipe_point(target); + + // Ask our writer about how much material was consumed. + // Skip this in case the layer is sparse and config option to not print sparse layers is enabled. + if (!m_no_sparse_layers || toolchanges_on_layer) + if (m_current_tool < m_used_filament_length.size()) m_used_filament_length[m_current_tool] += writer.get_and_reset_used_filament_length(); + + return construct_tcr(writer, false, old_tool, true, 0.f); +} + } // namespace Slic3r diff --git a/src/libslic3r/GCode/WipeTower.hpp b/src/libslic3r/GCode/WipeTower.hpp index dd652a4649..271e9180f4 100644 --- a/src/libslic3r/GCode/WipeTower.hpp +++ b/src/libslic3r/GCode/WipeTower.hpp @@ -152,6 +152,8 @@ public: // Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result" void generate(std::vector> &result); + WipeTower::ToolChangeResult only_generate_out_wall(); + float get_depth() const { return m_wipe_tower_depth; } float get_brim_width() const { return m_wipe_tower_brim_width_real; } @@ -263,7 +265,7 @@ private: return m_filpar[0].filament_area; // all extruders are assumed to have the same filament diameter at this point } - + bool m_enable_timelapse_print = false; bool m_semm = true; // Are we using a single extruder multimaterial printer? Vec2f m_wipe_tower_pos; // Left front corner of the wipe tower in mm. float m_wipe_tower_width; // Width of the wipe tower. diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index b9aca56de6..4629998021 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -237,8 +237,7 @@ enum class ModelVolumeType : int { NEGATIVE_VOLUME, PARAMETER_MODIFIER, SUPPORT_BLOCKER, - SUPPORT_ENFORCER, - TIMELAPSE_WIPE_TOWER + SUPPORT_ENFORCER }; enum class ModelObjectCutAttribute : int { KeepUpper, KeepLower, FlipLower, CutToParts }; @@ -271,7 +270,6 @@ public: LayerHeightProfile layer_height_profile; // Whether or not this object is printable bool printable; - bool is_timelapse_wipe_tower = false; // This vector holds position of selected support points for SLA. The data are // saved in mesh coordinates to allow using them for several instances. diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 710c74b18d..53d4037012 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -1575,6 +1575,9 @@ void Print::finalize_first_layer_convex_hull() // Wipe tower support. bool Print::has_wipe_tower() const { + if (enable_timelapse_print()) + return true; + return ! m_config.spiral_mode.value && m_config.enable_prime_tower.value && @@ -1589,18 +1592,25 @@ const WipeTowerData& Print::wipe_tower_data(size_t filaments_cnt) const double width = m_config.prime_tower_width; double layer_height = 0.2; // hard code layer height double wipe_volume = m_config.prime_volume; - const_cast(this)->m_wipe_tower_data.depth = wipe_volume * (filaments_cnt - 1) / (layer_height * width); + if (filaments_cnt == 1 && enable_timelapse_print()) { + const_cast(this)->m_wipe_tower_data.depth = wipe_volume / (layer_height * width); + } else { + const_cast(this)->m_wipe_tower_data.depth = wipe_volume * (filaments_cnt - 1) / (layer_height * width); + } const_cast(this)->m_wipe_tower_data.brim_width = m_config.prime_tower_brim_width; } return m_wipe_tower_data; } +bool Print::enable_timelapse_print() const +{ + return m_config.timelapse_no_toolhead.value; +} + void Print::_make_wipe_tower() { m_wipe_tower_data.clear(); - if (! this->has_wipe_tower()) - return; // Get wiping matrix to get number of extruders and convert vector to vector: std::vector flush_matrix(cast(m_config.flush_volumes_matrix.values)); @@ -1616,7 +1626,18 @@ void Print::_make_wipe_tower() // BBS: priming logic is removed, so don't consider it in tool ordering m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, false); - if (! m_wipe_tower_data.tool_ordering.has_wipe_tower()) + // if enable_timelapse_print(), update all layer_tools parameters(has_wipe_tower, wipe_tower_partitions) + if (enable_timelapse_print()) { + std::vector& layer_tools_array = m_wipe_tower_data.tool_ordering.layer_tools(); + for (LayerTools& layer_tools : layer_tools_array) { + layer_tools.has_wipe_tower = true; + if (layer_tools.wipe_tower_partitions == 0) { + layer_tools.wipe_tower_partitions = 1; + } + } + } + + if (!m_wipe_tower_data.tool_ordering.has_wipe_tower()) // Don't generate any wipe tower. return; @@ -1705,6 +1726,11 @@ void Print::_make_wipe_tower() } } layer_tools.wiping_extrusions().ensure_perimeters_infills_order(*this); + + // if enable timelapse, slice all layer + if (enable_timelapse_print()) + continue; + if (&layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0) break; } diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 51554e86c2..b07b6719e6 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -684,6 +684,8 @@ public: const WipeTowerData& wipe_tower_data(size_t filaments_cnt = 0) const; const ToolOrdering& tool_ordering() const { return m_tool_ordering; } + bool enable_timelapse_print() const; + std::string output_filename(const std::string &filename_base = std::string()) const override; size_t num_print_regions() const throw() { return m_print_regions.size(); } diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index b8c5e31d89..5119157366 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -666,8 +666,7 @@ bool PrintObject::invalidate_state_by_config_options( //BBS || opt_key == "adaptive_layer_height" || opt_key == "raft_layers" - || opt_key == "raft_contact_distance" - || opt_key == "timelapse_no_toolhead") { + || opt_key == "raft_contact_distance") { steps.emplace_back(posSlice); } else if ( opt_key == "elefant_foot_compensation" diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index b9f710631c..2eaf09ed83 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -375,7 +375,6 @@ public: bool is_modifier : 1; // Wheter or not this volume has been generated from the wipe tower bool is_wipe_tower : 1; - bool is_timelapse_wipe_tower : 1; // Wheter or not this volume has been generated from an extrusion path bool is_extrusion_path : 1; // Wheter or not to always render this volume using its own alpha diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index aa87ebe6b8..ed83d5f7d6 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -3000,7 +3000,8 @@ void GCodeViewer::load_shells(const Print& print, bool initialized, bool force_p const double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2); const PrintConfig& config = print.config(); - if (extruders_count > 1 && config.enable_prime_tower && (config.print_sequence == PrintSequence::ByLayer)) { + if (print.enable_timelapse_print() + || (extruders_count > 1 && config.enable_prime_tower && (config.print_sequence == PrintSequence::ByLayer))) { const float depth = print.wipe_tower_data(extruders_count).depth; const float brim_width = print.wipe_tower_data(extruders_count).brim_width; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 248ef03591..e8fe125247 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1925,7 +1925,11 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re bool wt = dynamic_cast(m_config->option("enable_prime_tower"))->value; auto co = dynamic_cast*>(m_config->option>("print_sequence")); - if (filaments_count > 1 && wt && co != nullptr && co->value != PrintSequence::ByObject) { + const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config; + const ConfigOption * option = dconfig.option("timelapse_no_toolhead"); + bool timelapse_enabled = option ? option->getBool() : false; + + if (timelapse_enabled || (filaments_count > 1 && wt && co != nullptr && co->value != PrintSequence::ByObject)) { for (int plate_id = 0; plate_id < n_plates; plate_id++) { DynamicPrintConfig& proj_cfg = wxGetApp().preset_bundle->project_config; float x = dynamic_cast(proj_cfg.option("wipe_tower_x"))->get_at(plate_id); @@ -3827,32 +3831,6 @@ void GLCanvas3D::do_scale(const std::string& snapshot_type) } } -#if 1 - // BBS: update Timelapse Wipe Tower according to max height - for (unsigned int obj_idx = 0; obj_idx < (unsigned int) m_model->objects.size(); ++obj_idx) { - ModelObject *model_object = m_model->objects[obj_idx]; - if (model_object->is_timelapse_wipe_tower) { - for (GLVolume *volume : m_volumes.volumes) { - if (volume->composite_id.object_id == obj_idx) { - int instance_idx = volume->instance_idx(); - auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate(); - double max_height = curr_plate->estimate_timelapse_wipe_tower_height(); - float z_factor = max_height / model_object->raw_mesh_bounding_box().size()[2]; - volume->set_instance_scaling_factor(Vec3d(1.0, 1.0, z_factor)); - model_object->instances[instance_idx]->set_scaling_factor(Vec3d(1.0, 1.0, z_factor)); - volume->is_timelapse_wipe_tower = true; - break; - } - } - - ensure_on_bed(obj_idx, false); - model_object->invalidate_bounding_box(); - break; - } - } -#endif - - //BBS: notify instance updates to part plater list m_selection.notify_instance_update(-1, -1); diff --git a/src/slic3r/GUI/GUI_Factories.cpp b/src/slic3r/GUI/GUI_Factories.cpp index a4616f9ad1..4f1bf04917 100644 --- a/src/slic3r/GUI/GUI_Factories.cpp +++ b/src/slic3r/GUI/GUI_Factories.cpp @@ -459,15 +459,6 @@ wxMenu* MenuFactory::append_submenu_add_generic(wxMenu* menu, ModelVolumeType ty [type, item](wxCommandEvent&) { obj_list()->load_generic_subobject(item, type); }, "", menu); } - // BBS: only add timelapse tower item for plate - if (type == ModelVolumeType::INVALID) { - auto item = L("Timelapse Wipe Tower"); - type = ModelVolumeType::TIMELAPSE_WIPE_TOWER; - append_menu_item(sub_menu, wxID_ANY, _(item), "", - [type, item](wxCommandEvent &) { obj_list()->load_generic_subobject(item, type); }, "", menu, - []() { return plater()->can_add_timelapse_wt(); }, m_parent); - } - return sub_menu; } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 0763740fbf..b93c0de6a3 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1869,7 +1869,7 @@ static TriangleMesh create_mesh(const std::string& type_name, const BoundingBoxf const double side = wxGetApp().plater()->canvas3D()->get_size_proportional_to_max_bed_size(0.1); indexed_triangle_set mesh; - if (type_name == "Cube" || type_name == "Timelapse Wipe Tower") + if (type_name == "Cube") // Sitting on the print bed, left front front corner at (0, 0). mesh = its_make_cube(side, side, side); else if (type_name == "Cylinder") @@ -1897,10 +1897,6 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode load_shape_object(type_name); return; } - else if (type == ModelVolumeType::TIMELAPSE_WIPE_TOWER) { - load_shape_object(type_name, true); - return; - } const int obj_idx = get_selected_obj_idx(); if (obj_idx < 0) @@ -2004,7 +2000,7 @@ void ObjectList::load_generic_subobject(const std::string& type_name, const Mode } } -void ObjectList::load_shape_object(const std::string &type_name, bool is_timelapse_wt) +void ObjectList::load_shape_object(const std::string &type_name) { const Selection& selection = wxGetApp().plater()->canvas3D()->get_selection(); //assert(selection.get_object_idx() == -1); // Add nothing is something is selected on 3DScene @@ -2021,11 +2017,11 @@ void ObjectList::load_shape_object(const std::string &type_name, bool is_timelap BoundingBoxf3 bb; TriangleMesh mesh = create_mesh(type_name, bb); // BBS: remove "Shape" prefix - load_mesh_object(mesh, _(type_name), true, is_timelapse_wt); + load_mesh_object(mesh, _(type_name)); wxGetApp().mainframe->update_title(); } -void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center, bool is_timelapse_wt) +void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center) { // Add mesh to model as a new object Model& model = wxGetApp().plater()->model(); @@ -2049,27 +2045,11 @@ void ObjectList::load_mesh_object(const TriangleMesh &mesh, const wxString &name new_object->invalidate_bounding_box(); new_object->translate(-bb.center()); - if (is_timelapse_wt) { - new_object->is_timelapse_wipe_tower = true; - auto curr_plate = wxGetApp().plater()->get_partplate_list().get_curr_plate(); - int highest_extruder = 0; - double max_height = curr_plate->estimate_timelapse_wipe_tower_height(&highest_extruder); - new_object->scale(1, 1, max_height / new_object->bounding_box().size()[2]); + // BBS: find an empty cell to put the copied object + auto start_point = wxGetApp().plater()->build_volume().bounding_volume2d().center(); + auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}); - // move to garbage bin of curr plate - auto offset = curr_plate->get_origin() + Vec3d(80.0, 230.0, -new_object->origin_translation.z()); - new_object->instances[0]->set_offset(offset); - - new_object->config.set_key_value("sparse_infill_density", new ConfigOptionPercent(0)); - new_object->config.set_key_value("top_shell_layers", new ConfigOptionInt(0)); - new_object->config.set("extruder", highest_extruder); - } else { - // BBS: find an empty cell to put the copied object - auto start_point = wxGetApp().plater()->build_volume().bounding_volume2d().center(); - auto empty_cell = wxGetApp().plater()->canvas3D()->get_nearest_empty_cell({start_point(0), start_point(1)}); - - new_object->instances[0]->set_offset(center ? to_3d(Vec2d(empty_cell(0), empty_cell(1)), -new_object->origin_translation.z()) : bb.center()); - } + new_object->instances[0]->set_offset(center ? to_3d(Vec2d(empty_cell(0), empty_cell(1)), -new_object->origin_translation.z()) : bb.center()); new_object->ensure_on_bed(); @@ -2765,11 +2745,6 @@ bool ObjectList::can_merge_to_multipart_object() const for (wxDataViewItem item : sels) { if (!(m_objects_model->GetItemType(item) & (itObject | itInstance))) return false; - - // BBS: do not support to merge timelapse wipe tower with other objects - ObjectDataViewModelNode* node = static_cast(item.GetID()); - if (node != nullptr && node->IsTimelapseWipeTower()) - return false; } return true; diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index 2387142728..dac2698469 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -279,8 +279,8 @@ public: //void load_part(ModelObject& model_object, std::vector& added_volumes, ModelVolumeType type, bool from_galery = false); void load_modifier(const wxArrayString& input_files, ModelObject& model_object, std::vector& added_volumes, ModelVolumeType type, bool from_galery = false); void load_generic_subobject(const std::string& type_name, const ModelVolumeType type); - void load_shape_object(const std::string &type_name, bool is_timelapse_wt = false); - void load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center = true, bool is_timelapse_wt = false); + void load_shape_object(const std::string &type_name); + void load_mesh_object(const TriangleMesh &mesh, const wxString &name, bool center = true); void del_object(const int obj_idx, bool refresh_immediately = true); void del_subobject_item(wxDataViewItem& item); void del_settings_from_config(const wxDataViewItem& parent_item); diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index 12aa398b69..73e2847898 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -333,18 +333,6 @@ void ObjectDataViewModelNode::SetPlateIdx(const int& idx) m_plate_idx = idx; } -// BBS -bool ObjectDataViewModelNode::IsTimelapseWipeTower() const -{ - if (m_model_object == nullptr) - return false; - - if (!(m_type & itObject) && !(m_type & itInstance)) - return false; - - return m_model_object->is_timelapse_wipe_tower; -} - void ObjectDataViewModelNode::UpdateExtruderAndColorIcon(wxString extruder /*= ""*/) { if (m_type == itVolume && m_volume_type != ModelVolumeType::MODEL_PART && m_volume_type != ModelVolumeType::PARAMETER_MODIFIER) diff --git a/src/slic3r/GUI/ObjectDataViewModel.hpp b/src/slic3r/GUI/ObjectDataViewModel.hpp index 24aa993686..749edae4b4 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.hpp +++ b/src/slic3r/GUI/ObjectDataViewModel.hpp @@ -227,7 +227,6 @@ public: bool HasSupportPainting() const { return m_support_enable; } bool IsActionEnabled() const { return m_action_enable; } void UpdateExtruderAndColorIcon(wxString extruder = ""); - bool IsTimelapseWipeTower() const; // use this function only for childrens void AssignAllVal(ObjectDataViewModelNode& from_node) diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index 8e240b04e2..1dd4eddc34 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -1103,8 +1103,12 @@ Vec3d PartPlate::estimate_wipe_tower_size(const double w, const double wipe_volu } wipe_tower_size(2) = max_height; + const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config; + const ConfigOption* option = dconfig.option("timelapse_no_toolhead"); + bool timelapse_enabled = option ? option->getBool() : false; + double depth = wipe_volume * (plate_extruders.size() - 1) / (layer_height * w); - if (depth > EPSILON) { + if (timelapse_enabled || depth > EPSILON) { float min_wipe_tower_depth = 0.f; auto iter = WipeTower::min_depth_per_height.begin(); while (iter != WipeTower::min_depth_per_height.end()) { @@ -1142,26 +1146,6 @@ Vec3d PartPlate::estimate_wipe_tower_size(const double w, const double wipe_volu return wipe_tower_size; } -double PartPlate::estimate_timelapse_wipe_tower_height(int *highest_extruder_id) const -{ - double max_height = 0; - int highest_extruder = 0; - - // auto m_model = wxGetApp().plater()->get_obj - for (int obj_idx = 0; obj_idx < m_model->objects.size(); obj_idx++) { - if (!contain_instance_totally(obj_idx, 0)) continue; - if (m_model->objects[obj_idx]->is_timelapse_wipe_tower) continue; - - BoundingBoxf3 bbox = m_model->objects[obj_idx]->bounding_box(); - if (bbox.size().z() > max_height) { - max_height = bbox.size().z(); - highest_extruder = m_model->objects[obj_idx]->config.opt_int("extruder"); - } - } - if (highest_extruder_id) *highest_extruder_id = highest_extruder; - return max_height; -} - bool PartPlate::operator<(PartPlate& plate) const { int index = plate.get_index(); @@ -1636,33 +1620,6 @@ void PartPlate::move_instances_to(PartPlate& left_plate, PartPlate& right_plate, return; } -//can add timelapse object -bool PartPlate::can_add_timelapse_object() -{ - bool result = true; - - if (obj_to_instance_set.size() == 0) - return false; - - for (std::set>::iterator it = obj_to_instance_set.begin(); it != obj_to_instance_set.end(); ++it) - { - int obj_id = it->first; - - if (obj_id >= m_model->objects.size()) - continue; - - ModelObject* object = m_model->objects[obj_id]; - - if (object->is_timelapse_wipe_tower) - { - result = false; - break; - } - } - - return result; -} - void PartPlate::generate_logo_polygon(ExPolygon &logo_polygon) { if (m_shape.size() == 4) diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 8dbff320a9..4bfc35d6c7 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -238,7 +238,6 @@ public: Vec3d get_origin() { return m_origin; } Vec3d estimate_wipe_tower_size(const double w, const double wipe_volume) const; - double estimate_timelapse_wipe_tower_height(int* highest_extruder_id=NULL) const; std::vector get_extruders() const; /* instance related operations*/ @@ -278,9 +277,6 @@ public: //move instances to left or right PartPlate void move_instances_to(PartPlate& left_plate, PartPlate& right_plate, BoundingBoxf3* bounding_box = nullptr); - //can add timelapse object - bool can_add_timelapse_object(); - /*rendering related functions*/ const Pointfs& get_shape() const { return m_shape; } bool set_shape(const Pointfs& shape, const Pointfs& exclude_areas, Vec2d position, float height_to_lid, float height_to_rod); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e420a87a08..460e4f8a5c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1785,7 +1785,6 @@ struct Plater::priv // Sets m_bed.m_polygon to limit the object placement. //BBS: add bed exclude area void set_bed_shape(const Pointfs& shape, const Pointfs& exclude_areas, const double printable_height, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false); - bool can_add_timelapse_wt() const; bool can_delete() const; bool can_delete_all() const; @@ -5930,16 +5929,6 @@ void Plater::priv::set_bed_shape(const Pointfs& shape, const Pointfs& exclude_ar } } -bool Plater::priv::can_add_timelapse_wt() const { - const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config; - const ConfigOption* option = dconfig.option("timelapse_no_toolhead"); - bool timelapse_enabled = option?option->getBool():false; - - PartPlate* curr_plate = q->get_partplate_list().get_curr_plate(); - - return timelapse_enabled && curr_plate->can_add_timelapse_object(); -} - bool Plater::priv::can_delete() const { return !get_selection().is_empty() && !get_selection().is_wipe_tower(); @@ -9836,7 +9825,6 @@ void Plater::show_status_message(std::string s) BOOST_LOG_TRIVIAL(trace) << "show_status_message:" << s; } -bool Plater::can_add_timelapse_wt() const { return p->can_add_timelapse_wt(); } // BBS bool Plater::can_delete() const { return p->can_delete(); } bool Plater::can_delete_all() const { return p->can_delete_all(); } bool Plater::can_add_model() const { return !is_background_process_slicing(); } diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 5fb45dfa3c..0af6643cab 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -417,7 +417,6 @@ public: //BBS: void fill_color(int extruder_id); - bool can_add_timelapse_wt() const; bool can_delete() const; bool can_delete_all() const; diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index ebe3eca71c..5920bc4a35 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1374,11 +1374,9 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value) if (opt_key == "enable_prime_tower" || opt_key == "single_extruder_multi_material" || opt_key == "extruders_count" ) update_wiping_button_visibility(); - //popup message dialog when first selected - if (opt_key == "timelapse_no_toolhead" && boost::any_cast(value)) - show_timelapse_warning_dialog(); - - + // reload scene to update timelapse wipe tower + if (opt_key == "timelapse_no_toolhead") + wxGetApp().plater()->update(); // BBS #if 0