Fix of #5007 - "Reload from disk" causes objects converted to inches to revert to mm

This commit is contained in:
YuSanka 2020-12-11 13:57:38 +01:00
parent 9dd83a3daa
commit aaaa85c1f8
7 changed files with 88 additions and 19 deletions

View File

@ -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));

View File

@ -552,11 +552,12 @@ public:
int volume_idx{ -1 };
Vec3d mesh_offset{ Vec3d::Zero() };
Geometry::Transformation transform;
bool is_converted_from_inches = 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);
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); }

View File

@ -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<int> 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);

View File

@ -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);

View File

@ -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();

View File

@ -63,7 +63,7 @@ void enable_menu_item(wxUpdateUIEvent& evt, std::function<bool()> const cb_condi
wxMenuItem* append_menu_item(wxMenu* menu, int id, const wxString& string, const wxString& description,
std::function<void(wxCommandEvent& event)> cb, const wxBitmap& icon, wxEvtHandler* event_handler,
std::function<bool()> const cb_condition, wxWindow* parent)
std::function<bool()> 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<void(wxCommandEvent& event)> cb, const std::string& icon, wxEvtHandler* event_handler,
std::function<bool()> const cb_condition, wxWindow* parent)
std::function<bool()> 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,

View File

@ -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<void(wxCommandEvent& event)> cb, const wxBitmap& icon, wxEvtHandler* event_handler = nullptr,
std::function<bool()> const cb_condition = []() { return true;}, wxWindow* parent = nullptr);
std::function<bool()> 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<void(wxCommandEvent& event)> cb, const std::string& icon = "", wxEvtHandler* event_handler = nullptr,
std::function<bool()> const cb_condition = []() { return true; }, wxWindow* parent = nullptr);
std::function<bool()> 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 = "",