MSW specific: Fixing by Windows repair algorithm of cut objects if it's needed.

Related to issues #7243
This commit is contained in:
YuSanka 2023-11-27 13:08:31 +01:00
parent ec40931389
commit 200f4073c8
4 changed files with 112 additions and 25 deletions

View File

@ -475,6 +475,30 @@ std::vector<wxBitmapBundle*> MenuFactory::get_svg_volume_bitmaps()
return volume_bmps; return volume_bmps;
} }
wxString MenuFactory::get_repaire_result_message(
const std::vector<std::string>& succes_models,
const std::vector<std::pair<std::string, std::string>>& failed_models)
{
// Show info notification
wxString msg;
wxString bullet_suf = "\n - ";
if (!succes_models.empty()) {
msg = _L_PLURAL("The following model was repaired successfully", "The following models were repaired successfully", succes_models.size()) + ":";
for (auto& model : succes_models)
msg += bullet_suf + from_u8(model);
msg += "\n\n";
}
if (!failed_models.empty()) {
msg += _L_PLURAL("Folowing model repair failed", "Folowing models repair failed", failed_models.size()) + ":\n";
for (auto& model : failed_models)
msg += bullet_suf + from_u8(model.first) + ": " + _(model.second);
}
if (msg.IsEmpty())
msg = _L("Repairing was canceled");
return msg;
}
void MenuFactory::append_menu_item_delete(wxMenu* menu) void MenuFactory::append_menu_item_delete(wxMenu* menu)
{ {
append_menu_item(menu, wxID_ANY, _L("Delete") + "\tDel", _L("Remove the selected object"), append_menu_item(menu, wxID_ANY, _L("Delete") + "\tDel", _L("Remove the selected object"),

View File

@ -41,6 +41,9 @@ public:
static std::vector<wxBitmapBundle*> get_text_volume_bitmaps(); static std::vector<wxBitmapBundle*> get_text_volume_bitmaps();
static std::vector<wxBitmapBundle*> get_svg_volume_bitmaps(); static std::vector<wxBitmapBundle*> get_svg_volume_bitmaps();
static wxString get_repaire_result_message(const std::vector<std::string>& succes_models,
const std::vector<std::pair<std::string, std::string>>& failed_models);
MenuFactory(); MenuFactory();
~MenuFactory() = default; ~MenuFactory() = default;

View File

@ -4670,21 +4670,7 @@ void ObjectList::fix_through_winsdk()
progress_dlg.Update(100, ""); progress_dlg.Update(100, "");
// Show info notification // Show info notification
wxString msg; wxString msg = MenuFactory::get_repaire_result_message(succes_models, failed_models);
wxString bullet_suf = "\n - ";
if (!succes_models.empty()) {
msg = _L_PLURAL("The following model was repaired successfully", "The following models were repaired successfully", succes_models.size()) + ":";
for (auto& model : succes_models)
msg += bullet_suf + from_u8(model);
msg += "\n\n";
}
if (!failed_models.empty()) {
msg += _L_PLURAL("Folowing model repair failed", "Folowing models repair failed", failed_models.size()) + ":\n";
for (auto& model : failed_models)
msg += bullet_suf + from_u8(model.first) + ": " + _(model.second);
}
if (msg.IsEmpty())
msg = _L("Repairing was canceled");
plater->get_notification_manager()->push_notification(NotificationType::RepairFinished, NotificationManager::NotificationLevel::PrintInfoShortNotificationLevel, boost::nowide::narrow(msg)); plater->get_notification_manager()->push_notification(NotificationType::RepairFinished, NotificationManager::NotificationLevel::PrintInfoShortNotificationLevel, boost::nowide::narrow(msg));
} }

View File

@ -12,8 +12,10 @@
#include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/Plater.hpp"
#include "slic3r/GUI/GUI_ObjectManipulation.hpp" #include "slic3r/GUI/GUI_ObjectManipulation.hpp"
#include "slic3r/GUI/GUI_Factories.hpp"
#include "slic3r/GUI/format.hpp" #include "slic3r/GUI/format.hpp"
#include "slic3r/Utils/UndoRedo.hpp" #include "slic3r/Utils/UndoRedo.hpp"
#include "slic3r/Utils/FixModelByWin10.hpp"
#include "libslic3r/AppConfig.hpp" #include "libslic3r/AppConfig.hpp"
#include "libslic3r/TriangleMeshSlicer.hpp" #include "libslic3r/TriangleMeshSlicer.hpp"
@ -3259,6 +3261,8 @@ void update_object_cut_id(CutObjectBase& cut_id, ModelObjectCutAttributes attrib
static void check_objects_after_cut(const ModelObjectPtrs& objects) static void check_objects_after_cut(const ModelObjectPtrs& objects)
{ {
std::vector<std::string> err_objects_names; std::vector<std::string> err_objects_names;
std::vector<int> err_objects_idxs;
int obj_idx{ 0 };
for (const ModelObject* object : objects) { for (const ModelObject* object : objects) {
std::vector<std::string> connectors_names; std::vector<std::string> connectors_names;
connectors_names.reserve(object->volumes.size()); connectors_names.reserve(object->volumes.size());
@ -3269,17 +3273,87 @@ static void check_objects_after_cut(const ModelObjectPtrs& objects)
sort_remove_duplicates(connectors_names); sort_remove_duplicates(connectors_names);
if (connectors_count != connectors_names.size()) if (connectors_count != connectors_names.size())
err_objects_names.push_back(object->name); err_objects_names.push_back(object->name);
}
if (err_objects_names.empty())
return;
// check manifol/repairs
auto stats = object->get_object_stl_stats();
if (!stats.manifold() || stats.repaired())
err_objects_idxs.push_back(obj_idx);
obj_idx++;
}
auto plater = wxGetApp().plater();
if (!err_objects_names.empty()) {
wxString names = from_u8(err_objects_names[0]); wxString names = from_u8(err_objects_names[0]);
for (size_t i = 1; i < err_objects_names.size(); i++) for (size_t i = 1; i < err_objects_names.size(); i++)
names += ", " + from_u8(err_objects_names[i]); names += ", " + from_u8(err_objects_names[i]);
WarningDialog(wxGetApp().plater(), format_wxstr("Objects(%1%) have duplicated connectors. " WarningDialog(plater, format_wxstr("Objects(%1%) have duplicated connectors. "
"Some connectors may be missing in slicing result.\n" "Some connectors may be missing in slicing result.\n"
"Please report to PrusaSlicer team in which scenario this issue happened.\n" "Please report to PrusaSlicer team in which scenario this issue happened.\n"
"Thank you.", names)).ShowModal(); "Thank you.", names)).ShowModal();
}
if (is_windows10() && !err_objects_idxs.empty()) {
auto dlg = WarningDialog(plater, _L("Cut is performed and open eages or auto-repaired errors are detected in result objects.\n"
"You can fix them by Windows repair algorithm.\n\n"
"Do you want to fix cut objects?"),
_L("Detected errors in cut objects"), wxYES_NO);
if (dlg.ShowModal() == wxID_YES) {
// model_name
std::vector<std::string> succes_models;
// model_name failing reason
std::vector<std::pair<std::string, std::string>> failed_models;
std::vector<std::string> model_names;
for (int obj_idx : err_objects_idxs)
model_names.push_back(objects[obj_idx]->name);
auto fix_and_update_progress = [plater, model_names, &objects](const int obj_idx, int model_idx,
wxProgressDialog& progress_dlg,
std::vector<std::string>& succes_models,
std::vector<std::pair<std::string, std::string>>& failed_models) -> bool
{
const std::string& model_name = model_names[model_idx];
wxString msg = _L("Repairing model");
if (model_names.size() == 1)
msg += ": " + from_u8(model_name) + "\n";
else {
msg += ":\n";
for (int i = 0; i < int(model_names.size()); ++i)
msg += (i == model_idx ? " > " : " ") + from_u8(model_names[i]) + "\n";
msg += "\n";
}
std::string res;
if (!fix_model_by_win10_sdk_gui(*objects[obj_idx], -1, progress_dlg, msg, res))
return false;
if (res.empty())
succes_models.push_back(model_name);
else
failed_models.push_back({ model_name, res });
return true;
};
// Open a progress dialog.
wxProgressDialog progress_dlg(_L("Fixing by Windows repair algorithm"), "", 100, find_toplevel_parent(plater),
wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
int model_idx{ 0 };
for (int obj_idx : err_objects_idxs) {
if (!fix_and_update_progress(obj_idx, model_idx, progress_dlg, succes_models, failed_models))
break;
model_idx++;
}
// Close the progress dialog
progress_dlg.Update(100, "");
// Show info dialog
wxString msg = MenuFactory::get_repaire_result_message(succes_models, failed_models);
InfoDialog(plater, _L("Repairing result"), msg).ShowModal();
}
}
} }
void synchronize_model_after_cut(Model& model, const CutObjectBase& cut_id) void synchronize_model_after_cut(Model& model, const CutObjectBase& cut_id)