diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 5887931df..b492fa01d 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -465,8 +465,11 @@ void Model::convert_from_imperial_units() { double in_to_mm = 25.4; for (ModelObject* obj : this->objects) - if (obj->get_object_stl_stats().volume < 9.0) // 9 = 3*3*3; + if (obj->get_object_stl_stats().volume < 9.0) { // 9 = 3*3*3; obj->scale_mesh_after_creation(Vec3d(in_to_mm, in_to_mm, in_to_mm)); + for (ModelVolume* v : obj->volumes) + v->source.is_converted_from_inches = true; + } } void Model::adjust_min_z() @@ -1053,12 +1056,16 @@ void ModelObject::convert_units(ModelObjectPtrs& new_objects, bool from_imperial assert(vol->config.id().valid()); assert(vol->config.id() != volume->config.id()); vol->set_material(volume->material_id(), *volume->material()); + vol->source.input_file = volume->source.input_file; + vol->source.object_idx = (int)new_objects.size(); + vol->source.volume_idx = vol_idx; // Perform conversion if (volume_idxs.empty() || 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; } else vol->set_offset(volume->get_offset()); @@ -1798,6 +1805,14 @@ void ModelVolume::transform_this_mesh(const Matrix3d &matrix, bool fix_left_hand this->set_new_unique_id(); } +void ModelVolume::convert_from_imperial_units() +{ + double in_to_mm = 25.4; + this->scale_geometry_after_creation(Vec3d(in_to_mm, in_to_mm, in_to_mm)); + this->set_offset(Vec3d(0, 0, 0)); + this->source.is_converted_from_inches = true; +} + void ModelInstance::transform_mesh(TriangleMesh* mesh, bool dont_translate) const { mesh->transform(get_matrix(dont_translate)); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index c2965f60c..c10e304c3 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -552,11 +552,12 @@ public: int volume_idx{ -1 }; Vec3d mesh_offset{ Vec3d::Zero() }; Geometry::Transformation transform; + bool is_converted_from_inches = false; template 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); + ar(input_file, object_idx, volume_idx, mesh_offset, transform, is_converted_from_inches); } }; Source source; @@ -655,6 +656,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(); 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); } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 0229962ea..f0c23f1d4 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1005,6 +1005,8 @@ void ObjectList::show_context_menu(const bool evt_context_menu) m_objects_model->GetParent(item) != wxDataViewItem(nullptr) ? &m_menu_part : printer_technology() == ptFFF ? &m_menu_object : &m_menu_sla_object; + if (type & (itObject | itVolume)) + append_menu_item_convert_unit(menu); if (!(type & itInstance)) append_menu_item_settings(menu); } @@ -1883,13 +1885,57 @@ 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_items_convert_unit(wxMenu* menu) +void ObjectList::append_menu_item_convert_unit(wxMenu* menu, int insert_pos/* = 1*/) { - append_menu_item(menu, wxID_ANY, _L("Convert from imperial units"), _L("Convert from imperial units"), - [](wxCommandEvent&) { wxGetApp().plater()->convert_unit(true); }, "", menu); + std::vector obj_idxs, vol_idxs; + get_selection_indexes(obj_idxs, vol_idxs); + if (obj_idxs.empty() && vol_idxs.empty()) + return; - append_menu_item(menu, wxID_ANY, _L("Revert conversion from imperial units"), _L("Revert conversion from imperial units"), - [](wxCommandEvent&) { wxGetApp().plater()->convert_unit(false); }, "", menu); + auto can_append = [this, obj_idxs, vol_idxs](bool from_imperial_unit) { + 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) + return false; + } + else { + for (int vol_idx : vol_idxs) + if (object->volumes[vol_idx]->source.is_converted_from_inches == from_imperial_unit) + 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); + + 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); + } } void ObjectList::append_menu_item_merge_to_multipart_object(wxMenu* menu) @@ -1915,7 +1961,6 @@ void ObjectList::create_object_popupmenu(wxMenu *menu) #endif // __WXOSX__ append_menu_item_reload_from_disk(menu); - append_menu_items_convert_unit(menu); append_menu_item_export_stl(menu); append_menu_item_fix_through_netfabb(menu); append_menu_item_scale_selection_to_fit_print_volume(menu); @@ -1944,7 +1989,6 @@ void ObjectList::create_sla_object_popupmenu(wxMenu *menu) #endif // __WXOSX__ append_menu_item_reload_from_disk(menu); - append_menu_items_convert_unit(menu); append_menu_item_export_stl(menu); append_menu_item_fix_through_netfabb(menu); // rest of a object_sla_menu will be added later in: @@ -1958,7 +2002,6 @@ void ObjectList::create_part_popupmenu(wxMenu *menu) #endif // __WXOSX__ append_menu_item_reload_from_disk(menu); - append_menu_items_convert_unit(menu); append_menu_item_export_stl(menu); append_menu_item_fix_through_netfabb(menu); @@ -4526,7 +4569,7 @@ void ObjectList::show_multi_selection_menu() return wxGetApp().plater()->can_reload_from_disk(); }, wxGetApp().plater()); - append_menu_items_convert_unit(menu); + append_menu_item_convert_unit(menu); if (can_merge_to_multipart_object()) append_menu_item_merge_to_multipart_object(menu); diff --git a/src/slic3r/GUI/GUI_ObjectList.hpp b/src/slic3r/GUI/GUI_ObjectList.hpp index aaea78339..52aefe0e6 100644 --- a/src/slic3r/GUI/GUI_ObjectList.hpp +++ b/src/slic3r/GUI/GUI_ObjectList.hpp @@ -281,7 +281,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_items_convert_unit(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_item_merge_to_multipart_object(wxMenu *menu); void append_menu_item_merge_to_single_object(wxMenu *menu); void create_object_popupmenu(wxMenu *menu); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index f1c129118..9129900d1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3297,6 +3297,8 @@ void Plater::priv::reload_from_disk() new_volume->set_material_id(old_volume->material_id()); new_volume->set_transformation(old_volume->get_transformation() * old_volume->source.transform); 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(); std::swap(old_model_object->volumes[sel_v.volume_idx], old_model_object->volumes.back()); old_model_object->delete_volume(old_model_object->volumes.size() - 1); old_model_object->ensure_on_bed(); @@ -3771,6 +3773,8 @@ void Plater::priv::on_right_click(RBtnEvent& evt) if (evt.data.second) return; + int menu_item_convert_unit_position = 11; + if (printer_technology == ptSLA) menu = &sla_object_menu; else @@ -3780,8 +3784,11 @@ void Plater::priv::on_right_click(RBtnEvent& evt) get_selection().is_single_full_object() || get_selection().is_multiple_full_instance(); menu = is_some_full_instances ? &object_menu : &part_menu; + if (!is_some_full_instances) + 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_item_settings(menu); if (printer_technology != ptSLA) @@ -3996,7 +4003,6 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/ }, menu_item_printable->GetId()); } - sidebar->obj_list()->append_menu_items_convert_unit(menu); sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu); wxMenu* mirror_menu = new wxMenu(); diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index e65446ca3..0ebe5ae2f 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -63,7 +63,7 @@ void enable_menu_item(wxUpdateUIEvent& evt, std::function const cb_condi wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function cb, const wxBitmap& icon, wxEvtHandler* event_handler, - std::function const cb_condition, wxWindow* parent) + std::function const cb_condition, wxWindow* parent, int insert_pos/* = wxNOT_FOUND*/) { if (id == wxID_ANY) id = wxNewId(); @@ -72,7 +72,10 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const if (icon.IsOk()) { item->SetBitmap(icon); } - menu->Append(item); + if (insert_pos == wxNOT_FOUND) + menu->Append(item); + else + menu->Insert(insert_pos, item); #ifdef __WXMSW__ if (event_handler != nullptr && event_handler != menu) @@ -91,7 +94,7 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function cb, const std::string& icon, wxEvtHandler* event_handler, - std::function const cb_condition, wxWindow* parent) + std::function const cb_condition, wxWindow* parent, int insert_pos/* = wxNOT_FOUND*/) { if (id == wxID_ANY) id = wxNewId(); @@ -103,7 +106,7 @@ wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const msw_menuitem_bitmaps[id] = icon; #endif /* __WXMSW__ */ - return append_menu_item(menu, id, string, description, cb, bmp, event_handler, cb_condition, parent); + return append_menu_item(menu, id, string, description, cb, bmp, event_handler, cb_condition, parent, insert_pos); } wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, const std::string& icon, diff --git a/src/slic3r/GUI/wxExtensions.hpp b/src/slic3r/GUI/wxExtensions.hpp index e0952d79d..4f5204775 100644 --- a/src/slic3r/GUI/wxExtensions.hpp +++ b/src/slic3r/GUI/wxExtensions.hpp @@ -22,10 +22,10 @@ inline void msw_rescale_menu(wxMenu* /* menu */) {} wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function cb, const wxBitmap& icon, wxEvtHandler* event_handler = nullptr, - std::function const cb_condition = []() { return true;}, wxWindow* parent = nullptr); + std::function const cb_condition = []() { return true;}, wxWindow* parent = nullptr, int insert_pos = wxNOT_FOUND); wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description, std::function cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr, - std::function const cb_condition = []() { return true; }, wxWindow* parent = nullptr); + std::function const cb_condition = []() { return true; }, wxWindow* parent = nullptr, int insert_pos = wxNOT_FOUND); wxMenuItem* append_submenu(wxMenu* menu, wxMenu* sub_menu, int id, const wxString& string, const wxString& description, const std::string& icon = "",