mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	SPE-1103 Added menu items for the conversation of the volumes from/to meters
Related to #4521
This commit is contained in:
		
							parent
							
								
									8049dd1f72
								
							
						
					
					
						commit
						e664100bf6
					
				
					 8 changed files with 84 additions and 42 deletions
				
			
		|  | @ -115,6 +115,7 @@ static constexpr const char* SOURCE_OFFSET_X_KEY = "source_offset_x"; | |||
| static constexpr const char* SOURCE_OFFSET_Y_KEY = "source_offset_y"; | ||||
| static constexpr const char* SOURCE_OFFSET_Z_KEY = "source_offset_z"; | ||||
| static constexpr const char* SOURCE_IN_INCHES    = "source_in_inches"; | ||||
| static constexpr const char* SOURCE_IN_METERS    = "source_in_meters"; | ||||
| 
 | ||||
| const unsigned int VALID_OBJECT_TYPES_COUNT = 1; | ||||
| const char* VALID_OBJECT_TYPES[] = | ||||
|  | @ -1913,6 +1914,8 @@ namespace Slic3r { | |||
|                     volume->source.mesh_offset(2) = ::atof(metadata.value.c_str()); | ||||
|                 else if (metadata.key == SOURCE_IN_INCHES) | ||||
|                     volume->source.is_converted_from_inches = metadata.value == "1"; | ||||
|                 else if (metadata.key == SOURCE_IN_METERS) | ||||
|                     volume->source.is_converted_from_meters = metadata.value == "1"; | ||||
|                 else | ||||
|                     volume->config.set_deserialize(metadata.key, metadata.value); | ||||
|             } | ||||
|  | @ -2822,6 +2825,8 @@ namespace Slic3r { | |||
|                                 } | ||||
|                                 if (volume->source.is_converted_from_inches) | ||||
|                                     stream << prefix << SOURCE_IN_INCHES << "\" " << VALUE_ATTR << "=\"1\"/>\n"; | ||||
|                                 if (volume->source.is_converted_from_meters) | ||||
|                                     stream << prefix << SOURCE_IN_METERS << "\" " << VALUE_ATTR << "=\"1\"/>\n"; | ||||
|                             } | ||||
| 
 | ||||
|                             // stores volume's config data
 | ||||
|  |  | |||
|  | @ -798,6 +798,9 @@ void AMFParserContext::endElement(const char * /* name */) | |||
|                 else if (strcmp(opt_key, "source_in_inches") == 0) { | ||||
|                     m_volume->source.is_converted_from_inches = m_value[1] == "1"; | ||||
|                 } | ||||
|                 else if (strcmp(opt_key, "source_in_meters") == 0) { | ||||
|                     m_volume->source.is_converted_from_meters = m_value[1] == "1"; | ||||
|                 } | ||||
|             } | ||||
|         } else if (m_path.size() == 3) { | ||||
|             if (m_path[1] == NODE_TYPE_MATERIAL) { | ||||
|  | @ -1232,6 +1235,8 @@ bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config, | |||
|             } | ||||
|             if (volume->source.is_converted_from_inches) | ||||
|                 stream << "        <metadata type=\"slic3r.source_in_inches\">1</metadata>\n"; | ||||
|             if (volume->source.is_converted_from_meters) | ||||
|                 stream << "        <metadata type=\"slic3r.source_in_meters\">1</metadata>\n"; | ||||
| 			stream << std::setprecision(std::numeric_limits<float>::max_digits10); | ||||
|             const indexed_triangle_set &its = volume->mesh().its; | ||||
|             for (size_t i = 0; i < its.indices.size(); ++i) { | ||||
|  |  | |||
|  | @ -491,7 +491,7 @@ void Model::convert_from_meters(bool only_small_volumes) | |||
|         if (! only_small_volumes || obj->get_object_stl_stats().volume < 0.001) { // 0.001 = 0.1*0.1*0.1;
 | ||||
|             obj->scale_mesh_after_creation(Vec3d(m_to_mm, m_to_mm, m_to_mm)); | ||||
|             for (ModelVolume* v : obj->volumes) | ||||
|                 v->source.is_converted_from_inches = true; | ||||
|                 v->source.is_converted_from_meters = true; | ||||
|         } | ||||
| } | ||||
| 
 | ||||
|  | @ -1046,13 +1046,14 @@ void ModelObject::scale_mesh_after_creation(const Vec3d &versor) | |||
|     this->invalidate_bounding_box(); | ||||
| } | ||||
| 
 | ||||
| void ModelObject::convert_units(ModelObjectPtrs& new_objects, bool from_imperial, std::vector<int> volume_idxs) | ||||
| void ModelObject::convert_units(ModelObjectPtrs& new_objects, ConversionType conv_type, std::vector<int> volume_idxs) | ||||
| { | ||||
|     BOOST_LOG_TRIVIAL(trace) << "ModelObject::convert_units - start"; | ||||
| 
 | ||||
|     ModelObject* new_object = new_clone(*this); | ||||
| 
 | ||||
|     double koef = from_imperial ? 25.4 : 0.0393700787; | ||||
|     double koef = conv_type == ConversionType::CONV_FROM_INCH   ? 25.4 : conv_type == ConversionType::CONV_TO_INCH  ? 0.0393700787  : | ||||
|                   conv_type == ConversionType::CONV_FROM_METER  ? 1000 : conv_type == ConversionType::CONV_TO_METER ? 0.001         : 1; | ||||
|     const Vec3d versor = Vec3d(koef, koef, koef); | ||||
| 
 | ||||
|     new_object->set_model(nullptr); | ||||
|  | @ -1080,6 +1081,8 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, bool from_imperial | |||
|             vol->source.input_file = volume->source.input_file; | ||||
|             vol->source.object_idx = (int)new_objects.size(); | ||||
|             vol->source.volume_idx = vol_idx; | ||||
|             vol->source.is_converted_from_inches = volume->source.is_converted_from_inches; | ||||
|             vol->source.is_converted_from_meters = volume->source.is_converted_from_meters; | ||||
| 
 | ||||
|             vol->supported_facets.assign(volume->supported_facets); | ||||
|             vol->seam_facets.assign(volume->seam_facets); | ||||
|  | @ -1091,7 +1094,10 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, bool from_imperial | |||
|                  std::find(volume_idxs.begin(), volume_idxs.end(), vol_idx) != volume_idxs.end())) { | ||||
|                 vol->scale_geometry_after_creation(versor); | ||||
|                 vol->set_offset(versor.cwiseProduct(volume->get_offset())); | ||||
|                 vol->source.is_converted_from_inches = from_imperial; | ||||
|                 if (conv_type == ConversionType::CONV_FROM_INCH || conv_type == ConversionType::CONV_TO_INCH) | ||||
|                     vol->source.is_converted_from_inches = conv_type == ConversionType::CONV_FROM_INCH; | ||||
|                 if (conv_type == ConversionType::CONV_FROM_METER || conv_type == ConversionType::CONV_TO_METER) | ||||
|                     vol->source.is_converted_from_meters = conv_type == ConversionType::CONV_FROM_METER; | ||||
|             } | ||||
|             else | ||||
|                 vol->set_offset(volume->get_offset()); | ||||
|  | @ -1841,6 +1847,14 @@ void ModelVolume::convert_from_imperial_units() | |||
|     this->source.is_converted_from_inches = true; | ||||
| } | ||||
| 
 | ||||
| void ModelVolume::convert_from_meters() | ||||
| { | ||||
|     double m_to_mm = 1000; | ||||
|     this->scale_geometry_after_creation(Vec3d(m_to_mm, m_to_mm, m_to_mm)); | ||||
|     this->set_offset(Vec3d(0, 0, 0)); | ||||
|     this->source.is_converted_from_meters = true; | ||||
| } | ||||
| 
 | ||||
| void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const | ||||
| { | ||||
|     mesh->transform(get_matrix(dont_translate)); | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ namespace cereal { | |||
| } | ||||
| 
 | ||||
| namespace Slic3r { | ||||
| enum class ConversionType; | ||||
| 
 | ||||
| class Model; | ||||
| class ModelInstance; | ||||
|  | @ -325,7 +326,7 @@ public: | |||
| 
 | ||||
|     // This method could only be called before the meshes of this ModelVolumes are not shared!
 | ||||
|     void scale_mesh_after_creation(const Vec3d& versor); | ||||
|     void convert_units(ModelObjectPtrs&new_objects, bool from_imperial, std::vector<int> volume_idxs); | ||||
|     void convert_units(ModelObjectPtrs&new_objects, ConversionType conv_type, std::vector<int> volume_idxs); | ||||
| 
 | ||||
|     size_t materials_count() const; | ||||
|     size_t facets_count() const; | ||||
|  | @ -495,6 +496,13 @@ enum class EnforcerBlockerType : int8_t { | |||
|     BLOCKER   = 2 | ||||
| }; | ||||
| 
 | ||||
| enum class ConversionType : int { | ||||
|     CONV_TO_INCH, | ||||
|     CONV_FROM_INCH, | ||||
|     CONV_TO_METER, | ||||
|     CONV_FROM_METER, | ||||
| }; | ||||
| 
 | ||||
| class FacetsAnnotation final : public ObjectWithTimestamp { | ||||
| public: | ||||
|     // Assign the content if the timestamp differs, don't assign an ObjectID.
 | ||||
|  | @ -553,11 +561,12 @@ public: | |||
|         Vec3d mesh_offset{ Vec3d::Zero() }; | ||||
|         Geometry::Transformation transform; | ||||
|         bool is_converted_from_inches = false; | ||||
|         bool is_converted_from_meters = false; | ||||
| 
 | ||||
|         template<class Archive> void serialize(Archive& ar) {  | ||||
|             //FIXME Vojtech: Serialize / deserialize only if the Source is set.
 | ||||
|             // likely testing input_file or object_idx would be sufficient.
 | ||||
|             ar(input_file, object_idx, volume_idx, mesh_offset, transform, is_converted_from_inches); | ||||
|             ar(input_file, object_idx, volume_idx, mesh_offset, transform, is_converted_from_inches, is_converted_from_meters); | ||||
|         } | ||||
|     }; | ||||
|     Source              source; | ||||
|  | @ -657,6 +666,7 @@ public: | |||
|     void set_mirror(const Vec3d& mirror) { m_transformation.set_mirror(mirror); } | ||||
|     void set_mirror(Axis axis, double mirror) { m_transformation.set_mirror(axis, mirror); } | ||||
|     void convert_from_imperial_units(); | ||||
|     void convert_from_meters(); | ||||
| 
 | ||||
|     const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1023,7 +1023,7 @@ void ObjectList::show_context_menu(const bool evt_context_menu) | |||
|                        printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object; | ||||
| 
 | ||||
|         if (type & (itObject | itVolume)) | ||||
|             append_menu_item_convert_unit(menu); | ||||
|             append_menu_items_convert_unit(menu); | ||||
|         if (!(type & itInstance)) | ||||
|             append_menu_item_settings(menu); | ||||
|     } | ||||
|  | @ -1906,56 +1906,59 @@ void ObjectList::append_menu_item_scale_selection_to_fit_print_volume(wxMenu* me | |||
|         [](wxCommandEvent&) { wxGetApp().plater()->scale_selection_to_fit_print_volume(); }, "", menu); | ||||
| } | ||||
| 
 | ||||
| void ObjectList::append_menu_item_convert_unit(wxMenu* menu, int insert_pos/* = 1*/) | ||||
| void ObjectList::append_menu_items_convert_unit(wxMenu* menu, int insert_pos/* = 1*/) | ||||
| { | ||||
|     std::vector<int> obj_idxs, vol_idxs; | ||||
|     get_selection_indexes(obj_idxs, vol_idxs); | ||||
|     if (obj_idxs.empty() && vol_idxs.empty()) | ||||
|         return; | ||||
| 
 | ||||
|     auto can_append = [this, obj_idxs, vol_idxs](bool from_imperial_unit) { | ||||
|     auto volume_respects_conversion = [](ModelVolume* volume, ConversionType conver_type) | ||||
|     { | ||||
|         return  (conver_type == ConversionType::CONV_FROM_INCH  &&  volume->source.is_converted_from_inches) || | ||||
|                 (conver_type == ConversionType::CONV_TO_INCH    && !volume->source.is_converted_from_inches) || | ||||
|                 (conver_type == ConversionType::CONV_FROM_METER &&  volume->source.is_converted_from_meters) || | ||||
|                 (conver_type == ConversionType::CONV_TO_METER   && !volume->source.is_converted_from_meters); | ||||
|     }; | ||||
| 
 | ||||
|     auto can_append = [this, obj_idxs, vol_idxs, volume_respects_conversion](ConversionType conver_type) | ||||
|     { | ||||
|         ModelObjectPtrs objects; | ||||
|         for (int obj_idx : obj_idxs) { | ||||
|             ModelObject* object = (*m_objects)[obj_idx]; | ||||
|             if (vol_idxs.empty()) { | ||||
|                 for (ModelVolume* volume : object->volumes) | ||||
|                     if (volume->source.is_converted_from_inches == from_imperial_unit) | ||||
|                     if (volume_respects_conversion(volume, conver_type)) | ||||
|                         return false; | ||||
|             } | ||||
|             else { | ||||
|                 for (int vol_idx : vol_idxs) | ||||
|                     if (object->volumes[vol_idx]->source.is_converted_from_inches == from_imperial_unit) | ||||
|                     if (volume_respects_conversion(object->volumes[vol_idx], conver_type)) | ||||
|                         return false; | ||||
|             } | ||||
|         } | ||||
|         return true; | ||||
|     }; | ||||
| 
 | ||||
|     wxString convert_menu_name = _L("Convert from imperial units"); | ||||
|     int      convert_menu_id   = menu->FindItem(convert_menu_name); | ||||
|     wxString revert_menu_name  = _L("Revert conversion from imperial units"); | ||||
|     int      revert_menu_id    = menu->FindItem(revert_menu_name); | ||||
|     std::vector<std::pair<ConversionType, wxString>> items = { | ||||
|         {ConversionType::CONV_FROM_INCH , _L("Convert from imperial units") }, | ||||
|         {ConversionType::CONV_TO_INCH   , _L("Revert conversion from imperial units") }, | ||||
|         {ConversionType::CONV_FROM_METER, _L("Convert from meters") }, | ||||
|         {ConversionType::CONV_TO_METER  , _L("Revert conversion from meters") } }; | ||||
| 
 | ||||
|     if (can_append(true)) { | ||||
|         // Delete revert menu item
 | ||||
|         if (revert_menu_id != wxNOT_FOUND) | ||||
|             menu->Destroy(revert_menu_id); | ||||
|         // Add convert menu item if it doesn't exist
 | ||||
|         if (convert_menu_id == wxNOT_FOUND) | ||||
|             append_menu_item(menu, wxID_ANY, convert_menu_name, convert_menu_name, | ||||
|                 [](wxCommandEvent&) { wxGetApp().plater()->convert_unit(true); }, "", menu,  | ||||
|                 []() {return true;}, nullptr, insert_pos); | ||||
|     } | ||||
| 
 | ||||
|     if (can_append(false)) { | ||||
|         // Delete convert menu item
 | ||||
|         if (convert_menu_id != wxNOT_FOUND) | ||||
|             menu->Destroy(convert_menu_id); | ||||
|         // Add convert menu item if it doesn't exist
 | ||||
|         if (revert_menu_id == wxNOT_FOUND) | ||||
|             append_menu_item(menu, wxID_ANY, revert_menu_name, revert_menu_name, | ||||
|                 [](wxCommandEvent&) { wxGetApp().plater()->convert_unit(false); }, "", menu, | ||||
|                 []() {return true;}, nullptr, insert_pos); | ||||
|     for (auto item : items) { | ||||
|         int menu_id = menu->FindItem(item.second); | ||||
|         if (can_append(item.first)) { | ||||
|             // Add menu item if it doesn't exist
 | ||||
|             if (menu_id == wxNOT_FOUND) | ||||
|                 append_menu_item(menu, wxID_ANY, item.second, item.second, | ||||
|                     [item](wxCommandEvent&) { wxGetApp().plater()->convert_unit(item.first); }, "", menu, | ||||
|                     []() {return true; }, nullptr, insert_pos); | ||||
|         } | ||||
|         else if (menu_id != wxNOT_FOUND) { | ||||
|             // Delete menu item
 | ||||
|             menu->Destroy(menu_id); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -4606,7 +4609,7 @@ void ObjectList::show_multi_selection_menu() | |||
|         return wxGetApp().plater()->can_reload_from_disk(); | ||||
|     }, wxGetApp().plater()); | ||||
| 
 | ||||
|     append_menu_item_convert_unit(menu); | ||||
|     append_menu_items_convert_unit(menu); | ||||
|     if (can_merge_to_multipart_object()) | ||||
|         append_menu_item_merge_to_multipart_object(menu); | ||||
| 
 | ||||
|  |  | |||
|  | @ -284,7 +284,7 @@ public: | |||
|     void                append_menu_item_change_extruder(wxMenu* menu); | ||||
|     void                append_menu_item_delete(wxMenu* menu); | ||||
|     void                append_menu_item_scale_selection_to_fit_print_volume(wxMenu* menu); | ||||
|     void                append_menu_item_convert_unit(wxMenu* menu, int insert_pos = 1); // Add "Conver/Revert..." menu item after "Reload From Disk"
 | ||||
|     void                append_menu_items_convert_unit(wxMenu* menu, int insert_pos = 1); // Add "Conver/Revert..." menu items (from/to inches/meters) after "Reload From Disk"
 | ||||
|     void                append_menu_item_merge_to_multipart_object(wxMenu *menu); | ||||
|     void                append_menu_item_merge_to_single_object(wxMenu *menu); | ||||
|     void                create_object_popupmenu(wxMenu *menu); | ||||
|  |  | |||
|  | @ -3329,6 +3329,8 @@ void Plater::priv::reload_from_disk() | |||
|                     new_volume->translate(new_volume->get_transformation().get_matrix(true) * (new_volume->source.mesh_offset - old_volume->source.mesh_offset)); | ||||
|                     if (old_volume->source.is_converted_from_inches) | ||||
|                         new_volume->convert_from_imperial_units(); | ||||
|                     if (old_volume->source.is_converted_from_meters) | ||||
|                         new_volume->convert_from_meters(); | ||||
|                     new_volume->supported_facets.assign(old_volume->supported_facets); | ||||
|                     new_volume->seam_facets.assign(old_volume->seam_facets); | ||||
|                     std::swap(old_model_object->volumes[sel_v.volume_idx], old_model_object->volumes.back()); | ||||
|  | @ -3871,7 +3873,7 @@ void Plater::priv::on_right_click(RBtnEvent& evt) | |||
|                 menu_item_convert_unit_position = 2; | ||||
|         } | ||||
| 
 | ||||
|         sidebar->obj_list()->append_menu_item_convert_unit(menu, menu_item_convert_unit_position); | ||||
|         sidebar->obj_list()->append_menu_items_convert_unit(menu, menu_item_convert_unit_position); | ||||
|         sidebar->obj_list()->append_menu_item_settings(menu); | ||||
| 
 | ||||
|         if (printer_technology != ptSLA) | ||||
|  | @ -5246,20 +5248,22 @@ void Plater::scale_selection_to_fit_print_volume() | |||
|     p->scale_selection_to_fit_print_volume(); | ||||
| } | ||||
| 
 | ||||
| void Plater::convert_unit(bool from_imperial_unit) | ||||
| void Plater::convert_unit(ConversionType conv_type) | ||||
| { | ||||
|     std::vector<int> obj_idxs, volume_idxs; | ||||
|     wxGetApp().obj_list()->get_selection_indexes(obj_idxs, volume_idxs); | ||||
|     if (obj_idxs.empty() && volume_idxs.empty()) | ||||
|         return; | ||||
| 
 | ||||
|     TakeSnapshot snapshot(this, from_imperial_unit ? _L("Convert from imperial units") : _L("Revert conversion from imperial units")); | ||||
|     TakeSnapshot snapshot(this, conv_type == ConversionType::CONV_FROM_INCH  ? _L("Convert from imperial units") : | ||||
|                                 conv_type == ConversionType::CONV_TO_INCH    ? _L("Revert conversion from imperial units") : | ||||
|                                 conv_type == ConversionType::CONV_FROM_METER ? _L("Convert from meters") : _L("Revert conversion from meters")); | ||||
|     wxBusyCursor wait; | ||||
| 
 | ||||
|     ModelObjectPtrs objects; | ||||
|     for (int obj_idx : obj_idxs) { | ||||
|         ModelObject *object = p->model.objects[obj_idx]; | ||||
|         object->convert_units(objects, from_imperial_unit, volume_idxs); | ||||
|         object->convert_units(objects, conv_type, volume_idxs); | ||||
|         remove(obj_idx); | ||||
|     } | ||||
|     p->load_model_objects(objects); | ||||
|  |  | |||
|  | @ -28,6 +28,7 @@ class ModelInstance; | |||
| class Print; | ||||
| class SLAPrint; | ||||
| enum SLAPrintObjectStep : unsigned int; | ||||
| enum class ConversionType : int; | ||||
| 
 | ||||
| using ModelInstancePtrs = std::vector<ModelInstance*>; | ||||
| 
 | ||||
|  | @ -191,7 +192,7 @@ public: | |||
|     void fill_bed_with_instances(); | ||||
|     bool is_selection_empty() const; | ||||
|     void scale_selection_to_fit_print_volume(); | ||||
|     void convert_unit(bool from_imperial_unit); | ||||
|     void convert_unit(ConversionType conv_type); | ||||
| 
 | ||||
|     void cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 YuSanka
						YuSanka