Tech ENABLE_REMOVE_ASSOCIATION_TO_FILE_FOR_WINDOWS_8_AND_LATER - Disable association to 3mf and stl files if the application is run on Windows 8 or later
This commit is contained in:
parent
e6750a524f
commit
39cefdad89
@ -81,6 +81,8 @@
|
|||||||
#define ENABLE_USED_FILAMENT_POST_PROCESS (1 && ENABLE_2_5_0_ALPHA1)
|
#define ENABLE_USED_FILAMENT_POST_PROCESS (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
// Enable gizmo grabbers to share common models
|
// Enable gizmo grabbers to share common models
|
||||||
#define ENABLE_GIZMO_GRABBER_REFACTOR (1 && ENABLE_2_5_0_ALPHA1)
|
#define ENABLE_GIZMO_GRABBER_REFACTOR (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
|
// Disable association to 3mf and stl files if the application is run on Windows 8 or later
|
||||||
|
#define ENABLE_REMOVE_ASSOCIATION_TO_FILE_FOR_WINDOWS_8_AND_LATER (1 && ENABLE_2_5_0_ALPHA1)
|
||||||
|
|
||||||
|
|
||||||
#endif // _prusaslicer_technologies_h_
|
#endif // _prusaslicer_technologies_h_
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,449 +1,449 @@
|
|||||||
#ifdef HAS_WIN10SDK
|
#ifdef HAS_WIN10SDK
|
||||||
|
|
||||||
#ifndef NOMINMAX
|
#ifndef NOMINMAX
|
||||||
# define NOMINMAX
|
# define NOMINMAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Windows Runtime
|
// Windows Runtime
|
||||||
#include <roapi.h>
|
#include <roapi.h>
|
||||||
// for ComPtr
|
// for ComPtr
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
|
|
||||||
// from C:/Program Files (x86)/Windows Kits/10/Include/10.0.17134.0/
|
// from C:/Program Files (x86)/Windows Kits/10/Include/10.0.17134.0/
|
||||||
#include <winrt/robuffer.h>
|
#include <winrt/robuffer.h>
|
||||||
#include <winrt/windows.storage.provider.h>
|
#include <winrt/windows.storage.provider.h>
|
||||||
#include <winrt/windows.graphics.printing3d.h>
|
#include <winrt/windows.graphics.printing3d.h>
|
||||||
|
|
||||||
#include "FixModelByWin10.hpp"
|
#include "FixModelByWin10.hpp"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/nowide/convert.hpp>
|
#include <boost/nowide/convert.hpp>
|
||||||
#include <boost/nowide/cstdio.hpp>
|
#include <boost/nowide/cstdio.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
#include "libslic3r/Model.hpp"
|
#include "libslic3r/Model.hpp"
|
||||||
#include "libslic3r/Print.hpp"
|
#include "libslic3r/Print.hpp"
|
||||||
#include "libslic3r/PresetBundle.hpp"
|
#include "libslic3r/PresetBundle.hpp"
|
||||||
#include "libslic3r/Format/3mf.hpp"
|
#include "libslic3r/Format/3mf.hpp"
|
||||||
#include "../GUI/GUI.hpp"
|
#include "../GUI/GUI.hpp"
|
||||||
#include "../GUI/I18N.hpp"
|
#include "../GUI/I18N.hpp"
|
||||||
#include "../GUI/MsgDialog.hpp"
|
#include "../GUI/MsgDialog.hpp"
|
||||||
|
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
#include <wx/progdlg.h>
|
#include <wx/progdlg.h>
|
||||||
|
|
||||||
extern "C"{
|
extern "C"{
|
||||||
// from rapi.h
|
// from rapi.h
|
||||||
typedef HRESULT (__stdcall* FunctionRoInitialize)(int);
|
typedef HRESULT (__stdcall* FunctionRoInitialize)(int);
|
||||||
typedef HRESULT (__stdcall* FunctionRoUninitialize)();
|
typedef HRESULT (__stdcall* FunctionRoUninitialize)();
|
||||||
typedef HRESULT (__stdcall* FunctionRoActivateInstance)(HSTRING activatableClassId, IInspectable **instance);
|
typedef HRESULT (__stdcall* FunctionRoActivateInstance)(HSTRING activatableClassId, IInspectable **instance);
|
||||||
typedef HRESULT (__stdcall* FunctionRoGetActivationFactory)(HSTRING activatableClassId, REFIID iid, void **factory);
|
typedef HRESULT (__stdcall* FunctionRoGetActivationFactory)(HSTRING activatableClassId, REFIID iid, void **factory);
|
||||||
// from winstring.h
|
// from winstring.h
|
||||||
typedef HRESULT (__stdcall* FunctionWindowsCreateString)(LPCWSTR sourceString, UINT32 length, HSTRING *string);
|
typedef HRESULT (__stdcall* FunctionWindowsCreateString)(LPCWSTR sourceString, UINT32 length, HSTRING *string);
|
||||||
typedef HRESULT (__stdcall* FunctionWindowsDelteString)(HSTRING string);
|
typedef HRESULT (__stdcall* FunctionWindowsDelteString)(HSTRING string);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
HMODULE s_hRuntimeObjectLibrary = nullptr;
|
HMODULE s_hRuntimeObjectLibrary = nullptr;
|
||||||
FunctionRoInitialize s_RoInitialize = nullptr;
|
FunctionRoInitialize s_RoInitialize = nullptr;
|
||||||
FunctionRoUninitialize s_RoUninitialize = nullptr;
|
FunctionRoUninitialize s_RoUninitialize = nullptr;
|
||||||
FunctionRoActivateInstance s_RoActivateInstance = nullptr;
|
FunctionRoActivateInstance s_RoActivateInstance = nullptr;
|
||||||
FunctionRoGetActivationFactory s_RoGetActivationFactory = nullptr;
|
FunctionRoGetActivationFactory s_RoGetActivationFactory = nullptr;
|
||||||
FunctionWindowsCreateString s_WindowsCreateString = nullptr;
|
FunctionWindowsCreateString s_WindowsCreateString = nullptr;
|
||||||
FunctionWindowsDelteString s_WindowsDeleteString = nullptr;
|
FunctionWindowsDelteString s_WindowsDeleteString = nullptr;
|
||||||
|
|
||||||
bool winrt_load_runtime_object_library()
|
bool winrt_load_runtime_object_library()
|
||||||
{
|
{
|
||||||
if (s_hRuntimeObjectLibrary == nullptr)
|
if (s_hRuntimeObjectLibrary == nullptr)
|
||||||
s_hRuntimeObjectLibrary = LoadLibrary(L"ComBase.dll");
|
s_hRuntimeObjectLibrary = LoadLibrary(L"ComBase.dll");
|
||||||
if (s_hRuntimeObjectLibrary != nullptr) {
|
if (s_hRuntimeObjectLibrary != nullptr) {
|
||||||
s_RoInitialize = (FunctionRoInitialize) GetProcAddress(s_hRuntimeObjectLibrary, "RoInitialize");
|
s_RoInitialize = (FunctionRoInitialize) GetProcAddress(s_hRuntimeObjectLibrary, "RoInitialize");
|
||||||
s_RoUninitialize = (FunctionRoUninitialize) GetProcAddress(s_hRuntimeObjectLibrary, "RoUninitialize");
|
s_RoUninitialize = (FunctionRoUninitialize) GetProcAddress(s_hRuntimeObjectLibrary, "RoUninitialize");
|
||||||
s_RoActivateInstance = (FunctionRoActivateInstance) GetProcAddress(s_hRuntimeObjectLibrary, "RoActivateInstance");
|
s_RoActivateInstance = (FunctionRoActivateInstance) GetProcAddress(s_hRuntimeObjectLibrary, "RoActivateInstance");
|
||||||
s_RoGetActivationFactory = (FunctionRoGetActivationFactory) GetProcAddress(s_hRuntimeObjectLibrary, "RoGetActivationFactory");
|
s_RoGetActivationFactory = (FunctionRoGetActivationFactory) GetProcAddress(s_hRuntimeObjectLibrary, "RoGetActivationFactory");
|
||||||
s_WindowsCreateString = (FunctionWindowsCreateString) GetProcAddress(s_hRuntimeObjectLibrary, "WindowsCreateString");
|
s_WindowsCreateString = (FunctionWindowsCreateString) GetProcAddress(s_hRuntimeObjectLibrary, "WindowsCreateString");
|
||||||
s_WindowsDeleteString = (FunctionWindowsDelteString) GetProcAddress(s_hRuntimeObjectLibrary, "WindowsDeleteString");
|
s_WindowsDeleteString = (FunctionWindowsDelteString) GetProcAddress(s_hRuntimeObjectLibrary, "WindowsDeleteString");
|
||||||
}
|
}
|
||||||
return s_RoInitialize && s_RoUninitialize && s_RoActivateInstance && s_WindowsCreateString && s_WindowsDeleteString;
|
return s_RoInitialize && s_RoUninitialize && s_RoActivateInstance && s_WindowsCreateString && s_WindowsDeleteString;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT winrt_activate_instance(const std::wstring &class_name, IInspectable **pinst)
|
static HRESULT winrt_activate_instance(const std::wstring &class_name, IInspectable **pinst)
|
||||||
{
|
{
|
||||||
HSTRING hClassName;
|
HSTRING hClassName;
|
||||||
HRESULT hr = (*s_WindowsCreateString)(class_name.c_str(), class_name.size(), &hClassName);
|
HRESULT hr = (*s_WindowsCreateString)(class_name.c_str(), class_name.size(), &hClassName);
|
||||||
if (S_OK != hr)
|
if (S_OK != hr)
|
||||||
return hr;
|
return hr;
|
||||||
hr = (*s_RoActivateInstance)(hClassName, pinst);
|
hr = (*s_RoActivateInstance)(hClassName, pinst);
|
||||||
(*s_WindowsDeleteString)(hClassName);
|
(*s_WindowsDeleteString)(hClassName);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TYPE>
|
template<typename TYPE>
|
||||||
static HRESULT winrt_activate_instance(const std::wstring &class_name, TYPE **pinst)
|
static HRESULT winrt_activate_instance(const std::wstring &class_name, TYPE **pinst)
|
||||||
{
|
{
|
||||||
IInspectable *pinspectable = nullptr;
|
IInspectable *pinspectable = nullptr;
|
||||||
HRESULT hr = winrt_activate_instance(class_name, &pinspectable);
|
HRESULT hr = winrt_activate_instance(class_name, &pinspectable);
|
||||||
if (S_OK != hr)
|
if (S_OK != hr)
|
||||||
return hr;
|
return hr;
|
||||||
hr = pinspectable->QueryInterface(__uuidof(TYPE), (void**)pinst);
|
hr = pinspectable->QueryInterface(__uuidof(TYPE), (void**)pinst);
|
||||||
pinspectable->Release();
|
pinspectable->Release();
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT winrt_get_activation_factory(const std::wstring &class_name, REFIID iid, void **pinst)
|
static HRESULT winrt_get_activation_factory(const std::wstring &class_name, REFIID iid, void **pinst)
|
||||||
{
|
{
|
||||||
HSTRING hClassName;
|
HSTRING hClassName;
|
||||||
HRESULT hr = (*s_WindowsCreateString)(class_name.c_str(), class_name.size(), &hClassName);
|
HRESULT hr = (*s_WindowsCreateString)(class_name.c_str(), class_name.size(), &hClassName);
|
||||||
if (S_OK != hr)
|
if (S_OK != hr)
|
||||||
return hr;
|
return hr;
|
||||||
hr = (*s_RoGetActivationFactory)(hClassName, iid, pinst);
|
hr = (*s_RoGetActivationFactory)(hClassName, iid, pinst);
|
||||||
(*s_WindowsDeleteString)(hClassName);
|
(*s_WindowsDeleteString)(hClassName);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TYPE>
|
template<typename TYPE>
|
||||||
static HRESULT winrt_get_activation_factory(const std::wstring &class_name, TYPE **pinst)
|
static HRESULT winrt_get_activation_factory(const std::wstring &class_name, TYPE **pinst)
|
||||||
{
|
{
|
||||||
return winrt_get_activation_factory(class_name, __uuidof(TYPE), reinterpret_cast<void**>(pinst));
|
return winrt_get_activation_factory(class_name, __uuidof(TYPE), reinterpret_cast<void**>(pinst));
|
||||||
}
|
}
|
||||||
|
|
||||||
// To be called often to test whether to cancel the operation.
|
// To be called often to test whether to cancel the operation.
|
||||||
typedef std::function<void ()> ThrowOnCancelFn;
|
typedef std::function<void ()> ThrowOnCancelFn;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static AsyncStatus winrt_async_await(const Microsoft::WRL::ComPtr<T> &asyncAction, ThrowOnCancelFn throw_on_cancel, int blocking_tick_ms = 100)
|
static AsyncStatus winrt_async_await(const Microsoft::WRL::ComPtr<T> &asyncAction, ThrowOnCancelFn throw_on_cancel, int blocking_tick_ms = 100)
|
||||||
{
|
{
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
||||||
asyncAction.As(&asyncInfo);
|
asyncAction.As(&asyncInfo);
|
||||||
AsyncStatus status;
|
AsyncStatus status;
|
||||||
// Ugly blocking loop until the RepairAsync call finishes.
|
// Ugly blocking loop until the RepairAsync call finishes.
|
||||||
//FIXME replace with a callback.
|
//FIXME replace with a callback.
|
||||||
// https://social.msdn.microsoft.com/Forums/en-US/a5038fb4-b7b7-4504-969d-c102faa389fb/trying-to-block-an-async-operation-and-wait-for-a-particular-time?forum=vclanguage
|
// https://social.msdn.microsoft.com/Forums/en-US/a5038fb4-b7b7-4504-969d-c102faa389fb/trying-to-block-an-async-operation-and-wait-for-a-particular-time?forum=vclanguage
|
||||||
for (;;) {
|
for (;;) {
|
||||||
asyncInfo->get_Status(&status);
|
asyncInfo->get_Status(&status);
|
||||||
if (status != AsyncStatus::Started)
|
if (status != AsyncStatus::Started)
|
||||||
return status;
|
return status;
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
::Sleep(blocking_tick_ms);
|
::Sleep(blocking_tick_ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT winrt_open_file_stream(
|
static HRESULT winrt_open_file_stream(
|
||||||
const std::wstring &path,
|
const std::wstring &path,
|
||||||
ABI::Windows::Storage::FileAccessMode mode,
|
ABI::Windows::Storage::FileAccessMode mode,
|
||||||
ABI::Windows::Storage::Streams::IRandomAccessStream **fileStream,
|
ABI::Windows::Storage::Streams::IRandomAccessStream **fileStream,
|
||||||
ThrowOnCancelFn throw_on_cancel)
|
ThrowOnCancelFn throw_on_cancel)
|
||||||
{
|
{
|
||||||
// Get the file factory.
|
// Get the file factory.
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFileStatics> fileFactory;
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFileStatics> fileFactory;
|
||||||
HRESULT hr = winrt_get_activation_factory(L"Windows.Storage.StorageFile", fileFactory.GetAddressOf());
|
HRESULT hr = winrt_get_activation_factory(L"Windows.Storage.StorageFile", fileFactory.GetAddressOf());
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
// Open the file asynchronously.
|
// Open the file asynchronously.
|
||||||
HSTRING hstr_path;
|
HSTRING hstr_path;
|
||||||
hr = (*s_WindowsCreateString)(path.c_str(), path.size(), &hstr_path);
|
hr = (*s_WindowsCreateString)(path.c_str(), path.size(), &hstr_path);
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::StorageFile*>> fileOpenAsync;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::StorageFile*>> fileOpenAsync;
|
||||||
hr = fileFactory->GetFileFromPathAsync(hstr_path, fileOpenAsync.GetAddressOf());
|
hr = fileFactory->GetFileFromPathAsync(hstr_path, fileOpenAsync.GetAddressOf());
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
(*s_WindowsDeleteString)(hstr_path);
|
(*s_WindowsDeleteString)(hstr_path);
|
||||||
|
|
||||||
// Wait until the file gets open, get the actual file.
|
// Wait until the file gets open, get the actual file.
|
||||||
AsyncStatus status = winrt_async_await(fileOpenAsync, throw_on_cancel);
|
AsyncStatus status = winrt_async_await(fileOpenAsync, throw_on_cancel);
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFile> storageFile;
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::IStorageFile> storageFile;
|
||||||
if (status == AsyncStatus::Completed) {
|
if (status == AsyncStatus::Completed) {
|
||||||
hr = fileOpenAsync->GetResults(storageFile.GetAddressOf());
|
hr = fileOpenAsync->GetResults(storageFile.GetAddressOf());
|
||||||
} else {
|
} else {
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
||||||
hr = fileOpenAsync.As(&asyncInfo);
|
hr = fileOpenAsync.As(&asyncInfo);
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
HRESULT err;
|
HRESULT err;
|
||||||
hr = asyncInfo->get_ErrorCode(&err);
|
hr = asyncInfo->get_ErrorCode(&err);
|
||||||
return FAILED(hr) ? hr : err;
|
return FAILED(hr) ? hr : err;
|
||||||
}
|
}
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::Streams::IRandomAccessStream*>> fileStreamAsync;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::Streams::IRandomAccessStream*>> fileStreamAsync;
|
||||||
hr = storageFile->OpenAsync(mode, fileStreamAsync.GetAddressOf());
|
hr = storageFile->OpenAsync(mode, fileStreamAsync.GetAddressOf());
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
status = winrt_async_await(fileStreamAsync, throw_on_cancel);
|
status = winrt_async_await(fileStreamAsync, throw_on_cancel);
|
||||||
if (status == AsyncStatus::Completed) {
|
if (status == AsyncStatus::Completed) {
|
||||||
hr = fileStreamAsync->GetResults(fileStream);
|
hr = fileStreamAsync->GetResults(fileStream);
|
||||||
} else {
|
} else {
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
||||||
hr = fileStreamAsync.As(&asyncInfo);
|
hr = fileStreamAsync.As(&asyncInfo);
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
HRESULT err;
|
HRESULT err;
|
||||||
hr = asyncInfo->get_ErrorCode(&err);
|
hr = asyncInfo->get_ErrorCode(&err);
|
||||||
if (!FAILED(hr))
|
if (!FAILED(hr))
|
||||||
hr = err;
|
hr = err;
|
||||||
}
|
}
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_windows10()
|
bool is_windows10()
|
||||||
{
|
{
|
||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey);
|
LONG lRes = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey);
|
||||||
if (lRes == ERROR_SUCCESS) {
|
if (lRes == ERROR_SUCCESS) {
|
||||||
WCHAR szBuffer[512];
|
WCHAR szBuffer[512];
|
||||||
DWORD dwBufferSize = sizeof(szBuffer);
|
DWORD dwBufferSize = sizeof(szBuffer);
|
||||||
lRes = RegQueryValueExW(hKey, L"ProductName", 0, nullptr, (LPBYTE)szBuffer, &dwBufferSize);
|
lRes = RegQueryValueExW(hKey, L"ProductName", 0, nullptr, (LPBYTE)szBuffer, &dwBufferSize);
|
||||||
if (lRes == ERROR_SUCCESS)
|
if (lRes == ERROR_SUCCESS)
|
||||||
return wcsncmp(szBuffer, L"Windows 10", 10) == 0;
|
return wcsncmp(szBuffer, L"Windows 10", 10) == 0;
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Progress function, to be called regularly to update the progress.
|
// Progress function, to be called regularly to update the progress.
|
||||||
typedef std::function<void (const char * /* message */, unsigned /* progress */)> ProgressFn;
|
typedef std::function<void (const char * /* message */, unsigned /* progress */)> ProgressFn;
|
||||||
|
|
||||||
void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path_dst, ProgressFn on_progress, ThrowOnCancelFn throw_on_cancel)
|
void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path_dst, ProgressFn on_progress, ThrowOnCancelFn throw_on_cancel)
|
||||||
{
|
{
|
||||||
if (! is_windows10())
|
if (! is_windows10())
|
||||||
throw Slic3r::RuntimeError("fix_model_by_win10_sdk called on non Windows 10 system");
|
throw Slic3r::RuntimeError("fix_model_by_win10_sdk called on non Windows 10 system");
|
||||||
|
|
||||||
if (! winrt_load_runtime_object_library())
|
if (! winrt_load_runtime_object_library())
|
||||||
throw Slic3r::RuntimeError("Failed to initialize the WinRT library.");
|
throw Slic3r::RuntimeError("Failed to initialize the WinRT library.");
|
||||||
|
|
||||||
HRESULT hr = (*s_RoInitialize)(RO_INIT_MULTITHREADED);
|
HRESULT hr = (*s_RoInitialize)(RO_INIT_MULTITHREADED);
|
||||||
{
|
{
|
||||||
on_progress(L("Exporting source model"), 20);
|
on_progress(L("Exporting source model"), 20);
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> fileStream;
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> fileStream;
|
||||||
hr = winrt_open_file_stream(boost::nowide::widen(path_src), ABI::Windows::Storage::FileAccessMode::FileAccessMode_Read, fileStream.GetAddressOf(), throw_on_cancel);
|
hr = winrt_open_file_stream(boost::nowide::widen(path_src), ABI::Windows::Storage::FileAccessMode::FileAccessMode_Read, fileStream.GetAddressOf(), throw_on_cancel);
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Printing3D::IPrinting3D3MFPackage> printing3d3mfpackage;
|
Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Printing3D::IPrinting3D3MFPackage> printing3d3mfpackage;
|
||||||
hr = winrt_activate_instance(L"Windows.Graphics.Printing3D.Printing3D3MFPackage", printing3d3mfpackage.GetAddressOf());
|
hr = winrt_activate_instance(L"Windows.Graphics.Printing3D.Printing3D3MFPackage", printing3d3mfpackage.GetAddressOf());
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Graphics::Printing3D::Printing3DModel*>> modelAsync;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Graphics::Printing3D::Printing3DModel*>> modelAsync;
|
||||||
hr = printing3d3mfpackage->LoadModelFromPackageAsync(fileStream.Get(), modelAsync.GetAddressOf());
|
hr = printing3d3mfpackage->LoadModelFromPackageAsync(fileStream.Get(), modelAsync.GetAddressOf());
|
||||||
|
|
||||||
AsyncStatus status = winrt_async_await(modelAsync, throw_on_cancel);
|
AsyncStatus status = winrt_async_await(modelAsync, throw_on_cancel);
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Printing3D::IPrinting3DModel> model;
|
Microsoft::WRL::ComPtr<ABI::Windows::Graphics::Printing3D::IPrinting3DModel> model;
|
||||||
if (status == AsyncStatus::Completed)
|
if (status == AsyncStatus::Completed)
|
||||||
hr = modelAsync->GetResults(model.GetAddressOf());
|
hr = modelAsync->GetResults(model.GetAddressOf());
|
||||||
else
|
else
|
||||||
throw Slic3r::RuntimeError(L("Failed loading the input model."));
|
throw Slic3r::RuntimeError(L("Failed loading the input model."));
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IVector<ABI::Windows::Graphics::Printing3D::Printing3DMesh*>> meshes;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IVector<ABI::Windows::Graphics::Printing3D::Printing3DMesh*>> meshes;
|
||||||
hr = model->get_Meshes(meshes.GetAddressOf());
|
hr = model->get_Meshes(meshes.GetAddressOf());
|
||||||
unsigned num_meshes = 0;
|
unsigned num_meshes = 0;
|
||||||
hr = meshes->get_Size(&num_meshes);
|
hr = meshes->get_Size(&num_meshes);
|
||||||
|
|
||||||
on_progress(L("Repairing model by the Netfabb service"), 40);
|
on_progress(L("Repairing model by the Netfabb service"), 40);
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> repairAsync;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> repairAsync;
|
||||||
hr = model->RepairAsync(repairAsync.GetAddressOf());
|
hr = model->RepairAsync(repairAsync.GetAddressOf());
|
||||||
status = winrt_async_await(repairAsync, throw_on_cancel);
|
status = winrt_async_await(repairAsync, throw_on_cancel);
|
||||||
if (status != AsyncStatus::Completed)
|
if (status != AsyncStatus::Completed)
|
||||||
throw Slic3r::RuntimeError(L("Mesh repair failed."));
|
throw Slic3r::RuntimeError(L("Mesh repair failed."));
|
||||||
repairAsync->GetResults();
|
repairAsync->GetResults();
|
||||||
|
|
||||||
on_progress(L("Loading repaired model"), 60);
|
on_progress(L("Loading repaired model"), 60);
|
||||||
|
|
||||||
// Verify the number of meshes returned after the repair action.
|
// Verify the number of meshes returned after the repair action.
|
||||||
meshes.Reset();
|
meshes.Reset();
|
||||||
hr = model->get_Meshes(meshes.GetAddressOf());
|
hr = model->get_Meshes(meshes.GetAddressOf());
|
||||||
hr = meshes->get_Size(&num_meshes);
|
hr = meshes->get_Size(&num_meshes);
|
||||||
|
|
||||||
// Save model to this class' Printing3D3MFPackage.
|
// Save model to this class' Printing3D3MFPackage.
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> saveToPackageAsync;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> saveToPackageAsync;
|
||||||
hr = printing3d3mfpackage->SaveModelToPackageAsync(model.Get(), saveToPackageAsync.GetAddressOf());
|
hr = printing3d3mfpackage->SaveModelToPackageAsync(model.Get(), saveToPackageAsync.GetAddressOf());
|
||||||
status = winrt_async_await(saveToPackageAsync, throw_on_cancel);
|
status = winrt_async_await(saveToPackageAsync, throw_on_cancel);
|
||||||
if (status != AsyncStatus::Completed)
|
if (status != AsyncStatus::Completed)
|
||||||
throw Slic3r::RuntimeError(L("Saving mesh into the 3MF container failed."));
|
throw Slic3r::RuntimeError(L("Saving mesh into the 3MF container failed."));
|
||||||
hr = saveToPackageAsync->GetResults();
|
hr = saveToPackageAsync->GetResults();
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::Streams::IRandomAccessStream*>> generatorStreamAsync;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::Streams::IRandomAccessStream*>> generatorStreamAsync;
|
||||||
hr = printing3d3mfpackage->SaveAsync(generatorStreamAsync.GetAddressOf());
|
hr = printing3d3mfpackage->SaveAsync(generatorStreamAsync.GetAddressOf());
|
||||||
status = winrt_async_await(generatorStreamAsync, throw_on_cancel);
|
status = winrt_async_await(generatorStreamAsync, throw_on_cancel);
|
||||||
if (status != AsyncStatus::Completed)
|
if (status != AsyncStatus::Completed)
|
||||||
throw Slic3r::RuntimeError(L("Saving mesh into the 3MF container failed."));
|
throw Slic3r::RuntimeError(L("Saving mesh into the 3MF container failed."));
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> generatorStream;
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> generatorStream;
|
||||||
hr = generatorStreamAsync->GetResults(generatorStream.GetAddressOf());
|
hr = generatorStreamAsync->GetResults(generatorStream.GetAddressOf());
|
||||||
|
|
||||||
// Go to the beginning of the stream.
|
// Go to the beginning of the stream.
|
||||||
generatorStream->Seek(0);
|
generatorStream->Seek(0);
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IInputStream> inputStream;
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IInputStream> inputStream;
|
||||||
hr = generatorStream.As(&inputStream);
|
hr = generatorStream.As(&inputStream);
|
||||||
|
|
||||||
// Get the buffer factory.
|
// Get the buffer factory.
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBufferFactory> bufferFactory;
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBufferFactory> bufferFactory;
|
||||||
hr = winrt_get_activation_factory(L"Windows.Storage.Streams.Buffer", bufferFactory.GetAddressOf());
|
hr = winrt_get_activation_factory(L"Windows.Storage.Streams.Buffer", bufferFactory.GetAddressOf());
|
||||||
|
|
||||||
// Open the destination file.
|
// Open the destination file.
|
||||||
FILE *fout = boost::nowide::fopen(path_dst.c_str(), "wb");
|
FILE *fout = boost::nowide::fopen(path_dst.c_str(), "wb");
|
||||||
try {
|
try {
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
|
||||||
byte *buffer_ptr;
|
byte *buffer_ptr;
|
||||||
bufferFactory->Create(65536 * 2048, buffer.GetAddressOf());
|
bufferFactory->Create(65536 * 2048, buffer.GetAddressOf());
|
||||||
{
|
{
|
||||||
Microsoft::WRL::ComPtr<Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess;
|
Microsoft::WRL::ComPtr<Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess;
|
||||||
buffer.As(&bufferByteAccess);
|
buffer.As(&bufferByteAccess);
|
||||||
hr = bufferByteAccess->Buffer(&buffer_ptr);
|
hr = bufferByteAccess->Buffer(&buffer_ptr);
|
||||||
}
|
}
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
hr = buffer->get_Length(&length);
|
hr = buffer->get_Length(&length);
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer*, UINT32>> asyncRead;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer*, UINT32>> asyncRead;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
hr = inputStream->ReadAsync(buffer.Get(), 65536 * 2048, ABI::Windows::Storage::Streams::InputStreamOptions_ReadAhead, asyncRead.GetAddressOf());
|
hr = inputStream->ReadAsync(buffer.Get(), 65536 * 2048, ABI::Windows::Storage::Streams::InputStreamOptions_ReadAhead, asyncRead.GetAddressOf());
|
||||||
status = winrt_async_await(asyncRead, throw_on_cancel);
|
status = winrt_async_await(asyncRead, throw_on_cancel);
|
||||||
if (status != AsyncStatus::Completed)
|
if (status != AsyncStatus::Completed)
|
||||||
throw Slic3r::RuntimeError(L("Saving mesh into the 3MF container failed."));
|
throw Slic3r::RuntimeError(L("Saving mesh into the 3MF container failed."));
|
||||||
hr = buffer->get_Length(&length);
|
hr = buffer->get_Length(&length);
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
break;
|
break;
|
||||||
fwrite(buffer_ptr, length, 1, fout);
|
fwrite(buffer_ptr, length, 1, fout);
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
fclose(fout);
|
fclose(fout);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
fclose(fout);
|
fclose(fout);
|
||||||
// Here all the COM objects will be released through the ComPtr destructors.
|
// Here all the COM objects will be released through the ComPtr destructors.
|
||||||
}
|
}
|
||||||
(*s_RoUninitialize)();
|
(*s_RoUninitialize)();
|
||||||
}
|
}
|
||||||
|
|
||||||
class RepairCanceledException : public std::exception {
|
class RepairCanceledException : public std::exception {
|
||||||
public:
|
public:
|
||||||
const char* what() const throw() { return "Model repair has been canceled"; }
|
const char* what() const throw() { return "Model repair has been canceled"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// returt FALSE, if fixing was canceled
|
// returt FALSE, if fixing was canceled
|
||||||
// fix_result is empty, if fixing finished successfully
|
// fix_result is empty, if fixing finished successfully
|
||||||
// fix_result containes a message if fixing failed
|
// fix_result containes a message if fixing failed
|
||||||
bool fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx, wxProgressDialog& progress_dialog, const wxString& msg_header, std::string& fix_result)
|
bool fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx, wxProgressDialog& progress_dialog, const wxString& msg_header, std::string& fix_result)
|
||||||
{
|
{
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
std::condition_variable condition;
|
std::condition_variable condition;
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
struct Progress {
|
struct Progress {
|
||||||
std::string message;
|
std::string message;
|
||||||
int percent = 0;
|
int percent = 0;
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
} progress;
|
} progress;
|
||||||
std::atomic<bool> canceled = false;
|
std::atomic<bool> canceled = false;
|
||||||
std::atomic<bool> finished = false;
|
std::atomic<bool> finished = false;
|
||||||
|
|
||||||
std::vector<ModelVolume*> volumes;
|
std::vector<ModelVolume*> volumes;
|
||||||
if (volume_idx == -1)
|
if (volume_idx == -1)
|
||||||
volumes = model_object.volumes;
|
volumes = model_object.volumes;
|
||||||
else
|
else
|
||||||
volumes.emplace_back(model_object.volumes[volume_idx]);
|
volumes.emplace_back(model_object.volumes[volume_idx]);
|
||||||
|
|
||||||
// Executing the calculation in a background thread, so that the COM context could be created with its own threading model.
|
// Executing the calculation in a background thread, so that the COM context could be created with its own threading model.
|
||||||
// (It seems like wxWidgets initialize the COM contex as single threaded and we need a multi-threaded context).
|
// (It seems like wxWidgets initialize the COM contex as single threaded and we need a multi-threaded context).
|
||||||
bool success = false;
|
bool success = false;
|
||||||
size_t ivolume = 0;
|
size_t ivolume = 0;
|
||||||
auto on_progress = [&mutex, &condition, &ivolume, &volumes, &progress](const char *msg, unsigned prcnt) {
|
auto on_progress = [&mutex, &condition, &ivolume, &volumes, &progress](const char *msg, unsigned prcnt) {
|
||||||
std::lock_guard<std::mutex> lk(mutex);
|
std::lock_guard<std::mutex> lk(mutex);
|
||||||
progress.message = msg;
|
progress.message = msg;
|
||||||
progress.percent = (int)floor((float(prcnt) + float(ivolume) * 100.f) / float(volumes.size()));
|
progress.percent = (int)floor((float(prcnt) + float(ivolume) * 100.f) / float(volumes.size()));
|
||||||
progress.updated = true;
|
progress.updated = true;
|
||||||
condition.notify_all();
|
condition.notify_all();
|
||||||
};
|
};
|
||||||
auto worker_thread = boost::thread([&model_object, &volumes, &ivolume, on_progress, &success, &canceled, &finished]() {
|
auto worker_thread = boost::thread([&model_object, &volumes, &ivolume, on_progress, &success, &canceled, &finished]() {
|
||||||
try {
|
try {
|
||||||
std::vector<TriangleMesh> meshes_repaired;
|
std::vector<TriangleMesh> meshes_repaired;
|
||||||
meshes_repaired.reserve(volumes.size());
|
meshes_repaired.reserve(volumes.size());
|
||||||
for (; ivolume < volumes.size(); ++ ivolume) {
|
for (; ivolume < volumes.size(); ++ ivolume) {
|
||||||
on_progress(L("Exporting source model"), 0);
|
on_progress(L("Exporting source model"), 0);
|
||||||
boost::filesystem::path path_src = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
boost::filesystem::path path_src = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
||||||
path_src += ".3mf";
|
path_src += ".3mf";
|
||||||
Model model;
|
Model model;
|
||||||
ModelObject *mo = model.add_object();
|
ModelObject *mo = model.add_object();
|
||||||
mo->add_volume(*volumes[ivolume]);
|
mo->add_volume(*volumes[ivolume]);
|
||||||
|
|
||||||
// We are about to save a 3mf, fix it by netfabb and load the fixed 3mf back.
|
// We are about to save a 3mf, fix it by netfabb and load the fixed 3mf back.
|
||||||
// store_3mf currently bakes the volume transformation into the mesh itself.
|
// store_3mf currently bakes the volume transformation into the mesh itself.
|
||||||
// If we then loaded the repaired 3mf and pushed the mesh into the original ModelVolume
|
// If we then loaded the repaired 3mf and pushed the mesh into the original ModelVolume
|
||||||
// (which remembers the matrix the whole time), the transformation would be used twice.
|
// (which remembers the matrix the whole time), the transformation would be used twice.
|
||||||
// We will therefore set the volume transform on the dummy ModelVolume to identity.
|
// We will therefore set the volume transform on the dummy ModelVolume to identity.
|
||||||
mo->volumes.back()->set_transformation(Geometry::Transformation());
|
mo->volumes.back()->set_transformation(Geometry::Transformation());
|
||||||
|
|
||||||
mo->add_instance();
|
mo->add_instance();
|
||||||
if (!Slic3r::store_3mf(path_src.string().c_str(), &model, nullptr, false, nullptr, false)) {
|
if (!Slic3r::store_3mf(path_src.string().c_str(), &model, nullptr, false, nullptr, false)) {
|
||||||
boost::filesystem::remove(path_src);
|
boost::filesystem::remove(path_src);
|
||||||
throw Slic3r::RuntimeError(L("Export of a temporary 3mf file failed"));
|
throw Slic3r::RuntimeError(L("Export of a temporary 3mf file failed"));
|
||||||
}
|
}
|
||||||
model.clear_objects();
|
model.clear_objects();
|
||||||
model.clear_materials();
|
model.clear_materials();
|
||||||
boost::filesystem::path path_dst = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
boost::filesystem::path path_dst = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
||||||
path_dst += ".3mf";
|
path_dst += ".3mf";
|
||||||
fix_model_by_win10_sdk(path_src.string().c_str(), path_dst.string(), on_progress,
|
fix_model_by_win10_sdk(path_src.string().c_str(), path_dst.string(), on_progress,
|
||||||
[&canceled]() { if (canceled) throw RepairCanceledException(); });
|
[&canceled]() { if (canceled) throw RepairCanceledException(); });
|
||||||
boost::filesystem::remove(path_src);
|
boost::filesystem::remove(path_src);
|
||||||
// PresetBundle bundle;
|
// PresetBundle bundle;
|
||||||
on_progress(L("Loading repaired model"), 80);
|
on_progress(L("Loading repaired model"), 80);
|
||||||
DynamicPrintConfig config;
|
DynamicPrintConfig config;
|
||||||
ConfigSubstitutionContext config_substitutions{ ForwardCompatibilitySubstitutionRule::EnableSilent };
|
ConfigSubstitutionContext config_substitutions{ ForwardCompatibilitySubstitutionRule::EnableSilent };
|
||||||
bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), config, config_substitutions, &model, false);
|
bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), config, config_substitutions, &model, false);
|
||||||
boost::filesystem::remove(path_dst);
|
boost::filesystem::remove(path_dst);
|
||||||
if (! loaded)
|
if (! loaded)
|
||||||
throw Slic3r::RuntimeError(L("Import of the repaired 3mf file failed"));
|
throw Slic3r::RuntimeError(L("Import of the repaired 3mf file failed"));
|
||||||
if (model.objects.size() == 0)
|
if (model.objects.size() == 0)
|
||||||
throw Slic3r::RuntimeError(L("Repaired 3MF file does not contain any object"));
|
throw Slic3r::RuntimeError(L("Repaired 3MF file does not contain any object"));
|
||||||
if (model.objects.size() > 1)
|
if (model.objects.size() > 1)
|
||||||
throw Slic3r::RuntimeError(L("Repaired 3MF file contains more than one object"));
|
throw Slic3r::RuntimeError(L("Repaired 3MF file contains more than one object"));
|
||||||
if (model.objects.front()->volumes.size() == 0)
|
if (model.objects.front()->volumes.size() == 0)
|
||||||
throw Slic3r::RuntimeError(L("Repaired 3MF file does not contain any volume"));
|
throw Slic3r::RuntimeError(L("Repaired 3MF file does not contain any volume"));
|
||||||
if (model.objects.front()->volumes.size() > 1)
|
if (model.objects.front()->volumes.size() > 1)
|
||||||
throw Slic3r::RuntimeError(L("Repaired 3MF file contains more than one volume"));
|
throw Slic3r::RuntimeError(L("Repaired 3MF file contains more than one volume"));
|
||||||
meshes_repaired.emplace_back(std::move(model.objects.front()->volumes.front()->mesh()));
|
meshes_repaired.emplace_back(std::move(model.objects.front()->volumes.front()->mesh()));
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < volumes.size(); ++ i) {
|
for (size_t i = 0; i < volumes.size(); ++ i) {
|
||||||
volumes[i]->set_mesh(std::move(meshes_repaired[i]));
|
volumes[i]->set_mesh(std::move(meshes_repaired[i]));
|
||||||
volumes[i]->calculate_convex_hull();
|
volumes[i]->calculate_convex_hull();
|
||||||
volumes[i]->set_new_unique_id();
|
volumes[i]->set_new_unique_id();
|
||||||
}
|
}
|
||||||
model_object.invalidate_bounding_box();
|
model_object.invalidate_bounding_box();
|
||||||
-- ivolume;
|
-- ivolume;
|
||||||
on_progress(L("Model repair finished"), 100);
|
on_progress(L("Model repair finished"), 100);
|
||||||
success = true;
|
success = true;
|
||||||
finished = true;
|
finished = true;
|
||||||
} catch (RepairCanceledException & /* ex */) {
|
} catch (RepairCanceledException & /* ex */) {
|
||||||
canceled = true;
|
canceled = true;
|
||||||
finished = true;
|
finished = true;
|
||||||
on_progress(L("Model repair canceled"), 100);
|
on_progress(L("Model repair canceled"), 100);
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
success = false;
|
success = false;
|
||||||
finished = true;
|
finished = true;
|
||||||
on_progress(ex.what(), 100);
|
on_progress(ex.what(), 100);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
while (! finished) {
|
while (! finished) {
|
||||||
condition.wait_for(lock, std::chrono::milliseconds(250), [&progress]{ return progress.updated; });
|
condition.wait_for(lock, std::chrono::milliseconds(250), [&progress]{ return progress.updated; });
|
||||||
// decrease progress.percent value to avoid closing of the progress dialog
|
// decrease progress.percent value to avoid closing of the progress dialog
|
||||||
if (!progress_dialog.Update(progress.percent-1, msg_header + _(progress.message)))
|
if (!progress_dialog.Update(progress.percent-1, msg_header + _(progress.message)))
|
||||||
canceled = true;
|
canceled = true;
|
||||||
else
|
else
|
||||||
progress_dialog.Fit();
|
progress_dialog.Fit();
|
||||||
progress.updated = false;
|
progress.updated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
// Nothing to show.
|
// Nothing to show.
|
||||||
} else if (success) {
|
} else if (success) {
|
||||||
fix_result = "";
|
fix_result = "";
|
||||||
} else {
|
} else {
|
||||||
fix_result = progress.message;
|
fix_result = progress.message;
|
||||||
}
|
}
|
||||||
worker_thread.join();
|
worker_thread.join();
|
||||||
return !canceled;
|
return !canceled;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif /* HAS_WIN10SDK */
|
#endif /* HAS_WIN10SDK */
|
||||||
|
Loading…
Reference in New Issue
Block a user