mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-25 23:54:00 -06:00
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
This commit is contained in:
commit
2cc2c02a9c
15 changed files with 405 additions and 104 deletions
|
@ -60,21 +60,25 @@ PrinterTechnology get_printer_technology(const DynamicConfig &config)
|
||||||
|
|
||||||
int CLI::run(int argc, char **argv)
|
int CLI::run(int argc, char **argv)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
// Switch boost::filesystem to utf8.
|
// Switch boost::filesystem to utf8.
|
||||||
try {
|
try {
|
||||||
boost::nowide::nowide_filesystem();
|
boost::nowide::nowide_filesystem();
|
||||||
} catch (const std::runtime_error& ex) {
|
} catch (const std::runtime_error& ex) {
|
||||||
std::string caption = std::string(SLIC3R_APP_NAME) + " Error";
|
std::string caption = std::string(SLIC3R_APP_NAME) + " Error";
|
||||||
std::string text = std::string("An error occured while setting up locale.\n") + SLIC3R_APP_NAME + " will now terminate.\n\n" + ex.what();
|
std::string text = std::string("An error occured while setting up locale.\n") + (
|
||||||
#ifdef SLIC3R_GUI
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||||
|
// likely some linux system
|
||||||
|
"You may need to reconfigure the missing locales, likely by running the \"locale-gen\" and \"dpkg-reconfigure locales\" commands.\n"
|
||||||
|
#endif
|
||||||
|
SLIC3R_APP_NAME " will now terminate.\n\n") + ex.what();
|
||||||
|
#if defined(_WIN32) && defined(SLIC3R_GUI)
|
||||||
if (m_actions.empty())
|
if (m_actions.empty())
|
||||||
|
// Empty actions means Slicer is executed in the GUI mode. Show a GUI message.
|
||||||
MessageBoxA(NULL, text.c_str(), caption.c_str(), MB_OK | MB_ICONERROR);
|
MessageBoxA(NULL, text.c_str(), caption.c_str(), MB_OK | MB_ICONERROR);
|
||||||
#endif
|
#endif
|
||||||
boost::nowide::cerr << text.c_str() << std::endl;
|
boost::nowide::cerr << text.c_str() << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (! this->setup(argc, argv))
|
if (! this->setup(argc, argv))
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -426,7 +430,7 @@ int CLI::run(int argc, char **argv)
|
||||||
outfile_final = sla_print.print_statistics().finalize_output_path(outfile);
|
outfile_final = sla_print.print_statistics().finalize_output_path(outfile);
|
||||||
sla_print.export_raster(outfile_final);
|
sla_print.export_raster(outfile_final);
|
||||||
}
|
}
|
||||||
if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final) != 0) {
|
if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final)) {
|
||||||
boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl;
|
boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -607,7 +607,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||||
m_analyzer.reset();
|
m_analyzer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rename_file(path_tmp, path) != 0)
|
if (rename_file(path_tmp, path))
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + path + '\n' +
|
std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + path + '\n' +
|
||||||
"Is " + path_tmp + " locked?" + '\n');
|
"Is " + path_tmp + " locked?" + '\n');
|
||||||
|
|
|
@ -390,7 +390,7 @@ namespace Slic3r {
|
||||||
fclose(out);
|
fclose(out);
|
||||||
in.close();
|
in.close();
|
||||||
|
|
||||||
if (rename_file(path_tmp, filename) != 0)
|
if (rename_file(path_tmp, filename))
|
||||||
throw std::runtime_error(std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + filename + '\n' +
|
throw std::runtime_error(std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + filename + '\n' +
|
||||||
"Is " + path_tmp + " locked?" + '\n');
|
"Is " + path_tmp + " locked?" + '\n');
|
||||||
|
|
||||||
|
|
|
@ -2412,6 +2412,22 @@ void PrintConfigDef::init_sla_params()
|
||||||
def->mode = comExpert;
|
def->mode = comExpert;
|
||||||
def->set_default_value(new ConfigOptionInt(10));
|
def->set_default_value(new ConfigOptionInt(10));
|
||||||
|
|
||||||
|
def = this->add("min_exposure_time", coFloat);
|
||||||
|
def->label = L("Minimum exposure time");
|
||||||
|
def->tooltip = L("Minimum exposure time");
|
||||||
|
def->sidetext = L("s");
|
||||||
|
def->min = 0;
|
||||||
|
def->mode = comExpert;
|
||||||
|
def->set_default_value(new ConfigOptionFloat(0));
|
||||||
|
|
||||||
|
def = this->add("max_exposure_time", coFloat);
|
||||||
|
def->label = L("Maximum exposure time");
|
||||||
|
def->tooltip = L("Maximum exposure time");
|
||||||
|
def->sidetext = L("s");
|
||||||
|
def->min = 0;
|
||||||
|
def->mode = comExpert;
|
||||||
|
def->set_default_value(new ConfigOptionFloat(100));
|
||||||
|
|
||||||
def = this->add("exposure_time", coFloat);
|
def = this->add("exposure_time", coFloat);
|
||||||
def->label = L("Exposure time");
|
def->label = L("Exposure time");
|
||||||
def->tooltip = L("Exposure time");
|
def->tooltip = L("Exposure time");
|
||||||
|
@ -2419,6 +2435,22 @@ void PrintConfigDef::init_sla_params()
|
||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->set_default_value(new ConfigOptionFloat(10));
|
def->set_default_value(new ConfigOptionFloat(10));
|
||||||
|
|
||||||
|
def = this->add("min_initial_exposure_time", coFloat);
|
||||||
|
def->label = L("Minimum initial exposure time");
|
||||||
|
def->tooltip = L("Minimum initial exposure time");
|
||||||
|
def->sidetext = L("s");
|
||||||
|
def->min = 0;
|
||||||
|
def->mode = comExpert;
|
||||||
|
def->set_default_value(new ConfigOptionFloat(0));
|
||||||
|
|
||||||
|
def = this->add("max_initial_exposure_time", coFloat);
|
||||||
|
def->label = L("Maximum initial exposure time");
|
||||||
|
def->tooltip = L("Maximum initial exposure time");
|
||||||
|
def->sidetext = L("s");
|
||||||
|
def->min = 0;
|
||||||
|
def->mode = comExpert;
|
||||||
|
def->set_default_value(new ConfigOptionFloat(150));
|
||||||
|
|
||||||
def = this->add("initial_exposure_time", coFloat);
|
def = this->add("initial_exposure_time", coFloat);
|
||||||
def->label = L("Initial exposure time");
|
def->label = L("Initial exposure time");
|
||||||
def->tooltip = L("Initial exposure time");
|
def->tooltip = L("Initial exposure time");
|
||||||
|
|
|
@ -1131,6 +1131,10 @@ public:
|
||||||
ConfigOptionFloat fast_tilt_time;
|
ConfigOptionFloat fast_tilt_time;
|
||||||
ConfigOptionFloat slow_tilt_time;
|
ConfigOptionFloat slow_tilt_time;
|
||||||
ConfigOptionFloat area_fill;
|
ConfigOptionFloat area_fill;
|
||||||
|
ConfigOptionFloat min_exposure_time;
|
||||||
|
ConfigOptionFloat max_exposure_time;
|
||||||
|
ConfigOptionFloat min_initial_exposure_time;
|
||||||
|
ConfigOptionFloat max_initial_exposure_time;
|
||||||
protected:
|
protected:
|
||||||
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
void initialize(StaticCacheBase &cache, const char *base_ptr)
|
||||||
{
|
{
|
||||||
|
@ -1150,6 +1154,10 @@ protected:
|
||||||
OPT_PTR(fast_tilt_time);
|
OPT_PTR(fast_tilt_time);
|
||||||
OPT_PTR(slow_tilt_time);
|
OPT_PTR(slow_tilt_time);
|
||||||
OPT_PTR(area_fill);
|
OPT_PTR(area_fill);
|
||||||
|
OPT_PTR(min_exposure_time);
|
||||||
|
OPT_PTR(max_exposure_time);
|
||||||
|
OPT_PTR(min_initial_exposure_time);
|
||||||
|
OPT_PTR(max_initial_exposure_time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -692,6 +692,20 @@ std::string SLAPrint::validate() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double expt_max = m_printer_config.max_exposure_time.getFloat();
|
||||||
|
double expt_min = m_printer_config.min_exposure_time.getFloat();
|
||||||
|
double expt_cur = m_material_config.exposure_time.getFloat();
|
||||||
|
|
||||||
|
if (expt_cur < expt_min || expt_cur > expt_max)
|
||||||
|
return L("Exposition time is out of printer profile bounds.");
|
||||||
|
|
||||||
|
double iexpt_max = m_printer_config.max_initial_exposure_time.getFloat();
|
||||||
|
double iexpt_min = m_printer_config.min_initial_exposure_time.getFloat();
|
||||||
|
double iexpt_cur = m_material_config.initial_exposure_time.getFloat();
|
||||||
|
|
||||||
|
if (iexpt_cur < iexpt_min || iexpt_cur > iexpt_max)
|
||||||
|
return L("Initial exposition time is out of printer profile bounds.");
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1586,7 +1600,11 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
|
||||||
// Cache the plenty of parameters, which influence the final rasterization only,
|
// Cache the plenty of parameters, which influence the final rasterization only,
|
||||||
// or they are only notes not influencing the rasterization step.
|
// or they are only notes not influencing the rasterization step.
|
||||||
static std::unordered_set<std::string> steps_rasterize = {
|
static std::unordered_set<std::string> steps_rasterize = {
|
||||||
|
"min_exposure_time",
|
||||||
|
"max_exposure_time",
|
||||||
"exposure_time",
|
"exposure_time",
|
||||||
|
"min_initial_exposure_time",
|
||||||
|
"max_initial_exposure_time",
|
||||||
"initial_exposure_time",
|
"initial_exposure_time",
|
||||||
"display_width",
|
"display_width",
|
||||||
"display_height",
|
"display_height",
|
||||||
|
|
|
@ -61,7 +61,7 @@ extern std::string normalize_utf8_nfc(const char *src);
|
||||||
// Safely rename a file even if the target exists.
|
// Safely rename a file even if the target exists.
|
||||||
// On Windows, the file explorer (or anti-virus or whatever else) often locks the file
|
// On Windows, the file explorer (or anti-virus or whatever else) often locks the file
|
||||||
// for a short while, so the file may not be movable. Retry while we see recoverable errors.
|
// for a short while, so the file may not be movable. Retry while we see recoverable errors.
|
||||||
extern int rename_file(const std::string &from, const std::string &to);
|
extern std::error_code rename_file(const std::string &from, const std::string &to);
|
||||||
|
|
||||||
// Copy a file, adjust the access attributes, so that the target is writable.
|
// Copy a file, adjust the access attributes, so that the target is writable.
|
||||||
extern int copy_file(const std::string &from, const std::string &to);
|
extern int copy_file(const std::string &from, const std::string &to);
|
||||||
|
|
|
@ -173,67 +173,247 @@ const std::string& data_dir()
|
||||||
return g_data_dir;
|
return g_data_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// The following helpers are borrowed from the LLVM project https://github.com/llvm
|
||||||
|
namespace WindowsSupport
|
||||||
|
{
|
||||||
|
template <typename HandleTraits>
|
||||||
|
class ScopedHandle {
|
||||||
|
typedef typename HandleTraits::handle_type handle_type;
|
||||||
|
handle_type Handle;
|
||||||
|
ScopedHandle(const ScopedHandle &other) = delete;
|
||||||
|
void operator=(const ScopedHandle &other) = delete;
|
||||||
|
public:
|
||||||
|
ScopedHandle() : Handle(HandleTraits::GetInvalid()) {}
|
||||||
|
explicit ScopedHandle(handle_type h) : Handle(h) {}
|
||||||
|
~ScopedHandle() { if (HandleTraits::IsValid(Handle)) HandleTraits::Close(Handle); }
|
||||||
|
handle_type take() {
|
||||||
|
handle_type t = Handle;
|
||||||
|
Handle = HandleTraits::GetInvalid();
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
ScopedHandle &operator=(handle_type h) {
|
||||||
|
if (HandleTraits::IsValid(Handle))
|
||||||
|
HandleTraits::Close(Handle);
|
||||||
|
Handle = h;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
// True if Handle is valid.
|
||||||
|
explicit operator bool() const { return HandleTraits::IsValid(Handle) ? true : false; }
|
||||||
|
operator handle_type() const { return Handle; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CommonHandleTraits {
|
||||||
|
typedef HANDLE handle_type;
|
||||||
|
static handle_type GetInvalid() { return INVALID_HANDLE_VALUE; }
|
||||||
|
static void Close(handle_type h) { ::CloseHandle(h); }
|
||||||
|
static bool IsValid(handle_type h) { return h != GetInvalid(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef ScopedHandle<CommonHandleTraits> ScopedFileHandle;
|
||||||
|
|
||||||
|
std::error_code map_windows_error(unsigned windows_error_code)
|
||||||
|
{
|
||||||
|
#define MAP_ERR_TO_COND(x, y) case x: return std::make_error_code(std::errc::y)
|
||||||
|
switch (windows_error_code) {
|
||||||
|
MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
|
||||||
|
MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
|
||||||
|
MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
|
||||||
|
MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
|
||||||
|
MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
|
||||||
|
MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
|
||||||
|
MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied);
|
||||||
|
MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error);
|
||||||
|
MAP_ERR_TO_COND(ERROR_CANTREAD, io_error);
|
||||||
|
MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error);
|
||||||
|
MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied);
|
||||||
|
MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device);
|
||||||
|
MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy);
|
||||||
|
MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty);
|
||||||
|
MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument);
|
||||||
|
MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device);
|
||||||
|
MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists);
|
||||||
|
MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory);
|
||||||
|
MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device);
|
||||||
|
MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied);
|
||||||
|
MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device);
|
||||||
|
MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
|
||||||
|
MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
|
||||||
|
MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument);
|
||||||
|
MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available);
|
||||||
|
MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available);
|
||||||
|
MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument);
|
||||||
|
MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied);
|
||||||
|
MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory);
|
||||||
|
MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again);
|
||||||
|
MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error);
|
||||||
|
MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
|
||||||
|
MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
|
||||||
|
MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
|
||||||
|
MAP_ERR_TO_COND(ERROR_BAD_NETPATH, no_such_file_or_directory);
|
||||||
|
MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
|
||||||
|
MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
|
||||||
|
MAP_ERR_TO_COND(ERROR_SEEK, io_error);
|
||||||
|
MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
|
||||||
|
MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open);
|
||||||
|
MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error);
|
||||||
|
MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied);
|
||||||
|
MAP_ERR_TO_COND(WSAEACCES, permission_denied);
|
||||||
|
MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor);
|
||||||
|
MAP_ERR_TO_COND(WSAEFAULT, bad_address);
|
||||||
|
MAP_ERR_TO_COND(WSAEINTR, interrupted);
|
||||||
|
MAP_ERR_TO_COND(WSAEINVAL, invalid_argument);
|
||||||
|
MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open);
|
||||||
|
MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long);
|
||||||
|
default:
|
||||||
|
return std::error_code(windows_error_code, std::system_category());
|
||||||
|
}
|
||||||
|
#undef MAP_ERR_TO_COND
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::error_code rename_internal(HANDLE from_handle, const std::wstring &wide_to, bool replace_if_exists)
|
||||||
|
{
|
||||||
|
std::vector<char> rename_info_buf(sizeof(FILE_RENAME_INFO) - sizeof(wchar_t) + (wide_to.size() * sizeof(wchar_t)));
|
||||||
|
FILE_RENAME_INFO &rename_info = *reinterpret_cast<FILE_RENAME_INFO*>(rename_info_buf.data());
|
||||||
|
rename_info.ReplaceIfExists = replace_if_exists;
|
||||||
|
rename_info.RootDirectory = 0;
|
||||||
|
rename_info.FileNameLength = DWORD(wide_to.size() * sizeof(wchar_t));
|
||||||
|
std::copy(wide_to.begin(), wide_to.end(), &rename_info.FileName[0]);
|
||||||
|
|
||||||
|
::SetLastError(ERROR_SUCCESS);
|
||||||
|
if (! ::SetFileInformationByHandle(from_handle, FileRenameInfo, &rename_info, (DWORD)rename_info_buf.size())) {
|
||||||
|
unsigned Error = GetLastError();
|
||||||
|
if (Error == ERROR_SUCCESS)
|
||||||
|
Error = ERROR_CALL_NOT_IMPLEMENTED; // Wine doesn't always set error code.
|
||||||
|
return map_windows_error(Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::error_code();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::error_code real_path_from_handle(HANDLE H, std::wstring &buffer)
|
||||||
|
{
|
||||||
|
buffer.resize(MAX_PATH + 1);
|
||||||
|
DWORD CountChars = ::GetFinalPathNameByHandleW(H, (LPWSTR)buffer.data(), (DWORD)buffer.size() - 1, FILE_NAME_NORMALIZED);
|
||||||
|
if (CountChars > buffer.size()) {
|
||||||
|
// The buffer wasn't big enough, try again. In this case the return value *does* indicate the size of the null terminator.
|
||||||
|
buffer.resize((size_t)CountChars);
|
||||||
|
CountChars = ::GetFinalPathNameByHandleW(H, (LPWSTR)buffer.data(), (DWORD)buffer.size() - 1, FILE_NAME_NORMALIZED);
|
||||||
|
}
|
||||||
|
if (CountChars == 0)
|
||||||
|
return map_windows_error(GetLastError());
|
||||||
|
buffer.resize(CountChars);
|
||||||
|
return std::error_code();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::error_code rename(const std::string &from, const std::string &to)
|
||||||
|
{
|
||||||
|
// Convert to utf-16.
|
||||||
|
std::wstring wide_from = boost::nowide::widen(from);
|
||||||
|
std::wstring wide_to = boost::nowide::widen(to);
|
||||||
|
|
||||||
|
ScopedFileHandle from_handle;
|
||||||
|
// Retry this a few times to defeat badly behaved file system scanners.
|
||||||
|
for (unsigned retry = 0; retry != 200; ++ retry) {
|
||||||
|
if (retry != 0)
|
||||||
|
::Sleep(10);
|
||||||
|
from_handle = ::CreateFileW((LPWSTR)wide_from.data(), GENERIC_READ | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (from_handle)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (! from_handle)
|
||||||
|
return map_windows_error(GetLastError());
|
||||||
|
|
||||||
|
// We normally expect this loop to succeed after a few iterations. If it
|
||||||
|
// requires more than 200 tries, it's more likely that the failures are due to
|
||||||
|
// a true error, so stop trying.
|
||||||
|
for (unsigned retry = 0; retry != 200; ++ retry) {
|
||||||
|
auto errcode = rename_internal(from_handle, wide_to, true);
|
||||||
|
|
||||||
|
if (errcode == std::error_code(ERROR_CALL_NOT_IMPLEMENTED, std::system_category())) {
|
||||||
|
// Wine doesn't support SetFileInformationByHandle in rename_internal.
|
||||||
|
// Fall back to MoveFileEx.
|
||||||
|
if (std::error_code errcode2 = real_path_from_handle(from_handle, wide_from))
|
||||||
|
return errcode2;
|
||||||
|
if (::MoveFileExW((LPCWSTR)wide_from.data(), (LPCWSTR)wide_to.data(), MOVEFILE_REPLACE_EXISTING))
|
||||||
|
return std::error_code();
|
||||||
|
return map_windows_error(GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! errcode || errcode != std::errc::permission_denied)
|
||||||
|
return errcode;
|
||||||
|
|
||||||
|
// The destination file probably exists and is currently open in another
|
||||||
|
// process, either because the file was opened without FILE_SHARE_DELETE or
|
||||||
|
// it is mapped into memory (e.g. using MemoryBuffer). Rename it in order to
|
||||||
|
// move it out of the way of the source file. Use FILE_FLAG_DELETE_ON_CLOSE
|
||||||
|
// to arrange for the destination file to be deleted when the other process
|
||||||
|
// closes it.
|
||||||
|
ScopedFileHandle to_handle(::CreateFileW((LPCWSTR)wide_to.data(), GENERIC_READ | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL));
|
||||||
|
if (! to_handle) {
|
||||||
|
auto errcode = map_windows_error(GetLastError());
|
||||||
|
// Another process might have raced with us and moved the existing file
|
||||||
|
// out of the way before we had a chance to open it. If that happens, try
|
||||||
|
// to rename the source file again.
|
||||||
|
if (errcode == std::errc::no_such_file_or_directory)
|
||||||
|
continue;
|
||||||
|
return errcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
BY_HANDLE_FILE_INFORMATION FI;
|
||||||
|
if (! ::GetFileInformationByHandle(to_handle, &FI))
|
||||||
|
return map_windows_error(GetLastError());
|
||||||
|
|
||||||
|
// Try to find a unique new name for the destination file.
|
||||||
|
for (unsigned unique_id = 0; unique_id != 200; ++ unique_id) {
|
||||||
|
std::wstring tmp_filename = wide_to + L".tmp" + std::to_wstring(unique_id);
|
||||||
|
std::error_code errcode = rename_internal(to_handle, tmp_filename, false);
|
||||||
|
if (errcode) {
|
||||||
|
if (errcode == std::make_error_code(std::errc::file_exists) || errcode == std::make_error_code(std::errc::permission_denied)) {
|
||||||
|
// Again, another process might have raced with us and moved the file
|
||||||
|
// before we could move it. Check whether this is the case, as it
|
||||||
|
// might have caused the permission denied error. If that was the
|
||||||
|
// case, we don't need to move it ourselves.
|
||||||
|
ScopedFileHandle to_handle2(::CreateFileW((LPCWSTR)wide_to.data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
|
||||||
|
if (! to_handle2) {
|
||||||
|
auto errcode = map_windows_error(GetLastError());
|
||||||
|
if (errcode == std::errc::no_such_file_or_directory)
|
||||||
|
break;
|
||||||
|
return errcode;
|
||||||
|
}
|
||||||
|
BY_HANDLE_FILE_INFORMATION FI2;
|
||||||
|
if (! ::GetFileInformationByHandle(to_handle2, &FI2))
|
||||||
|
return map_windows_error(GetLastError());
|
||||||
|
if (FI.nFileIndexHigh != FI2.nFileIndexHigh || FI.nFileIndexLow != FI2.nFileIndexLow || FI.dwVolumeSerialNumber != FI2.dwVolumeSerialNumber)
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return errcode;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Okay, the old destination file has probably been moved out of the way at
|
||||||
|
// this point, so try to rename the source file again. Still, another
|
||||||
|
// process might have raced with us to create and open the destination
|
||||||
|
// file, so we need to keep doing this until we succeed.
|
||||||
|
}
|
||||||
|
|
||||||
|
// The most likely root cause.
|
||||||
|
return std::make_error_code(std::errc::permission_denied);
|
||||||
|
}
|
||||||
|
} // namespace WindowsSupport
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
// borrowed from LVVM lib/Support/Windows/Path.inc
|
// borrowed from LVVM lib/Support/Windows/Path.inc
|
||||||
int rename_file(const std::string &from, const std::string &to)
|
std::error_code rename_file(const std::string &from, const std::string &to)
|
||||||
{
|
{
|
||||||
int ec = 0;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
return WindowsSupport::rename(from, to);
|
||||||
// Convert to utf-16.
|
|
||||||
std::wstring wide_from = boost::nowide::widen(from);
|
|
||||||
std::wstring wide_to = boost::nowide::widen(to);
|
|
||||||
|
|
||||||
// Retry while we see recoverable errors.
|
|
||||||
// System scanners (eg. indexer) might open the source file when it is written
|
|
||||||
// and closed.
|
|
||||||
bool TryReplace = true;
|
|
||||||
|
|
||||||
// This loop may take more than 2000 x 1ms to finish.
|
|
||||||
for (int i = 0; i < 2000; ++ i) {
|
|
||||||
if (i > 0)
|
|
||||||
// Sleep 1ms
|
|
||||||
::Sleep(1);
|
|
||||||
if (TryReplace) {
|
|
||||||
// Try ReplaceFile first, as it is able to associate a new data stream
|
|
||||||
// with the destination even if the destination file is currently open.
|
|
||||||
if (::ReplaceFileW(wide_to.data(), wide_from.data(), NULL, 0, NULL, NULL))
|
|
||||||
return 0;
|
|
||||||
DWORD ReplaceError = ::GetLastError();
|
|
||||||
ec = -1; // ReplaceError
|
|
||||||
// If ReplaceFileW returned ERROR_UNABLE_TO_MOVE_REPLACEMENT or
|
|
||||||
// ERROR_UNABLE_TO_MOVE_REPLACEMENT_2, retry but only use MoveFileExW().
|
|
||||||
if (ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT ||
|
|
||||||
ReplaceError == ERROR_UNABLE_TO_MOVE_REPLACEMENT_2) {
|
|
||||||
TryReplace = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// If ReplaceFileW returned ERROR_UNABLE_TO_REMOVE_REPLACED, retry
|
|
||||||
// using ReplaceFileW().
|
|
||||||
if (ReplaceError == ERROR_UNABLE_TO_REMOVE_REPLACED)
|
|
||||||
continue;
|
|
||||||
// We get ERROR_FILE_NOT_FOUND if the destination file is missing.
|
|
||||||
// MoveFileEx can handle this case.
|
|
||||||
if (ReplaceError != ERROR_ACCESS_DENIED && ReplaceError != ERROR_FILE_NOT_FOUND && ReplaceError != ERROR_SHARING_VIOLATION)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (::MoveFileExW(wide_from.c_str(), wide_to.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
|
|
||||||
return 0;
|
|
||||||
DWORD MoveError = ::GetLastError();
|
|
||||||
ec = -1; // MoveError
|
|
||||||
if (MoveError != ERROR_ACCESS_DENIED && MoveError != ERROR_SHARING_VIOLATION)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
boost::nowide::remove(to.c_str());
|
boost::nowide::remove(to.c_str());
|
||||||
ec = boost::nowide::rename(from.c_str(), to.c_str());
|
return std::make_error_code(static_cast<std::errc>(boost::nowide::rename(from.c_str(), to.c_str())));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int copy_file(const std::string &from, const std::string &to)
|
int copy_file(const std::string &from, const std::string &to)
|
||||||
|
|
|
@ -98,9 +98,10 @@ void AppConfig::load()
|
||||||
pt::read_ini(ifs, tree);
|
pt::read_ini(ifs, tree);
|
||||||
} catch (pt::ptree_error& ex) {
|
} catch (pt::ptree_error& ex) {
|
||||||
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
|
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
|
||||||
throw std::runtime_error(wxString::Format(_(L("Error parsing config file, it is probably corrupted. "
|
throw std::runtime_error(
|
||||||
"Try to manualy delete the file. Your user profiles will not be affected.\n\n%s\n\n%s")),
|
_utf8(L("Error parsing PrusaSlicer config file, it is probably corrupted. "
|
||||||
AppConfig::config_path(), ex.what()).ToStdString());
|
"Try to manualy delete the file to recover from the error. Your user profiles will not be affected.")) +
|
||||||
|
"\n\n" + AppConfig::config_path() + "\n\n" + ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) Parse the property_tree, extract the sections and key / value pairs.
|
// 2) Parse the property_tree, extract the sections and key / value pairs.
|
||||||
|
|
|
@ -293,6 +293,20 @@ bool GUI_App::on_init_inner()
|
||||||
config_wizard_startup(app_conf_exists);
|
config_wizard_startup(app_conf_exists);
|
||||||
preset_updater->slic3r_update_notify();
|
preset_updater->slic3r_update_notify();
|
||||||
preset_updater->sync(preset_bundle);
|
preset_updater->sync(preset_bundle);
|
||||||
|
const GLCanvas3DManager::GLInfo &glinfo = GLCanvas3DManager::get_gl_info();
|
||||||
|
if (! glinfo.is_version_greater_or_equal_to(2, 0)) {
|
||||||
|
// Complain about the OpenGL version.
|
||||||
|
wxString message = wxString::Format(
|
||||||
|
_(L("PrusaSlicer requires OpenGL 2.0 capable graphics driver to run correctly, \n"
|
||||||
|
"while OpenGL version %s, render %s, vendor %s was detected.")), wxString(glinfo.get_version()), wxString(glinfo.get_renderer()), wxString(glinfo.get_vendor()));
|
||||||
|
message += "\n";
|
||||||
|
message += _(L("You may need to update your graphics card driver."));
|
||||||
|
#ifdef _WIN32
|
||||||
|
message += "\n";
|
||||||
|
message += _(L("As a workaround, you may run PrusaSlicer with a software rendered 3D graphics by running prusa-slicer.exe with the --sw_renderer parameter."));
|
||||||
|
#endif
|
||||||
|
wxMessageBox(message, wxString("PrusaSlicer - ") + _(L("Unsupported OpenGL version")), wxOK | wxICON_ERROR);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -153,8 +153,8 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||||
|
|
||||||
auto manifold_warning_icon = [this](wxWindow* parent) {
|
auto manifold_warning_icon = [this](wxWindow* parent) {
|
||||||
m_fix_throught_netfab_bitmap = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap);
|
m_fix_throught_netfab_bitmap = new wxStaticBitmap(parent, wxID_ANY, wxNullBitmap);
|
||||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
// auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
sizer->Add(m_fix_throught_netfab_bitmap);
|
// sizer->Add(m_fix_throught_netfab_bitmap);
|
||||||
|
|
||||||
if (is_windows10())
|
if (is_windows10())
|
||||||
m_fix_throught_netfab_bitmap->Bind(wxEVT_CONTEXT_MENU, [this](wxCommandEvent &e)
|
m_fix_throught_netfab_bitmap->Bind(wxEVT_CONTEXT_MENU, [this](wxCommandEvent &e)
|
||||||
|
@ -167,17 +167,19 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||||
update_warning_icon_state(wxGetApp().obj_list()->get_mesh_errors_list());
|
update_warning_icon_state(wxGetApp().obj_list()->get_mesh_errors_list());
|
||||||
});
|
});
|
||||||
|
|
||||||
return sizer;
|
// return sizer;
|
||||||
|
return m_fix_throught_netfab_bitmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
line.append_widget(manifold_warning_icon);
|
// line.append_widget(manifold_warning_icon);
|
||||||
|
line.near_label_widget = manifold_warning_icon;
|
||||||
def.label = "";
|
def.label = "";
|
||||||
def.gui_type = "legend";
|
def.gui_type = "legend";
|
||||||
def.tooltip = L("Object name");
|
def.tooltip = L("Object name");
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
def.width = 19;
|
def.width = 20;
|
||||||
#else
|
#else
|
||||||
def.width = 21;
|
def.width = 22;
|
||||||
#endif
|
#endif
|
||||||
def.set_default_value(new ConfigOptionString{ " " });
|
def.set_default_value(new ConfigOptionString{ " " });
|
||||||
line.append_option(Option(def, "object_name"));
|
line.append_option(Option(def, "object_name"));
|
||||||
|
@ -392,10 +394,19 @@ ObjectManipulation::ObjectManipulation(wxWindow* parent) :
|
||||||
|
|
||||||
// call back for a rescale of button "Set uniform scale"
|
// call back for a rescale of button "Set uniform scale"
|
||||||
m_og->rescale_near_label_widget = [this](wxWindow* win) {
|
m_og->rescale_near_label_widget = [this](wxWindow* win) {
|
||||||
|
// rescale lock icon
|
||||||
auto *ctrl = dynamic_cast<LockButton*>(win);
|
auto *ctrl = dynamic_cast<LockButton*>(win);
|
||||||
if (ctrl == nullptr)
|
if (ctrl != nullptr) {
|
||||||
|
ctrl->msw_rescale();
|
||||||
return;
|
return;
|
||||||
ctrl->msw_rescale();
|
}
|
||||||
|
|
||||||
|
if (win == m_fix_throught_netfab_bitmap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// rescale "place" of the empty icon (to correct layout of the "Size" and "Scale")
|
||||||
|
if (dynamic_cast<wxStaticBitmap*>(win) != nullptr)
|
||||||
|
win->SetMinSize(create_scaled_bitmap(m_parent, "one_layer_lock_on.png").GetSize());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -685,6 +696,7 @@ void ObjectManipulation::emulate_kill_focus()
|
||||||
void ObjectManipulation::update_warning_icon_state(const wxString& tooltip)
|
void ObjectManipulation::update_warning_icon_state(const wxString& tooltip)
|
||||||
{
|
{
|
||||||
m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp.bmp());
|
m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp.bmp());
|
||||||
|
m_fix_throught_netfab_bitmap->SetMinSize(tooltip.IsEmpty() ? wxSize(0,0) : m_manifold_warning_bmp.bmp().GetSize());
|
||||||
m_fix_throught_netfab_bitmap->SetToolTip(tooltip);
|
m_fix_throught_netfab_bitmap->SetToolTip(tooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,7 +931,10 @@ void ObjectManipulation::msw_rescale()
|
||||||
{
|
{
|
||||||
msw_rescale_word_local_combo(m_word_local_combo);
|
msw_rescale_word_local_combo(m_word_local_combo);
|
||||||
m_manifold_warning_bmp.msw_rescale();
|
m_manifold_warning_bmp.msw_rescale();
|
||||||
m_fix_throught_netfab_bitmap->SetBitmap(m_manifold_warning_bmp.bmp());
|
|
||||||
|
const wxString& tooltip = m_fix_throught_netfab_bitmap->GetToolTipText();
|
||||||
|
m_fix_throught_netfab_bitmap->SetBitmap(tooltip.IsEmpty() ? wxNullBitmap : m_manifold_warning_bmp.bmp());
|
||||||
|
m_fix_throught_netfab_bitmap->SetMinSize(tooltip.IsEmpty() ? wxSize(0, 0) : m_manifold_warning_bmp.bmp().GetSize());
|
||||||
|
|
||||||
m_mirror_bitmap_on.msw_rescale();
|
m_mirror_bitmap_on.msw_rescale();
|
||||||
m_mirror_bitmap_off.msw_rescale();
|
m_mirror_bitmap_off.msw_rescale();
|
||||||
|
|
|
@ -64,6 +64,12 @@ public:
|
||||||
m_prev_scale_factor = m_scale_factor;
|
m_prev_scale_factor = m_scale_factor;
|
||||||
m_normal_font = get_default_font_for_dpi(dpi);
|
m_normal_font = get_default_font_for_dpi(dpi);
|
||||||
|
|
||||||
|
/* Because of default window font is a primary display font,
|
||||||
|
* We should set correct font for window before getting em_unit value.
|
||||||
|
*/
|
||||||
|
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
|
||||||
|
this->SetFont(m_normal_font);
|
||||||
|
#endif
|
||||||
// initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
|
// initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
|
||||||
m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
|
m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
|
||||||
|
|
||||||
|
@ -72,6 +78,8 @@ public:
|
||||||
this->Bind(EVT_DPI_CHANGED, [this](const DpiChangedEvent &evt) {
|
this->Bind(EVT_DPI_CHANGED, [this](const DpiChangedEvent &evt) {
|
||||||
m_scale_factor = (float)evt.dpi / (float)DPI_DEFAULT;
|
m_scale_factor = (float)evt.dpi / (float)DPI_DEFAULT;
|
||||||
|
|
||||||
|
m_new_font_point_size = get_default_font_for_dpi(evt.dpi).GetPointSize();
|
||||||
|
|
||||||
if (!m_can_rescale)
|
if (!m_can_rescale)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -124,6 +132,8 @@ private:
|
||||||
float m_prev_scale_factor;
|
float m_prev_scale_factor;
|
||||||
bool m_can_rescale{ true };
|
bool m_can_rescale{ true };
|
||||||
|
|
||||||
|
int m_new_font_point_size;
|
||||||
|
|
||||||
// void recalc_font()
|
// void recalc_font()
|
||||||
// {
|
// {
|
||||||
// wxClientDC dc(this);
|
// wxClientDC dc(this);
|
||||||
|
@ -135,14 +145,22 @@ private:
|
||||||
// check if new scale is differ from previous
|
// check if new scale is differ from previous
|
||||||
bool is_new_scale_factor() const { return fabs(m_scale_factor - m_prev_scale_factor) > 0.001; }
|
bool is_new_scale_factor() const { return fabs(m_scale_factor - m_prev_scale_factor) > 0.001; }
|
||||||
|
|
||||||
|
// function for a font scaling of the window
|
||||||
|
void scale_win_font(wxWindow *window, const int font_point_size)
|
||||||
|
{
|
||||||
|
wxFont new_font(window->GetFont());
|
||||||
|
new_font.SetPointSize(font_point_size);
|
||||||
|
window->SetFont(new_font);
|
||||||
|
}
|
||||||
|
|
||||||
// recursive function for scaling fonts for all controls in Window
|
// recursive function for scaling fonts for all controls in Window
|
||||||
void scale_controls_fonts(wxWindow *window, const float scale_f)
|
void scale_controls_fonts(wxWindow *window, const int font_point_size)
|
||||||
{
|
{
|
||||||
auto children = window->GetChildren();
|
auto children = window->GetChildren();
|
||||||
|
|
||||||
for (auto child : children) {
|
for (auto child : children) {
|
||||||
scale_controls_fonts(child, scale_f);
|
scale_controls_fonts(child, font_point_size);
|
||||||
child->SetFont(child->GetFont().Scaled(scale_f));
|
scale_win_font(child, font_point_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
window->Layout();
|
window->Layout();
|
||||||
|
@ -151,18 +169,18 @@ private:
|
||||||
void rescale(const wxRect &suggested_rect)
|
void rescale(const wxRect &suggested_rect)
|
||||||
{
|
{
|
||||||
this->Freeze();
|
this->Freeze();
|
||||||
const float relative_scale_factor = m_scale_factor / m_prev_scale_factor;
|
|
||||||
|
|
||||||
// rescale fonts of all controls
|
// rescale fonts of all controls
|
||||||
scale_controls_fonts(this, relative_scale_factor);
|
scale_controls_fonts(this, m_new_font_point_size);
|
||||||
this->SetFont(this->GetFont().Scaled(relative_scale_factor));
|
// rescale current window font
|
||||||
|
scale_win_font(this, m_new_font_point_size);
|
||||||
|
|
||||||
|
|
||||||
// rescale normal_font value
|
// set normal application font as a current window font
|
||||||
m_normal_font = m_normal_font.Scaled(relative_scale_factor);
|
m_normal_font = this->GetFont();
|
||||||
|
|
||||||
// An analog of em_unit value from GUI_App.
|
// update em_unit value for new window font
|
||||||
m_em_unit = std::max<size_t>(10, 10 * m_scale_factor);
|
m_em_unit = std::max<size_t>(10, this->GetTextExtent("m").x - 1);
|
||||||
|
|
||||||
// rescale missed controls sizes and images
|
// rescale missed controls sizes and images
|
||||||
on_dpi_changed(suggested_rect);
|
on_dpi_changed(suggested_rect);
|
||||||
|
|
|
@ -39,10 +39,12 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
||||||
{
|
{
|
||||||
// Fonts were created by the DPIFrame constructor for the monitor, on which the window opened.
|
// Fonts were created by the DPIFrame constructor for the monitor, on which the window opened.
|
||||||
wxGetApp().update_fonts(this);
|
wxGetApp().update_fonts(this);
|
||||||
|
/*
|
||||||
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
|
#ifndef __WXOSX__ // Don't call SetFont under OSX to avoid name cutting in ObjectList
|
||||||
this->SetFont(this->normal_font());
|
this->SetFont(this->normal_font());
|
||||||
#endif
|
#endif
|
||||||
|
// Font is already set in DPIFrame constructor
|
||||||
|
*/
|
||||||
// Load the icon either from the exe, or from the ico file.
|
// Load the icon either from the exe, or from the ico file.
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
{
|
{
|
||||||
|
|
|
@ -500,7 +500,8 @@ const std::vector<std::string>& Preset::sla_material_options()
|
||||||
if (s_opts.empty()) {
|
if (s_opts.empty()) {
|
||||||
s_opts = {
|
s_opts = {
|
||||||
"initial_layer_height",
|
"initial_layer_height",
|
||||||
"exposure_time", "initial_exposure_time",
|
"exposure_time",
|
||||||
|
"initial_exposure_time",
|
||||||
"material_correction",
|
"material_correction",
|
||||||
"material_notes",
|
"material_notes",
|
||||||
"default_sla_material_profile",
|
"default_sla_material_profile",
|
||||||
|
@ -526,6 +527,8 @@ const std::vector<std::string>& Preset::sla_printer_options()
|
||||||
"relative_correction",
|
"relative_correction",
|
||||||
"absolute_correction",
|
"absolute_correction",
|
||||||
"gamma_correction",
|
"gamma_correction",
|
||||||
|
"min_exposure_time", "max_exposure_time",
|
||||||
|
"min_initial_exposure_time", "max_initial_exposure_time",
|
||||||
"print_host", "printhost_apikey", "printhost_cafile",
|
"print_host", "printhost_apikey", "printhost_cafile",
|
||||||
"printer_notes",
|
"printer_notes",
|
||||||
"inherits"
|
"inherits"
|
||||||
|
|
|
@ -838,7 +838,7 @@ static wxString support_combo_value_for_config(const DynamicPrintConfig &config,
|
||||||
|
|
||||||
static wxString pad_combo_value_for_config(const DynamicPrintConfig &config)
|
static wxString pad_combo_value_for_config(const DynamicPrintConfig &config)
|
||||||
{
|
{
|
||||||
return config.opt_bool("pad_enable") ? (config.opt_bool("pad_zero_elevation") ? _("Around object") : _("Below object")) : _("None");
|
return config.opt_bool("pad_enable") ? (config.opt_bool("pad_zero_elevation") ? _("Around object") : _("Below object")) : _("None");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
||||||
|
@ -860,8 +860,8 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
||||||
(opt_key == "supports_enable" || opt_key == "support_buildplate_only"))
|
(opt_key == "supports_enable" || opt_key == "support_buildplate_only"))
|
||||||
og_freq_chng_params->set_value("support", support_combo_value_for_config(*m_config, is_fff));
|
og_freq_chng_params->set_value("support", support_combo_value_for_config(*m_config, is_fff));
|
||||||
|
|
||||||
if (! is_fff && (opt_key == "pad_enable" || opt_key == "pad_zero_elevation"))
|
if (! is_fff && (opt_key == "pad_enable" || opt_key == "pad_zero_elevation"))
|
||||||
og_freq_chng_params->set_value("pad", pad_combo_value_for_config(*m_config));
|
og_freq_chng_params->set_value("pad", pad_combo_value_for_config(*m_config));
|
||||||
|
|
||||||
if (opt_key == "brim_width")
|
if (opt_key == "brim_width")
|
||||||
{
|
{
|
||||||
|
@ -998,7 +998,7 @@ void Tab::update_frequently_changed_parameters()
|
||||||
|
|
||||||
og_freq_chng_params->set_value("support", support_combo_value_for_config(*m_config, is_fff));
|
og_freq_chng_params->set_value("support", support_combo_value_for_config(*m_config, is_fff));
|
||||||
if (! is_fff)
|
if (! is_fff)
|
||||||
og_freq_chng_params->set_value("pad", pad_combo_value_for_config(*m_config));
|
og_freq_chng_params->set_value("pad", pad_combo_value_for_config(*m_config));
|
||||||
|
|
||||||
const std::string updated_value_key = is_fff ? "fill_density" : "pad_enable";
|
const std::string updated_value_key = is_fff ? "fill_density" : "pad_enable";
|
||||||
|
|
||||||
|
@ -1772,13 +1772,13 @@ void TabFilament::reload_config()
|
||||||
|
|
||||||
void TabFilament::update_volumetric_flow_preset_hints()
|
void TabFilament::update_volumetric_flow_preset_hints()
|
||||||
{
|
{
|
||||||
wxString text;
|
wxString text;
|
||||||
try {
|
try {
|
||||||
text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle));
|
text = from_u8(PresetHints::maximum_volumetric_flow_description(*m_preset_bundle));
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
text = _(L("Volumetric flow hints not available\n\n")) + from_u8(ex.what());
|
text = _(L("Volumetric flow hints not available\n\n")) + from_u8(ex.what());
|
||||||
}
|
}
|
||||||
m_volumetric_speed_description_line->SetText(text);
|
m_volumetric_speed_description_line->SetText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabFilament::update()
|
void TabFilament::update()
|
||||||
|
@ -1788,9 +1788,9 @@ void TabFilament::update()
|
||||||
|
|
||||||
m_update_cnt++;
|
m_update_cnt++;
|
||||||
|
|
||||||
wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset()));
|
wxString text = from_u8(PresetHints::cooling_description(m_presets->get_edited_preset()));
|
||||||
m_cooling_description_line->SetText(text);
|
m_cooling_description_line->SetText(text);
|
||||||
this->update_volumetric_flow_preset_hints();
|
this->update_volumetric_flow_preset_hints();
|
||||||
Layout();
|
Layout();
|
||||||
|
|
||||||
bool cooling = m_config->opt_bool("cooling", 0);
|
bool cooling = m_config->opt_bool("cooling", 0);
|
||||||
|
@ -1812,8 +1812,8 @@ void TabFilament::update()
|
||||||
|
|
||||||
void TabFilament::OnActivate()
|
void TabFilament::OnActivate()
|
||||||
{
|
{
|
||||||
this->update_volumetric_flow_preset_hints();
|
this->update_volumetric_flow_preset_hints();
|
||||||
Tab::OnActivate();
|
Tab::OnActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText)
|
wxSizer* Tab::description_line_widget(wxWindow* parent, ogStaticText* *StaticText)
|
||||||
|
@ -2290,6 +2290,12 @@ void TabPrinter::build_sla()
|
||||||
optgroup->append_single_option_line("absolute_correction");
|
optgroup->append_single_option_line("absolute_correction");
|
||||||
optgroup->append_single_option_line("gamma_correction");
|
optgroup->append_single_option_line("gamma_correction");
|
||||||
|
|
||||||
|
optgroup = page->new_optgroup(_(L("Exposure")));
|
||||||
|
optgroup->append_single_option_line("min_exposure_time");
|
||||||
|
optgroup->append_single_option_line("max_exposure_time");
|
||||||
|
optgroup->append_single_option_line("min_initial_exposure_time");
|
||||||
|
optgroup->append_single_option_line("max_initial_exposure_time");
|
||||||
|
|
||||||
optgroup = page->new_optgroup(_(L("Print Host upload")));
|
optgroup = page->new_optgroup(_(L("Print Host upload")));
|
||||||
build_printhost(optgroup.get());
|
build_printhost(optgroup.get());
|
||||||
|
|
||||||
|
@ -2560,7 +2566,7 @@ void TabPrinter::build_unregular_pages()
|
||||||
optgroup = page->new_optgroup(_(L("Preview")));
|
optgroup = page->new_optgroup(_(L("Preview")));
|
||||||
|
|
||||||
auto reset_to_filament_color = [this, extruder_idx](wxWindow* parent) {
|
auto reset_to_filament_color = [this, extruder_idx](wxWindow* parent) {
|
||||||
add_scaled_button(parent, &m_reset_to_filament_color, "undo",
|
add_scaled_button(parent, &m_reset_to_filament_color, "undo",
|
||||||
_(L("Reset to Filament Color")), wxBU_LEFT | wxBU_EXACTFIT);
|
_(L("Reset to Filament Color")), wxBU_LEFT | wxBU_EXACTFIT);
|
||||||
ScalableButton* btn = m_reset_to_filament_color;
|
ScalableButton* btn = m_reset_to_filament_color;
|
||||||
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||||
|
@ -2571,7 +2577,7 @@ void TabPrinter::build_unregular_pages()
|
||||||
{
|
{
|
||||||
std::vector<std::string> colors = static_cast<const ConfigOptionStrings*>(m_config->option("extruder_colour"))->values;
|
std::vector<std::string> colors = static_cast<const ConfigOptionStrings*>(m_config->option("extruder_colour"))->values;
|
||||||
colors[extruder_idx] = "";
|
colors[extruder_idx] = "";
|
||||||
|
|
||||||
DynamicPrintConfig new_conf = *m_config;
|
DynamicPrintConfig new_conf = *m_config;
|
||||||
new_conf.set_key_value("extruder_colour", new ConfigOptionStrings(colors));
|
new_conf.set_key_value("extruder_colour", new ConfigOptionStrings(colors));
|
||||||
load_config(new_conf);
|
load_config(new_conf);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue