mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	ENH: Optimize and design the time-lapse wiper tower
Multiplex existing wipe tower and revert old time-lapse wipe tower code Change-Id: Ia1cba9808647ea900f691b2c5d5887077be12d89 (cherry picked from commit 61f41df572d11b7cc738c34f2624fd123cd9a6df)
This commit is contained in:
		
							parent
							
								
									a26c573b1b
								
							
						
					
					
						commit
						f745c5fea2
					
				
					 21 changed files with 172 additions and 183 deletions
				
			
		|  | @ -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
 | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1925,7 +1925,11 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re | |||
|         bool wt = dynamic_cast<const ConfigOptionBool*>(m_config->option("enable_prime_tower"))->value; | ||||
|         auto co = dynamic_cast<const ConfigOptionEnum<PrintSequence>*>(m_config->option<ConfigOptionEnum<PrintSequence>>("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<const ConfigOptionFloats*>(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); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<ObjectDataViewModelNode*>(item.GetID()); | ||||
|         if (node != nullptr && node->IsTimelapseWipeTower()) | ||||
|             return false; | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
|  |  | |||
|  | @ -279,8 +279,8 @@ public: | |||
|     //void                load_part(ModelObject& model_object, std::vector<ModelVolume*>& added_volumes, ModelVolumeType type, bool from_galery = false);
 | ||||
|     void                load_modifier(const wxArrayString& input_files, ModelObject& model_object, std::vector<ModelVolume*>& 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); | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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<std::pair<int, int>>::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) | ||||
|  |  | |||
|  | @ -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<int> 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); | ||||
|  |  | |||
|  | @ -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(); } | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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<bool>(value)) | ||||
|         show_timelapse_warning_dialog(); | ||||
|      | ||||
| 
 | ||||
|     // reload scene to update timelapse wipe tower
 | ||||
|     if (opt_key == "timelapse_no_toolhead") | ||||
|         wxGetApp().plater()->update(); | ||||
| 
 | ||||
|     // BBS
 | ||||
| #if 0 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 zhimin.zeng
						zhimin.zeng