mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-11 03:11:49 +08:00
Merge branch 'master' of https://github.com/Prusa3d/PrusaSlicer
This commit is contained in:
commit
0688778a24
14
deps/CGAL/cgal/CGALConfigVersion.cmake
vendored
14
deps/CGAL/cgal/CGALConfigVersion.cmake
vendored
@ -22,16 +22,4 @@ endif()
|
|||||||
# if the installed project requested no architecture check, don't perform the check
|
# if the installed project requested no architecture check, don't perform the check
|
||||||
if("FALSE")
|
if("FALSE")
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it:
|
|
||||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
|
|
||||||
if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8")
|
|
||||||
math(EXPR installedBits "8 * 8")
|
|
||||||
set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
|
|
||||||
set(PACKAGE_VERSION_UNSUITABLE TRUE)
|
|
||||||
endif()
|
|
File diff suppressed because it is too large
Load Diff
@ -395,9 +395,7 @@ public:
|
|||||||
PConfig& config() { return m_pconf; }
|
PConfig& config() { return m_pconf; }
|
||||||
const PConfig& config() const { return m_pconf; }
|
const PConfig& config() const { return m_pconf; }
|
||||||
|
|
||||||
inline void preload(std::vector<Item>& fixeditems) {
|
inline void preload(std::vector<Item>& fixeditems) {
|
||||||
// Build the rtree for queries to work
|
|
||||||
|
|
||||||
for(unsigned idx = 0; idx < fixeditems.size(); ++idx) {
|
for(unsigned idx = 0; idx < fixeditems.size(); ++idx) {
|
||||||
Item& itm = fixeditems[idx];
|
Item& itm = fixeditems[idx];
|
||||||
itm.markAsFixedInBin(itm.binId());
|
itm.markAsFixedInBin(itm.binId());
|
||||||
@ -416,13 +414,10 @@ template<> std::function<double(const Item&)> AutoArranger<Box>::get_objfn()
|
|||||||
|
|
||||||
double score = std::get<0>(result);
|
double score = std::get<0>(result);
|
||||||
auto& fullbb = std::get<1>(result);
|
auto& fullbb = std::get<1>(result);
|
||||||
|
|
||||||
auto bin = m_bin;
|
|
||||||
sl::offset(bin, -EPSILON * (m_bin.width() + m_bin.height()));
|
|
||||||
|
|
||||||
double miss = Placer::overfit(fullbb, bin);
|
double miss = Placer::overfit(fullbb, m_bin);
|
||||||
miss = miss > 0? miss : 0;
|
miss = miss > 0? miss : 0;
|
||||||
score += miss*miss;
|
score += miss * miss;
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
};
|
};
|
||||||
@ -490,7 +485,7 @@ void _arrange(
|
|||||||
{
|
{
|
||||||
// Integer ceiling the min distance from the bed perimeters
|
// Integer ceiling the min distance from the bed perimeters
|
||||||
coord_t md = params.min_obj_distance;
|
coord_t md = params.min_obj_distance;
|
||||||
md = (md % 2) ? md / 2 + 1 : md / 2;
|
md = md / 2;
|
||||||
|
|
||||||
auto corrected_bin = bin;
|
auto corrected_bin = bin;
|
||||||
sl::offset(corrected_bin, md);
|
sl::offset(corrected_bin, md);
|
||||||
@ -577,10 +572,13 @@ static void process_arrangeable(const ArrangePolygon &arrpoly,
|
|||||||
|
|
||||||
clppr::Polygon clpath(Slic3rMultiPoint_to_ClipperPath(p));
|
clppr::Polygon clpath(Slic3rMultiPoint_to_ClipperPath(p));
|
||||||
|
|
||||||
if (!clpath.Contour.empty()) {
|
// This fixes:
|
||||||
auto firstp = clpath.Contour.front();
|
// https://github.com/prusa3d/PrusaSlicer/issues/2209
|
||||||
clpath.Contour.emplace_back(firstp);
|
if (clpath.Contour.size() < 3)
|
||||||
}
|
return;
|
||||||
|
|
||||||
|
auto firstp = clpath.Contour.front();
|
||||||
|
clpath.Contour.emplace_back(firstp);
|
||||||
|
|
||||||
outp.emplace_back(std::move(clpath));
|
outp.emplace_back(std::move(clpath));
|
||||||
outp.back().rotation(rotation);
|
outp.back().rotation(rotation);
|
||||||
|
@ -20,7 +20,8 @@ SLIC3R_DERIVE_EXCEPTION(OutOfRange, LogicError);
|
|||||||
SLIC3R_DERIVE_EXCEPTION(IOError, CriticalException);
|
SLIC3R_DERIVE_EXCEPTION(IOError, CriticalException);
|
||||||
SLIC3R_DERIVE_EXCEPTION(FileIOError, IOError);
|
SLIC3R_DERIVE_EXCEPTION(FileIOError, IOError);
|
||||||
SLIC3R_DERIVE_EXCEPTION(HostNetworkError, IOError);
|
SLIC3R_DERIVE_EXCEPTION(HostNetworkError, IOError);
|
||||||
SLIC3R_DERIVE_EXCEPTION(ExportError, CriticalException);
|
SLIC3R_DERIVE_EXCEPTION(ExportError, CriticalException);
|
||||||
|
SLIC3R_DERIVE_EXCEPTION(PlaceholderParserError, RuntimeError);
|
||||||
// Runtime exception produced by Slicer. Such exception cancels the slicing process and it shall be shown in notifications.
|
// Runtime exception produced by Slicer. Such exception cancels the slicing process and it shall be shown in notifications.
|
||||||
SLIC3R_DERIVE_EXCEPTION(SlicingError, Exception);
|
SLIC3R_DERIVE_EXCEPTION(SlicingError, Exception);
|
||||||
#undef SLIC3R_DERIVE_EXCEPTION
|
#undef SLIC3R_DERIVE_EXCEPTION
|
||||||
|
@ -748,15 +748,17 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessor::Result* re
|
|||||||
|
|
||||||
if (! m_placeholder_parser_failed_templates.empty()) {
|
if (! m_placeholder_parser_failed_templates.empty()) {
|
||||||
// G-code export proceeded, but some of the PlaceholderParser substitutions failed.
|
// G-code export proceeded, but some of the PlaceholderParser substitutions failed.
|
||||||
|
//FIXME localize!
|
||||||
std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n";
|
std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n";
|
||||||
for (const std::string &name : m_placeholder_parser_failed_templates)
|
for (const auto &name_and_error : m_placeholder_parser_failed_templates)
|
||||||
msg += std::string("\t") + name + "\n";
|
msg += name_and_error.first + "\n" + name_and_error.second + "\n";
|
||||||
msg += "\nPlease inspect the file ";
|
msg += "\nPlease inspect the file ";
|
||||||
msg += path_tmp + " for error messages enclosed between\n";
|
msg += path_tmp + " for error messages enclosed between\n";
|
||||||
msg += " !!!!! Failed to process the custom G-code template ...\n";
|
msg += " !!!!! Failed to process the custom G-code template ...\n";
|
||||||
msg += "and\n";
|
msg += "and\n";
|
||||||
msg += " !!!!! End of an error report for the custom G-code template ...\n";
|
msg += " !!!!! End of an error report for the custom G-code template ...\n";
|
||||||
throw Slic3r::RuntimeError(msg);
|
msg += "for all macro processing errors.";
|
||||||
|
throw Slic3r::PlaceholderParserError(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info();
|
BOOST_LOG_TRIVIAL(debug) << "Start processing gcode, " << log_memory_info();
|
||||||
@ -1434,7 +1436,11 @@ std::string GCode::placeholder_parser_process(const std::string &name, const std
|
|||||||
return m_placeholder_parser.process(templ, current_extruder_id, config_override);
|
return m_placeholder_parser.process(templ, current_extruder_id, config_override);
|
||||||
} catch (std::runtime_error &err) {
|
} catch (std::runtime_error &err) {
|
||||||
// Collect the names of failed template substitutions for error reporting.
|
// Collect the names of failed template substitutions for error reporting.
|
||||||
m_placeholder_parser_failed_templates.insert(name);
|
auto it = m_placeholder_parser_failed_templates.find(name);
|
||||||
|
if (it == m_placeholder_parser_failed_templates.end())
|
||||||
|
// Only if there was no error reported for this template, store the first error message into the map to be reported.
|
||||||
|
// We don't want to collect error message for each and every occurence of a single custom G-code section.
|
||||||
|
m_placeholder_parser_failed_templates.insert(it, std::make_pair(name, std::string(err.what())));
|
||||||
// Insert the macro error message into the G-code.
|
// Insert the macro error message into the G-code.
|
||||||
return
|
return
|
||||||
std::string("\n!!!!! Failed to process the custom G-code template ") + name + "\n" +
|
std::string("\n!!!!! Failed to process the custom G-code template ") + name + "\n" +
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "GCode/ThumbnailData.hpp"
|
#include "GCode/ThumbnailData.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#ifdef HAS_PRESSURE_EQUALIZER
|
#ifdef HAS_PRESSURE_EQUALIZER
|
||||||
@ -323,7 +324,7 @@ private:
|
|||||||
GCodeWriter m_writer;
|
GCodeWriter m_writer;
|
||||||
PlaceholderParser m_placeholder_parser;
|
PlaceholderParser m_placeholder_parser;
|
||||||
// Collection of templates, on which the placeholder substitution failed.
|
// Collection of templates, on which the placeholder substitution failed.
|
||||||
std::set<std::string> m_placeholder_parser_failed_templates;
|
std::map<std::string, std::string> m_placeholder_parser_failed_templates;
|
||||||
OozePrevention m_ooze_prevention;
|
OozePrevention m_ooze_prevention;
|
||||||
Wipe m_wipe;
|
Wipe m_wipe;
|
||||||
AvoidCrossingPerimeters m_avoid_crossing_perimeters;
|
AvoidCrossingPerimeters m_avoid_crossing_perimeters;
|
||||||
|
@ -1273,6 +1273,10 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
|
|||||||
ModelVolume* volume = this->volumes.front();
|
ModelVolume* volume = this->volumes.front();
|
||||||
TriangleMeshPtrs meshptrs = volume->mesh().split();
|
TriangleMeshPtrs meshptrs = volume->mesh().split();
|
||||||
for (TriangleMesh *mesh : meshptrs) {
|
for (TriangleMesh *mesh : meshptrs) {
|
||||||
|
|
||||||
|
// FIXME: crashes if not satisfied
|
||||||
|
if (mesh->facets_count() < 3) continue;
|
||||||
|
|
||||||
mesh->repair();
|
mesh->repair();
|
||||||
|
|
||||||
// XXX: this seems to be the only real usage of m_model, maybe refactor this so that it's not needed?
|
// XXX: this seems to be the only real usage of m_model, maybe refactor this so that it's not needed?
|
||||||
@ -1846,7 +1850,7 @@ void ModelInstance::transform_polygon(Polygon* polygon) const
|
|||||||
|
|
||||||
arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const
|
arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const
|
||||||
{
|
{
|
||||||
static const double SIMPLIFY_TOLERANCE_MM = 0.1;
|
// static const double SIMPLIFY_TOLERANCE_MM = 0.1;
|
||||||
|
|
||||||
Vec3d rotation = get_rotation();
|
Vec3d rotation = get_rotation();
|
||||||
rotation.z() = 0.;
|
rotation.z() = 0.;
|
||||||
@ -1858,13 +1862,11 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const
|
|||||||
|
|
||||||
assert(!p.points.empty());
|
assert(!p.points.empty());
|
||||||
|
|
||||||
// this may happen for malformed models, see:
|
// if (!p.points.empty()) {
|
||||||
// https://github.com/prusa3d/PrusaSlicer/issues/2209
|
// Polygons pp{p};
|
||||||
if (!p.points.empty()) {
|
// pp = p.simplify(scaled<double>(SIMPLIFY_TOLERANCE_MM));
|
||||||
Polygons pp{p};
|
// if (!pp.empty()) p = pp.front();
|
||||||
pp = p.simplify(scaled<double>(SIMPLIFY_TOLERANCE_MM));
|
// }
|
||||||
if (!pp.empty()) p = pp.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
arrangement::ArrangePolygon ret;
|
arrangement::ArrangePolygon ret;
|
||||||
ret.poly.contour = std::move(p);
|
ret.poly.contour = std::move(p);
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <boost/nowide/convert.hpp>
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <stdlib.h> // provides **_environ
|
#include <stdlib.h> // provides **_environ
|
||||||
#else
|
#else
|
||||||
@ -870,7 +871,9 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
msg += '\n';
|
msg += '\n';
|
||||||
msg += error_line;
|
// This hack removes all non-UTF8 characters from the source line, so that the upstream wxWidgets conversions
|
||||||
|
// from UTF8 to UTF16 don't bail out.
|
||||||
|
msg += boost::nowide::narrow(boost::nowide::widen(error_line));
|
||||||
msg += '\n';
|
msg += '\n';
|
||||||
for (size_t i = 0; i < error_pos; ++ i)
|
for (size_t i = 0; i < error_pos; ++ i)
|
||||||
msg += ' ';
|
msg += ' ';
|
||||||
@ -1304,7 +1307,7 @@ static std::string process_macro(const std::string &templ, client::MyContext &co
|
|||||||
if (!context.error_message.empty()) {
|
if (!context.error_message.empty()) {
|
||||||
if (context.error_message.back() != '\n' && context.error_message.back() != '\r')
|
if (context.error_message.back() != '\n' && context.error_message.back() != '\r')
|
||||||
context.error_message += '\n';
|
context.error_message += '\n';
|
||||||
throw Slic3r::RuntimeError(context.error_message);
|
throw Slic3r::PlaceholderParserError(context.error_message);
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,11 @@ public:
|
|||||||
const DynamicConfig* external_config() const { return m_external_config; }
|
const DynamicConfig* external_config() const { return m_external_config; }
|
||||||
|
|
||||||
// Fill in the template using a macro processing language.
|
// Fill in the template using a macro processing language.
|
||||||
// Throws Slic3r::RuntimeError on syntax or runtime error.
|
// Throws Slic3r::PlaceholderParserError on syntax or runtime error.
|
||||||
std::string process(const std::string &templ, unsigned int current_extruder_id = 0, const DynamicConfig *config_override = nullptr) const;
|
std::string process(const std::string &templ, unsigned int current_extruder_id = 0, const DynamicConfig *config_override = nullptr) const;
|
||||||
|
|
||||||
// Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax.
|
// Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax.
|
||||||
// Throws Slic3r::RuntimeError on syntax or runtime error.
|
// Throws Slic3r::PlaceholderParserError on syntax or runtime error.
|
||||||
static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override = nullptr);
|
static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override = nullptr);
|
||||||
|
|
||||||
// Update timestamp, year, month, day, hour, minute, second variables at the provided config.
|
// Update timestamp, year, month, day, hour, minute, second variables at the provided config.
|
||||||
|
@ -731,8 +731,9 @@ static bool profile_print_params_same(const DynamicPrintConfig &cfg_old, const D
|
|||||||
|
|
||||||
// Load a preset from an already parsed config file, insert it into the sorted sequence of presets
|
// Load a preset from an already parsed config file, insert it into the sorted sequence of presets
|
||||||
// and select it, losing previous modifications.
|
// and select it, losing previous modifications.
|
||||||
// In case
|
// Only a single profile could be edited at at the same time, which introduces complexity when loading
|
||||||
Preset& PresetCollection::load_external_preset(
|
// filament profiles for multi-extruder printers.
|
||||||
|
std::pair<Preset*, bool> PresetCollection::load_external_preset(
|
||||||
// Path to the profile source file (a G-code, an AMF or 3MF file, a config file)
|
// Path to the profile source file (a G-code, an AMF or 3MF file, a config file)
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
// Name of the profile, derived from the source file name.
|
// Name of the profile, derived from the source file name.
|
||||||
@ -742,14 +743,23 @@ Preset& PresetCollection::load_external_preset(
|
|||||||
// Config to initialize the preset from.
|
// Config to initialize the preset from.
|
||||||
const DynamicPrintConfig &config,
|
const DynamicPrintConfig &config,
|
||||||
// Select the preset after loading?
|
// Select the preset after loading?
|
||||||
bool select)
|
LoadAndSelect select)
|
||||||
{
|
{
|
||||||
// Load the preset over a default preset, so that the missing fields are filled in from the default preset.
|
// Load the preset over a default preset, so that the missing fields are filled in from the default preset.
|
||||||
DynamicPrintConfig cfg(this->default_preset_for(config).config);
|
DynamicPrintConfig cfg(this->default_preset_for(config).config);
|
||||||
cfg.apply_only(config, cfg.keys(), true);
|
cfg.apply_only(config, cfg.keys(), true);
|
||||||
|
std::string &inherits = Preset::inherits(cfg);
|
||||||
|
if (select == LoadAndSelect::Never) {
|
||||||
|
// Some filament profile has been selected and modified already.
|
||||||
|
// Check whether this profile is equal to the modified edited profile.
|
||||||
|
const Preset &edited = this->get_edited_preset();
|
||||||
|
if ((edited.name == original_name || edited.name == inherits) && profile_print_params_same(edited.config, cfg))
|
||||||
|
// Just point to that already selected and edited profile.
|
||||||
|
return std::make_pair(&(*this->find_preset_internal(edited.name)), false);
|
||||||
|
}
|
||||||
// Is there a preset already loaded with the name stored inside the config?
|
// Is there a preset already loaded with the name stored inside the config?
|
||||||
std::deque<Preset>::iterator it = this->find_preset_internal(original_name);
|
std::deque<Preset>::iterator it = this->find_preset_internal(original_name);
|
||||||
bool found = it != m_presets.end() && it->name == original_name;
|
bool found = it != m_presets.end() && it->name == original_name;
|
||||||
if (! found) {
|
if (! found) {
|
||||||
// Try to match the original_name against the "renamed_from" profile names of loaded system profiles.
|
// Try to match the original_name against the "renamed_from" profile names of loaded system profiles.
|
||||||
it = this->find_preset_renamed(original_name);
|
it = this->find_preset_renamed(original_name);
|
||||||
@ -757,19 +767,40 @@ Preset& PresetCollection::load_external_preset(
|
|||||||
}
|
}
|
||||||
if (found && profile_print_params_same(it->config, cfg)) {
|
if (found && profile_print_params_same(it->config, cfg)) {
|
||||||
// The preset exists and it matches the values stored inside config.
|
// The preset exists and it matches the values stored inside config.
|
||||||
if (select)
|
if (select == LoadAndSelect::Always)
|
||||||
this->select_preset(it - m_presets.begin());
|
this->select_preset(it - m_presets.begin());
|
||||||
return *it;
|
return std::make_pair(&(*it), false);
|
||||||
}
|
}
|
||||||
// Update the "inherits" field.
|
if (! found && select != LoadAndSelect::Never && ! inherits.empty()) {
|
||||||
std::string &inherits = Preset::inherits(cfg);
|
// Try to use a system profile as a base to select the system profile
|
||||||
if (found && inherits.empty()) {
|
// and override its settings with the loaded ones.
|
||||||
// There is a profile with the same name already loaded. Should we update the "inherits" field?
|
assert(it == m_presets.end());
|
||||||
if (it->vendor == nullptr)
|
it = this->find_preset_internal(inherits);
|
||||||
inherits = it->inherits();
|
found = it != m_presets.end() && it->name == inherits;
|
||||||
else
|
if (found && profile_print_params_same(it->config, cfg)) {
|
||||||
inherits = it->name;
|
// The system preset exists and it matches the values stored inside config.
|
||||||
|
if (select == LoadAndSelect::Always)
|
||||||
|
this->select_preset(it - m_presets.begin());
|
||||||
|
return std::make_pair(&(*it), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (found) {
|
||||||
|
if (select != LoadAndSelect::Never) {
|
||||||
|
// Select the existing preset and override it with new values, so that
|
||||||
|
// the differences will be shown in the preset editor against the referenced profile.
|
||||||
|
this->select_preset(it - m_presets.begin());
|
||||||
|
this->get_edited_preset().config.apply(config);
|
||||||
|
this->update_dirty();
|
||||||
|
assert(this->get_edited_preset().is_dirty);
|
||||||
|
return std::make_pair(&(*it), this->get_edited_preset().is_dirty);
|
||||||
|
}
|
||||||
|
if (inherits.empty()) {
|
||||||
|
// Update the "inherits" field.
|
||||||
|
// There is a profile with the same name already loaded. Should we update the "inherits" field?
|
||||||
|
inherits = it->vendor ? it->name : it->inherits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The external preset does not match an internal preset, load the external preset.
|
// The external preset does not match an internal preset, load the external preset.
|
||||||
std::string new_name;
|
std::string new_name;
|
||||||
for (size_t idx = 0;; ++ idx) {
|
for (size_t idx = 0;; ++ idx) {
|
||||||
@ -790,19 +821,19 @@ Preset& PresetCollection::load_external_preset(
|
|||||||
break;
|
break;
|
||||||
if (profile_print_params_same(it->config, cfg)) {
|
if (profile_print_params_same(it->config, cfg)) {
|
||||||
// The preset exists and it matches the values stored inside config.
|
// The preset exists and it matches the values stored inside config.
|
||||||
if (select)
|
if (select == LoadAndSelect::Always)
|
||||||
this->select_preset(it - m_presets.begin());
|
this->select_preset(it - m_presets.begin());
|
||||||
return *it;
|
return std::make_pair(&(*it), false);
|
||||||
}
|
}
|
||||||
// Form another profile name.
|
// Form another profile name.
|
||||||
}
|
}
|
||||||
// Insert a new profile.
|
// Insert a new profile.
|
||||||
Preset &preset = this->load_preset(path, new_name, std::move(cfg), select);
|
Preset &preset = this->load_preset(path, new_name, std::move(cfg), select == LoadAndSelect::Always);
|
||||||
preset.is_external = true;
|
preset.is_external = true;
|
||||||
if (&this->get_selected_preset() == &preset)
|
if (&this->get_selected_preset() == &preset)
|
||||||
this->get_edited_preset().is_external = true;
|
this->get_edited_preset().is_external = true;
|
||||||
|
|
||||||
return preset;
|
return std::make_pair(&preset, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select)
|
Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select)
|
||||||
|
@ -287,7 +287,18 @@ public:
|
|||||||
Preset& load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select = true);
|
Preset& load_preset(const std::string &path, const std::string &name, const DynamicPrintConfig &config, bool select = true);
|
||||||
Preset& load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select = true);
|
Preset& load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select = true);
|
||||||
|
|
||||||
Preset& load_external_preset(
|
// Returns a loaded preset, returns true if an existing preset was selected AND modified from config.
|
||||||
|
// In that case the successive filament loaded for a multi material printer should not be modified, but
|
||||||
|
// an external preset should be created instead.
|
||||||
|
enum class LoadAndSelect {
|
||||||
|
// Never select
|
||||||
|
Never,
|
||||||
|
// Always select
|
||||||
|
Always,
|
||||||
|
// Select a profile only if it was modified.
|
||||||
|
OnlyIfModified,
|
||||||
|
};
|
||||||
|
std::pair<Preset*, bool> load_external_preset(
|
||||||
// Path to the profile source file (a G-code, an AMF or 3MF file, a config file)
|
// Path to the profile source file (a G-code, an AMF or 3MF file, a config file)
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
// Name of the profile, derived from the source file name.
|
// Name of the profile, derived from the source file name.
|
||||||
@ -297,7 +308,7 @@ public:
|
|||||||
// Config to initialize the preset from.
|
// Config to initialize the preset from.
|
||||||
const DynamicPrintConfig &config,
|
const DynamicPrintConfig &config,
|
||||||
// Select the preset after loading?
|
// Select the preset after loading?
|
||||||
bool select = true);
|
LoadAndSelect select = LoadAndSelect::Always);
|
||||||
|
|
||||||
// Save the preset under a new name. If the name is different from the old one,
|
// Save the preset under a new name. If the name is different from the old one,
|
||||||
// a new preset is stored into the list of presets.
|
// a new preset is stored into the list of presets.
|
||||||
|
@ -49,7 +49,7 @@ PresetBundle::PresetBundle() :
|
|||||||
// initialized based on PrintConfigDef(), but to empty values (zeros, empty vectors, empty strings).
|
// initialized based on PrintConfigDef(), but to empty values (zeros, empty vectors, empty strings).
|
||||||
//
|
//
|
||||||
// "compatible_printers", "compatible_printers_condition", "inherits",
|
// "compatible_printers", "compatible_printers_condition", "inherits",
|
||||||
// "print_settings_id", "filament_settings_id", "printer_settings_id",
|
// "print_settings_id", "filament_settings_id", "printer_settings_id", "printer_settings_id"
|
||||||
// "printer_vendor", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile"
|
// "printer_vendor", "printer_model", "printer_variant", "default_print_profile", "default_filament_profile"
|
||||||
|
|
||||||
// Create the ID config keys, as they are not part of the Static print config classes.
|
// Create the ID config keys, as they are not part of the Static print config classes.
|
||||||
@ -586,6 +586,7 @@ DynamicPrintConfig PresetBundle::full_fff_config() const
|
|||||||
out.option<ConfigOptionString >("print_settings_id", true)->value = this->prints.get_selected_preset_name();
|
out.option<ConfigOptionString >("print_settings_id", true)->value = this->prints.get_selected_preset_name();
|
||||||
out.option<ConfigOptionStrings>("filament_settings_id", true)->values = this->filament_presets;
|
out.option<ConfigOptionStrings>("filament_settings_id", true)->values = this->filament_presets;
|
||||||
out.option<ConfigOptionString >("printer_settings_id", true)->value = this->printers.get_selected_preset_name();
|
out.option<ConfigOptionString >("printer_settings_id", true)->value = this->printers.get_selected_preset_name();
|
||||||
|
out.option<ConfigOptionString >("physical_printer_settings_id", true)->value = this->physical_printers.get_selected_printer_name();
|
||||||
|
|
||||||
// Serialize the collected "compatible_printers_condition" and "inherits" fields.
|
// Serialize the collected "compatible_printers_condition" and "inherits" fields.
|
||||||
// There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored.
|
// There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored.
|
||||||
@ -637,6 +638,7 @@ DynamicPrintConfig PresetBundle::full_sla_config() const
|
|||||||
out.option<ConfigOptionString >("sla_print_settings_id", true)->value = this->sla_prints.get_selected_preset_name();
|
out.option<ConfigOptionString >("sla_print_settings_id", true)->value = this->sla_prints.get_selected_preset_name();
|
||||||
out.option<ConfigOptionString >("sla_material_settings_id", true)->value = this->sla_materials.get_selected_preset_name();
|
out.option<ConfigOptionString >("sla_material_settings_id", true)->value = this->sla_materials.get_selected_preset_name();
|
||||||
out.option<ConfigOptionString >("printer_settings_id", true)->value = this->printers.get_selected_preset_name();
|
out.option<ConfigOptionString >("printer_settings_id", true)->value = this->printers.get_selected_preset_name();
|
||||||
|
out.option<ConfigOptionString >("physical_printer_settings_id", true)->value = this->physical_printers.get_selected_printer_name();
|
||||||
|
|
||||||
// Serialize the collected "compatible_printers_condition" and "inherits" fields.
|
// Serialize the collected "compatible_printers_condition" and "inherits" fields.
|
||||||
// There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored.
|
// There will be 1 + num_exturders fields for "inherits" and 2 + num_extruders for "compatible_printers_condition" stored.
|
||||||
@ -712,6 +714,7 @@ void PresetBundle::load_config_file(const std::string &path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load a config file from a boost property_tree. This is a private method called from load_config_file.
|
// Load a config file from a boost property_tree. This is a private method called from load_config_file.
|
||||||
|
// is_external == false on if called from ConfigWizard
|
||||||
void PresetBundle::load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config)
|
void PresetBundle::load_config_file_config(const std::string &name_or_path, bool is_external, DynamicPrintConfig &&config)
|
||||||
{
|
{
|
||||||
PrinterTechnology printer_technology = Preset::printer_technology(config);
|
PrinterTechnology printer_technology = Preset::printer_technology(config);
|
||||||
@ -798,14 +801,17 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||||||
compatible_prints_condition = compatible_prints_condition_values.front();
|
compatible_prints_condition = compatible_prints_condition_values.front();
|
||||||
Preset *loaded = nullptr;
|
Preset *loaded = nullptr;
|
||||||
if (is_external) {
|
if (is_external) {
|
||||||
loaded = &this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config);
|
auto [aloaded, modified] = this->filaments.load_external_preset(name_or_path, name, old_filament_profile_names->values.front(), config);
|
||||||
|
loaded = aloaded;
|
||||||
} else {
|
} else {
|
||||||
loaded = &this->filaments.load_preset(this->filaments.path_from_name(name), name, config);
|
// called from Config Wizard.
|
||||||
|
loaded= &this->filaments.load_preset(this->filaments.path_from_name(name), name, config);
|
||||||
loaded->save();
|
loaded->save();
|
||||||
}
|
}
|
||||||
this->filament_presets.clear();
|
this->filament_presets.clear();
|
||||||
this->filament_presets.emplace_back(loaded->name);
|
this->filament_presets.emplace_back(loaded->name);
|
||||||
} else {
|
} else {
|
||||||
|
assert(is_external);
|
||||||
// Split the filament presets, load each of them separately.
|
// Split the filament presets, load each of them separately.
|
||||||
std::vector<DynamicPrintConfig> configs(num_extruders, this->filaments.default_preset().config);
|
std::vector<DynamicPrintConfig> configs(num_extruders, this->filaments.default_preset().config);
|
||||||
// loop through options and scatter them into configs.
|
// loop through options and scatter them into configs.
|
||||||
@ -826,6 +832,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||||||
// To avoid incorrect selection of the first filament preset (means a value of Preset->m_idx_selected)
|
// To avoid incorrect selection of the first filament preset (means a value of Preset->m_idx_selected)
|
||||||
// in a case when next added preset take a place of previosly selected preset,
|
// in a case when next added preset take a place of previosly selected preset,
|
||||||
// we should add presets from last to first
|
// we should add presets from last to first
|
||||||
|
bool any_modified = false;
|
||||||
for (int i = (int)configs.size()-1; i >= 0; i--) {
|
for (int i = (int)configs.size()-1; i >= 0; i--) {
|
||||||
DynamicPrintConfig &cfg = configs[i];
|
DynamicPrintConfig &cfg = configs[i];
|
||||||
// Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets.
|
// Split the "compatible_printers_condition" and "inherits" from the cummulative vectors to separate filament presets.
|
||||||
@ -833,24 +840,15 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||||||
cfg.opt_string("compatible_prints_condition", true) = compatible_prints_condition_values[i];
|
cfg.opt_string("compatible_prints_condition", true) = compatible_prints_condition_values[i];
|
||||||
cfg.opt_string("inherits", true) = inherits_values[i + 1];
|
cfg.opt_string("inherits", true) = inherits_values[i + 1];
|
||||||
// Load all filament presets, but only select the first one in the preset dialog.
|
// Load all filament presets, but only select the first one in the preset dialog.
|
||||||
Preset *loaded = nullptr;
|
auto [loaded, modified] = this->filaments.load_external_preset(name_or_path, name,
|
||||||
if (is_external)
|
(i < int(old_filament_profile_names->values.size())) ? old_filament_profile_names->values[i] : "",
|
||||||
loaded = &this->filaments.load_external_preset(name_or_path, name,
|
std::move(cfg),
|
||||||
(i < int(old_filament_profile_names->values.size())) ? old_filament_profile_names->values[i] : "",
|
i == 0 ?
|
||||||
std::move(cfg), i == 0);
|
PresetCollection::LoadAndSelect::Always :
|
||||||
else {
|
any_modified ?
|
||||||
// Used by the config wizard when creating a custom setup.
|
PresetCollection::LoadAndSelect::Never :
|
||||||
// Therefore this block should only be called for a single extruder.
|
PresetCollection::LoadAndSelect::OnlyIfModified);
|
||||||
char suffix[64];
|
any_modified |= modified;
|
||||||
if (i == 0)
|
|
||||||
suffix[0] = 0;
|
|
||||||
else
|
|
||||||
sprintf(suffix, "%d", (int)i);
|
|
||||||
std::string new_name = name + suffix;
|
|
||||||
loaded = &this->filaments.load_preset(this->filaments.path_from_name(new_name),
|
|
||||||
new_name, std::move(cfg), i == 0);
|
|
||||||
loaded->save();
|
|
||||||
}
|
|
||||||
this->filament_presets[i] = loaded->name;
|
this->filament_presets[i] = loaded->name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -864,10 +862,23 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||||||
load_preset(this->sla_materials, 1, "sla_material_settings_id");
|
load_preset(this->sla_materials, 1, "sla_material_settings_id");
|
||||||
load_preset(this->printers, 2, "printer_settings_id");
|
load_preset(this->printers, 2, "printer_settings_id");
|
||||||
break;
|
break;
|
||||||
default: break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->update_compatible(PresetSelectCompatibleType::Never);
|
this->update_compatible(PresetSelectCompatibleType::Never);
|
||||||
|
|
||||||
|
const std::string &physical_printer = config.option<ConfigOptionString>("physical_printer_settings_id", true)->value;
|
||||||
|
if (this->printers.get_edited_preset().is_external || physical_printer.empty()) {
|
||||||
|
this->physical_printers.unselect_printer();
|
||||||
|
} else {
|
||||||
|
// Activate the physical printer profile if possible.
|
||||||
|
PhysicalPrinter *pp = this->physical_printers.find_printer(physical_printer, true);
|
||||||
|
if (pp != nullptr && std::find(pp->preset_names.begin(), pp->preset_names.end(), this->printers.get_edited_preset().name) != pp->preset_names.end())
|
||||||
|
this->physical_printers.select_printer(*pp);
|
||||||
|
else
|
||||||
|
this->physical_printers.unselect_printer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the active configuration of a config bundle from a boost property_tree. This is a private method called from load_config_file.
|
// Load the active configuration of a config bundle from a boost property_tree. This is a private method called from load_config_file.
|
||||||
|
@ -70,7 +70,7 @@ public:
|
|||||||
|
|
||||||
// Load user configuration and store it into the user profiles.
|
// Load user configuration and store it into the user profiles.
|
||||||
// This method is called by the configuration wizard.
|
// This method is called by the configuration wizard.
|
||||||
void load_config(const std::string &name, DynamicPrintConfig config)
|
void load_config_from_wizard(const std::string &name, DynamicPrintConfig config)
|
||||||
{ this->load_config_file_config(name, false, std::move(config)); }
|
{ this->load_config_file_config(name, false, std::move(config)); }
|
||||||
|
|
||||||
// Load configuration that comes from a model file containing configuration, such as 3MF et al.
|
// Load configuration that comes from a model file containing configuration, such as 3MF et al.
|
||||||
|
@ -597,9 +597,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
#endif /* _DEBUG */
|
#endif /* _DEBUG */
|
||||||
|
|
||||||
// Normalize the config.
|
// Normalize the config.
|
||||||
new_full_config.option("print_settings_id", true);
|
new_full_config.option("print_settings_id", true);
|
||||||
new_full_config.option("filament_settings_id", true);
|
new_full_config.option("filament_settings_id", true);
|
||||||
new_full_config.option("printer_settings_id", true);
|
new_full_config.option("printer_settings_id", true);
|
||||||
|
new_full_config.option("physical_printer_settings_id", true);
|
||||||
new_full_config.normalize_fdm();
|
new_full_config.normalize_fdm();
|
||||||
|
|
||||||
// Find modified keys of the various configs. Resolve overrides extruder retract values by filament profiles.
|
// Find modified keys of the various configs. Resolve overrides extruder retract values by filament profiles.
|
||||||
@ -628,9 +629,10 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
|||||||
if (! full_config_diff.empty()) {
|
if (! full_config_diff.empty()) {
|
||||||
update_apply_status(this->invalidate_step(psGCodeExport));
|
update_apply_status(this->invalidate_step(psGCodeExport));
|
||||||
// Set the profile aliases for the PrintBase::output_filename()
|
// Set the profile aliases for the PrintBase::output_filename()
|
||||||
m_placeholder_parser.set("print_preset", new_full_config.option("print_settings_id")->clone());
|
m_placeholder_parser.set("print_preset", new_full_config.option("print_settings_id")->clone());
|
||||||
m_placeholder_parser.set("filament_preset", new_full_config.option("filament_settings_id")->clone());
|
m_placeholder_parser.set("filament_preset", new_full_config.option("filament_settings_id")->clone());
|
||||||
m_placeholder_parser.set("printer_preset", new_full_config.option("printer_settings_id")->clone());
|
m_placeholder_parser.set("printer_preset", new_full_config.option("printer_settings_id")->clone());
|
||||||
|
m_placeholder_parser.set("physical_printer_preset", new_full_config.option("physical_printer_settings_id")->clone());
|
||||||
// We want the filament overrides to be applied over their respective extruder parameters by the PlaceholderParser.
|
// We want the filament overrides to be applied over their respective extruder parameters by the PlaceholderParser.
|
||||||
// see "Placeholders do not respect filament overrides." GH issue #3649
|
// see "Placeholders do not respect filament overrides." GH issue #3649
|
||||||
m_placeholder_parser.apply_config(filament_overrides);
|
m_placeholder_parser.apply_config(filament_overrides);
|
||||||
|
@ -69,7 +69,7 @@ std::string PrintBase::output_filename(const std::string &format, const std::str
|
|||||||
filename = boost::filesystem::change_extension(filename, default_ext);
|
filename = boost::filesystem::change_extension(filename, default_ext);
|
||||||
return filename.string();
|
return filename.string();
|
||||||
} catch (std::runtime_error &err) {
|
} catch (std::runtime_error &err) {
|
||||||
throw Slic3r::RuntimeError(L("Failed processing of the output_filename_format template.") + "\n" + err.what());
|
throw Slic3r::PlaceholderParserError(L("Failed processing of the output_filename_format template.") + "\n" + err.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,9 @@ void PrintConfigDef::init_common_params()
|
|||||||
def = this->add("print_host", coString);
|
def = this->add("print_host", coString);
|
||||||
def->label = L("Hostname, IP or URL");
|
def->label = L("Hostname, IP or URL");
|
||||||
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
|
def->tooltip = L("Slic3r can upload G-code files to a printer host. This field should contain "
|
||||||
"the hostname, IP address or URL of the printer host instance.");
|
"the hostname, IP address or URL of the printer host instance. "
|
||||||
|
"Print host behind HAProxy with basic auth enabled can be accessed by putting the user name and password into the URL "
|
||||||
|
"in the following format: https://username:password@your-octopi-address/");
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionString(""));
|
def->set_default_value(new ConfigOptionString(""));
|
||||||
|
|
||||||
@ -1689,6 +1691,10 @@ void PrintConfigDef::init_fff_params()
|
|||||||
def->set_default_value(new ConfigOptionString(""));
|
def->set_default_value(new ConfigOptionString(""));
|
||||||
def->cli = ConfigOptionDef::nocli;
|
def->cli = ConfigOptionDef::nocli;
|
||||||
|
|
||||||
|
def = this->add("physical_printer_settings_id", coString);
|
||||||
|
def->set_default_value(new ConfigOptionString(""));
|
||||||
|
def->cli = ConfigOptionDef::nocli;
|
||||||
|
|
||||||
def = this->add("raft_layers", coInt);
|
def = this->add("raft_layers", coInt);
|
||||||
def->label = L("Raft layers");
|
def->label = L("Raft layers");
|
||||||
def->category = L("Support material");
|
def->category = L("Support material");
|
||||||
|
@ -193,9 +193,10 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
|
|||||||
#endif /* _DEBUG */
|
#endif /* _DEBUG */
|
||||||
|
|
||||||
// Normalize the config.
|
// Normalize the config.
|
||||||
config.option("sla_print_settings_id", true);
|
config.option("sla_print_settings_id", true);
|
||||||
config.option("sla_material_settings_id", true);
|
config.option("sla_material_settings_id", true);
|
||||||
config.option("printer_settings_id", true);
|
config.option("printer_settings_id", true);
|
||||||
|
config.option("physical_printer_settings_id", true);
|
||||||
// Collect changes to print config.
|
// Collect changes to print config.
|
||||||
t_config_option_keys print_diff = m_print_config.diff(config);
|
t_config_option_keys print_diff = m_print_config.diff(config);
|
||||||
t_config_option_keys printer_diff = m_printer_config.diff(config);
|
t_config_option_keys printer_diff = m_printer_config.diff(config);
|
||||||
@ -228,9 +229,10 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
|
|||||||
// update_apply_status(this->invalidate_step(slapsRasterize));
|
// update_apply_status(this->invalidate_step(slapsRasterize));
|
||||||
m_placeholder_parser.apply_config(config);
|
m_placeholder_parser.apply_config(config);
|
||||||
// Set the profile aliases for the PrintBase::output_filename()
|
// Set the profile aliases for the PrintBase::output_filename()
|
||||||
m_placeholder_parser.set("print_preset", config.option("sla_print_settings_id")->clone());
|
m_placeholder_parser.set("print_preset", config.option("sla_print_settings_id")->clone());
|
||||||
m_placeholder_parser.set("material_preset", config.option("sla_material_settings_id")->clone());
|
m_placeholder_parser.set("material_preset", config.option("sla_material_settings_id")->clone());
|
||||||
m_placeholder_parser.set("printer_preset", config.option("printer_settings_id")->clone());
|
m_placeholder_parser.set("printer_preset", config.option("printer_settings_id")->clone());
|
||||||
|
m_placeholder_parser.set("physical_printer_preset", config.option("physical_printer_settings_id")->clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
|
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
|
||||||
|
@ -89,6 +89,7 @@
|
|||||||
#define ENABLE_2_3_0_BETA2 1
|
#define ENABLE_2_3_0_BETA2 1
|
||||||
|
|
||||||
#define ENABLE_ARROW_KEYS_WITH_SLIDERS (1 && ENABLE_2_3_0_BETA2)
|
#define ENABLE_ARROW_KEYS_WITH_SLIDERS (1 && ENABLE_2_3_0_BETA2)
|
||||||
|
#define ENABLE_NEW_NOTIFICATIONS_FADE_OUT (1 && ENABLE_2_3_0_BETA2)
|
||||||
|
|
||||||
|
|
||||||
#endif // _prusaslicer_technologies_h_
|
#endif // _prusaslicer_technologies_h_
|
||||||
|
@ -804,6 +804,10 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
|
|||||||
BoundingBoxf3 print_volume(Vec3d(unscale<double>(bed_box_2D.min(0)), unscale<double>(bed_box_2D.min(1)), 0.0), Vec3d(unscale<double>(bed_box_2D.max(0)), unscale<double>(bed_box_2D.max(1)), config->opt_float("max_print_height")));
|
BoundingBoxf3 print_volume(Vec3d(unscale<double>(bed_box_2D.min(0)), unscale<double>(bed_box_2D.min(1)), 0.0), Vec3d(unscale<double>(bed_box_2D.max(0)), unscale<double>(bed_box_2D.max(1)), config->opt_float("max_print_height")));
|
||||||
// Allow the objects to protrude below the print bed
|
// Allow the objects to protrude below the print bed
|
||||||
print_volume.min(2) = -1e10;
|
print_volume.min(2) = -1e10;
|
||||||
|
print_volume.min(0) -= BedEpsilon;
|
||||||
|
print_volume.min(1) -= BedEpsilon;
|
||||||
|
print_volume.max(0) += BedEpsilon;
|
||||||
|
print_volume.max(1) += BedEpsilon;
|
||||||
|
|
||||||
ModelInstanceEPrintVolumeState state = ModelInstancePVS_Inside;
|
ModelInstanceEPrintVolumeState state = ModelInstancePVS_Inside;
|
||||||
|
|
||||||
|
@ -611,6 +611,8 @@ struct _3DScene
|
|||||||
static void point3_to_verts(const Vec3crd& point, double width, double height, GLVolume& volume);
|
static void point3_to_verts(const Vec3crd& point, double width, double height, GLVolume& volume);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr float BedEpsilon = EPSILON;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -68,9 +68,10 @@ bool SlicingProcessCompletedEvent::invalidate_plater() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SlicingProcessCompletedEvent::format_error_message() const
|
std::pair<std::string, bool> SlicingProcessCompletedEvent::format_error_message() const
|
||||||
{
|
{
|
||||||
std::string error;
|
std::string error;
|
||||||
|
bool monospace = false;
|
||||||
try {
|
try {
|
||||||
this->rethrow_exception();
|
this->rethrow_exception();
|
||||||
} catch (const std::bad_alloc& ex) {
|
} catch (const std::bad_alloc& ex) {
|
||||||
@ -78,12 +79,15 @@ std::string SlicingProcessCompletedEvent::format_error_message() const
|
|||||||
"If you are sure you have enough RAM on your system, this may also be a bug and we would "
|
"If you are sure you have enough RAM on your system, this may also be a bug and we would "
|
||||||
"be glad if you reported it."))) % SLIC3R_APP_NAME).str());
|
"be glad if you reported it."))) % SLIC3R_APP_NAME).str());
|
||||||
error = std::string(errmsg.ToUTF8()) + "\n\n" + std::string(ex.what());
|
error = std::string(errmsg.ToUTF8()) + "\n\n" + std::string(ex.what());
|
||||||
|
} catch (PlaceholderParserError &ex) {
|
||||||
|
error = ex.what();
|
||||||
|
monospace = true;
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
error = ex.what();
|
error = ex.what();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
error = "Unknown C++ exception.";
|
error = "Unknown C++ exception.";
|
||||||
}
|
}
|
||||||
return error;
|
return std::make_pair(std::move(error), monospace);
|
||||||
}
|
}
|
||||||
|
|
||||||
BackgroundSlicingProcess::BackgroundSlicingProcess()
|
BackgroundSlicingProcess::BackgroundSlicingProcess()
|
||||||
|
@ -57,7 +57,8 @@ public:
|
|||||||
// Only valid if error()
|
// Only valid if error()
|
||||||
void rethrow_exception() const { assert(this->error()); assert(m_exception); std::rethrow_exception(m_exception); }
|
void rethrow_exception() const { assert(this->error()); assert(m_exception); std::rethrow_exception(m_exception); }
|
||||||
// Produce a human readable message to be displayed by a notification or a message box.
|
// Produce a human readable message to be displayed by a notification or a message box.
|
||||||
std::string format_error_message() const;
|
// 2nd parameter defines whether the output should be displayed with a monospace font.
|
||||||
|
std::pair<std::string, bool> format_error_message() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StatusType m_status;
|
StatusType m_status;
|
||||||
|
@ -2457,7 +2457,7 @@ void ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
|||||||
page_temps->apply_custom_config(*custom_config);
|
page_temps->apply_custom_config(*custom_config);
|
||||||
|
|
||||||
const std::string profile_name = page_custom->profile_name();
|
const std::string profile_name = page_custom->profile_name();
|
||||||
preset_bundle->load_config(profile_name, *custom_config);
|
preset_bundle->load_config_from_wizard(profile_name, *custom_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the selections from the compatibilty.
|
// Update the selections from the compatibilty.
|
||||||
|
@ -636,9 +636,9 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool
|
|||||||
auto ¬ification_manager = *wxGetApp().plater()->get_notification_manager();
|
auto ¬ification_manager = *wxGetApp().plater()->get_notification_manager();
|
||||||
if (state) {
|
if (state) {
|
||||||
if(error)
|
if(error)
|
||||||
notification_manager.push_plater_error_notification(text,*(wxGetApp().plater()->get_current_canvas3D()));
|
notification_manager.push_plater_error_notification(text);
|
||||||
else
|
else
|
||||||
notification_manager.push_plater_warning_notification(text, *(wxGetApp().plater()->get_current_canvas3D()));
|
notification_manager.push_plater_warning_notification(text);
|
||||||
} else {
|
} else {
|
||||||
if (error)
|
if (error)
|
||||||
notification_manager.close_plater_error_notification(text);
|
notification_manager.close_plater_error_notification(text);
|
||||||
@ -1728,8 +1728,7 @@ void GLCanvas3D::render()
|
|||||||
m_tooltip.render(m_mouse.position, *this);
|
m_tooltip.render(m_mouse.position, *this);
|
||||||
|
|
||||||
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(*this);
|
wxGetApp().plater()->get_mouse3d_controller().render_settings_dialog(*this);
|
||||||
|
wxGetApp().plater()->get_notification_manager()->render_notifications(get_overlay_window_width());
|
||||||
wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width());
|
|
||||||
|
|
||||||
wxGetApp().imgui()->render();
|
wxGetApp().imgui()->render();
|
||||||
|
|
||||||
@ -2384,6 +2383,14 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
|
|||||||
if (!m_initialized)
|
if (!m_initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
NotificationManager* notification_mgr = wxGetApp().plater()->get_notification_manager();
|
||||||
|
if (notification_mgr->requires_update())
|
||||||
|
notification_mgr->update_notifications();
|
||||||
|
|
||||||
|
m_dirty |= notification_mgr->requires_render();
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
|
||||||
m_dirty |= m_main_toolbar.update_items_state();
|
m_dirty |= m_main_toolbar.update_items_state();
|
||||||
m_dirty |= m_undoredo_toolbar.update_items_state();
|
m_dirty |= m_undoredo_toolbar.update_items_state();
|
||||||
m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state();
|
m_dirty |= wxGetApp().plater()->get_view_toolbar().update_items_state();
|
||||||
@ -2391,12 +2398,24 @@ void GLCanvas3D::on_idle(wxIdleEvent& evt)
|
|||||||
bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera());
|
bool mouse3d_controller_applied = wxGetApp().plater()->get_mouse3d_controller().apply(wxGetApp().plater()->get_camera());
|
||||||
m_dirty |= mouse3d_controller_applied;
|
m_dirty |= mouse3d_controller_applied;
|
||||||
|
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
if (!m_dirty) {
|
||||||
|
if (notification_mgr->requires_update())
|
||||||
|
evt.RequestMore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!m_dirty)
|
if (!m_dirty)
|
||||||
return;
|
return;
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
|
||||||
_refresh_if_shown_on_screen();
|
_refresh_if_shown_on_screen();
|
||||||
|
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
if (m_extra_frame_requested || mouse3d_controller_applied || notification_mgr->requires_update()) {
|
||||||
|
#else
|
||||||
if (m_extra_frame_requested || mouse3d_controller_applied) {
|
if (m_extra_frame_requested || mouse3d_controller_applied) {
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
m_dirty = true;
|
m_dirty = true;
|
||||||
m_extra_frame_requested = false;
|
m_extra_frame_requested = false;
|
||||||
evt.RequestMore();
|
evt.RequestMore();
|
||||||
@ -2531,7 +2550,7 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||||||
case WXK_BACK:
|
case WXK_BACK:
|
||||||
case WXK_DELETE:
|
case WXK_DELETE:
|
||||||
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); break;
|
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE_ALL)); break;
|
||||||
default: evt.Skip();
|
default: evt.Skip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((evt.GetModifiers() & shiftMask) != 0) {
|
else if ((evt.GetModifiers() & shiftMask) != 0) {
|
||||||
@ -2560,7 +2579,13 @@ void GLCanvas3D::on_char(wxKeyEvent& evt)
|
|||||||
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE));
|
post_event(SimpleEvent(EVT_GLTOOLBAR_DELETE));
|
||||||
break;
|
break;
|
||||||
case WXK_ESCAPE: { deselect_all(); break; }
|
case WXK_ESCAPE: { deselect_all(); break; }
|
||||||
case WXK_F5: { post_event(SimpleEvent(EVT_GLCANVAS_RELOAD_FROM_DISK)); break; }
|
case WXK_F5:
|
||||||
|
{
|
||||||
|
if ((wxGetApp().is_editor() && !wxGetApp().plater()->model().objects.empty()) ||
|
||||||
|
(wxGetApp().is_gcode_viewer() && !wxGetApp().plater()->get_last_loaded_gcode().empty()))
|
||||||
|
post_event(SimpleEvent(EVT_GLCANVAS_RELOAD_FROM_DISK));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case '0': { select_view("iso"); break; }
|
case '0': { select_view("iso"); break; }
|
||||||
case '1': { select_view("top"); break; }
|
case '1': { select_view("top"); break; }
|
||||||
case '2': { select_view("bottom"); break; }
|
case '2': { select_view("bottom"); break; }
|
||||||
@ -4972,7 +4997,7 @@ void GLCanvas3D::_render_objects() const
|
|||||||
|
|
||||||
if (m_config != nullptr) {
|
if (m_config != nullptr) {
|
||||||
const BoundingBoxf3& bed_bb = wxGetApp().plater()->get_bed().get_bounding_box(false);
|
const BoundingBoxf3& bed_bb = wxGetApp().plater()->get_bed().get_bounding_box(false);
|
||||||
m_volumes.set_print_box((float)bed_bb.min(0), (float)bed_bb.min(1), 0.0f, (float)bed_bb.max(0), (float)bed_bb.max(1), (float)m_config->opt_float("max_print_height"));
|
m_volumes.set_print_box((float)bed_bb.min(0) - BedEpsilon, (float)bed_bb.min(1) - BedEpsilon, 0.0f, (float)bed_bb.max(0) + BedEpsilon, (float)bed_bb.max(1) + BedEpsilon, (float)m_config->opt_float("max_print_height"));
|
||||||
m_volumes.check_outside_state(m_config, nullptr);
|
m_volumes.check_outside_state(m_config, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,16 +221,16 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_error(wxWindow* parent, const wxString& message)
|
void show_error(wxWindow* parent, const wxString& message, bool monospaced_font)
|
||||||
{
|
{
|
||||||
ErrorDialog msg(parent, message);
|
ErrorDialog msg(parent, message, monospaced_font);
|
||||||
msg.ShowModal();
|
msg.ShowModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_error(wxWindow* parent, const char* message)
|
void show_error(wxWindow* parent, const char* message, bool monospaced_font)
|
||||||
{
|
{
|
||||||
assert(message);
|
assert(message);
|
||||||
show_error(parent, wxString::FromUTF8(message));
|
show_error(parent, wxString::FromUTF8(message), monospaced_font);
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_error_id(int id, const std::string& message)
|
void show_error_id(int id, const std::string& message)
|
||||||
|
@ -39,9 +39,11 @@ extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_
|
|||||||
// Change option value in config
|
// Change option value in config
|
||||||
void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index = 0);
|
void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt_key, const boost::any& value, int opt_index = 0);
|
||||||
|
|
||||||
void show_error(wxWindow* parent, const wxString& message);
|
// If monospaced_font is true, the error message is displayed using html <code><pre></pre></code> tags,
|
||||||
void show_error(wxWindow* parent, const char* message);
|
// so that the code formatting will be preserved. This is useful for reporting errors from the placeholder parser.
|
||||||
inline void show_error(wxWindow* parent, const std::string& message) { show_error(parent, message.c_str()); }
|
void show_error(wxWindow* parent, const wxString& message, bool monospaced_font = false);
|
||||||
|
void show_error(wxWindow* parent, const char* message, bool monospaced_font = false);
|
||||||
|
inline void show_error(wxWindow* parent, const std::string& message, bool monospaced_font = false) { show_error(parent, message.c_str(), monospaced_font); }
|
||||||
void show_error_id(int id, const std::string& message); // For Perl
|
void show_error_id(int id, const std::string& message); // For Perl
|
||||||
void show_info(wxWindow* parent, const wxString& message, const wxString& title = wxString());
|
void show_info(wxWindow* parent, const wxString& message, const wxString& title = wxString());
|
||||||
void show_info(wxWindow* parent, const char* message, const char* title = nullptr);
|
void show_info(wxWindow* parent, const char* message, const char* title = nullptr);
|
||||||
|
@ -820,7 +820,7 @@ bool GUI_App::on_init_inner()
|
|||||||
app_config->save();
|
app_config->save();
|
||||||
if (this->plater_ != nullptr) {
|
if (this->plater_ != nullptr) {
|
||||||
if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(into_u8(evt.GetString()))) {
|
if (*Semver::parse(SLIC3R_VERSION) < *Semver::parse(into_u8(evt.GetString()))) {
|
||||||
this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAvailable, *(this->plater_->get_current_canvas3D()));
|
this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAvailable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -1710,11 +1710,12 @@ bool GUI_App::checked_tab(Tab* tab)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update UI / Tabs to reflect changes in the currently loaded presets
|
// Update UI / Tabs to reflect changes in the currently loaded presets
|
||||||
void GUI_App::load_current_presets()
|
void GUI_App::load_current_presets(bool check_printer_presets_ /*= true*/)
|
||||||
{
|
{
|
||||||
// check printer_presets for the containing information about "Print Host upload"
|
// check printer_presets for the containing information about "Print Host upload"
|
||||||
// and create physical printer from it, if any exists
|
// and create physical printer from it, if any exists
|
||||||
check_printer_presets();
|
if (check_printer_presets_)
|
||||||
|
check_printer_presets();
|
||||||
|
|
||||||
PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology();
|
PrinterTechnology printer_technology = preset_bundle->printers.get_edited_preset().printer_technology();
|
||||||
this->plater()->set_printer_technology(printer_technology);
|
this->plater()->set_printer_technology(printer_technology);
|
||||||
|
@ -206,7 +206,7 @@ public:
|
|||||||
void add_config_menu(wxMenuBar *menu);
|
void add_config_menu(wxMenuBar *menu);
|
||||||
bool check_unsaved_changes(const wxString &header = wxString());
|
bool check_unsaved_changes(const wxString &header = wxString());
|
||||||
bool checked_tab(Tab* tab);
|
bool checked_tab(Tab* tab);
|
||||||
void load_current_presets();
|
void load_current_presets(bool check_printer_presets = true);
|
||||||
|
|
||||||
wxString current_language_code() const { return m_wxLocale->GetCanonicalName(); }
|
wxString current_language_code() const { return m_wxLocale->GetCanonicalName(); }
|
||||||
// Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US".
|
// Translate the language code to a code, for which Prusa Research maintains translations. Defaults to "en_US".
|
||||||
|
@ -1007,7 +1007,7 @@ ManipulationEditor::ManipulationEditor(ObjectManipulation* parent,
|
|||||||
const std::string& opt_key,
|
const std::string& opt_key,
|
||||||
int axis) :
|
int axis) :
|
||||||
wxTextCtrl(parent->parent(), wxID_ANY, wxEmptyString, wxDefaultPosition,
|
wxTextCtrl(parent->parent(), wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||||
wxSize(5*int(wxGetApp().em_unit()), wxDefaultCoord), wxTE_PROCESS_ENTER),
|
wxSize((wxOSX ? 5 : 6)*int(wxGetApp().em_unit()), wxDefaultCoord), wxTE_PROCESS_ENTER),
|
||||||
m_opt_key(opt_key),
|
m_opt_key(opt_key),
|
||||||
m_axis(axis)
|
m_axis(axis)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,8 @@
|
|||||||
#include "format.hpp"
|
#include "format.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include "GUI_App.hpp"
|
#include "GUI_App.hpp"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -84,6 +86,31 @@ public:
|
|||||||
};
|
};
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
|
// Load the icon either from the exe, or from the ico file.
|
||||||
|
static wxIcon main_frame_icon(GUI_App::EAppMode app_mode)
|
||||||
|
{
|
||||||
|
#if _WIN32
|
||||||
|
std::wstring path(size_t(MAX_PATH), wchar_t(0));
|
||||||
|
int len = int(::GetModuleFileName(nullptr, path.data(), MAX_PATH));
|
||||||
|
if (len > 0 && len < MAX_PATH) {
|
||||||
|
path.erase(path.begin() + len, path.end());
|
||||||
|
if (app_mode == GUI_App::EAppMode::GCodeViewer) {
|
||||||
|
// Only in case the slicer was started with --gcodeviewer parameter try to load the icon from prusa-gcodeviewer.exe
|
||||||
|
// Otherwise load it from the exe.
|
||||||
|
for (const std::wstring_view exe_name : { std::wstring_view(L"prusa-slicer.exe"), std::wstring_view(L"prusa-slicer-console.exe") })
|
||||||
|
if (boost::iends_with(path, exe_name)) {
|
||||||
|
path.erase(path.end() - exe_name.size(), path.end());
|
||||||
|
path += L"prusa-gcodeviewer.exe";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wxIcon(path, wxBITMAP_TYPE_ICO);
|
||||||
|
#else // _WIN32
|
||||||
|
return wxIcon(Slic3r::var(app_mode == GUI_App::EAppMode::Editor ? "PrusaSlicer_128px.png" : "PrusaSlicer-gcodeviewer_128px.png"), wxBITMAP_TYPE_PNG);
|
||||||
|
#endif // _WIN32
|
||||||
|
}
|
||||||
|
|
||||||
MainFrame::MainFrame() :
|
MainFrame::MainFrame() :
|
||||||
DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"),
|
DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, "mainframe"),
|
||||||
m_printhost_queue_dlg(new PrintHostQueueDialog(this))
|
m_printhost_queue_dlg(new PrintHostQueueDialog(this))
|
||||||
@ -115,35 +142,7 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
|||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
// 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
|
SetIcon(main_frame_icon(wxGetApp().get_app_mode()));
|
||||||
{
|
|
||||||
wxString src_path;
|
|
||||||
wxFileName::SplitPath(wxStandardPaths::Get().GetExecutablePath(), &src_path, nullptr, nullptr, wxPATH_NATIVE);
|
|
||||||
switch (wxGetApp().get_app_mode()) {
|
|
||||||
default:
|
|
||||||
case GUI_App::EAppMode::Editor: { src_path += "\\prusa-slicer.exe"; break; }
|
|
||||||
case GUI_App::EAppMode::GCodeViewer: { src_path += "\\prusa-gcodeviewer.exe"; break; }
|
|
||||||
}
|
|
||||||
wxIconLocation icon_location;
|
|
||||||
icon_location.SetFileName(src_path);
|
|
||||||
SetIcon(icon_location);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
switch (wxGetApp().get_app_mode())
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case GUI_App::EAppMode::Editor:
|
|
||||||
{
|
|
||||||
SetIcon(wxIcon(Slic3r::var("PrusaSlicer_128px.png"), wxBITMAP_TYPE_PNG));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GUI_App::EAppMode::GCodeViewer:
|
|
||||||
{
|
|
||||||
SetIcon(wxIcon(Slic3r::var("PrusaSlicer-gcodeviewer_128px.png"), wxBITMAP_TYPE_PNG));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
// initialize status bar
|
// initialize status bar
|
||||||
m_statusbar = std::make_shared<ProgressStatusBar>(this);
|
m_statusbar = std::make_shared<ProgressStatusBar>(this);
|
||||||
@ -1243,6 +1242,9 @@ void MainFrame::init_menubar_as_gcodeviewer()
|
|||||||
append_menu_item(fileMenu, wxID_ANY, _L("&Open G-code") + dots + "\tCtrl+O", _L("Open a G-code file"),
|
append_menu_item(fileMenu, wxID_ANY, _L("&Open G-code") + dots + "\tCtrl+O", _L("Open a G-code file"),
|
||||||
[this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->load_gcode(); }, "open", nullptr,
|
[this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->load_gcode(); }, "open", nullptr,
|
||||||
[this]() {return m_plater != nullptr; }, this);
|
[this]() {return m_plater != nullptr; }, this);
|
||||||
|
append_menu_item(fileMenu, wxID_ANY, _L("Re&load from disk") + sep + "F5",
|
||||||
|
_L("Reload the plater from disk"), [this](wxCommandEvent&) { m_plater->reload_gcode_from_disk(); },
|
||||||
|
"", nullptr, [this]() { return !m_plater->get_last_loaded_gcode().empty(); }, this);
|
||||||
fileMenu->AppendSeparator();
|
fileMenu->AppendSeparator();
|
||||||
append_menu_item(fileMenu, wxID_ANY, _L("Export &toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"),
|
append_menu_item(fileMenu, wxID_ANY, _L("Export &toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"),
|
||||||
[this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->export_toolpaths_to_obj(); }, "export_plater", nullptr,
|
[this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->export_toolpaths_to_obj(); }, "export_plater", nullptr,
|
||||||
|
@ -602,7 +602,7 @@ void Mouse3DController::disconnected()
|
|||||||
m_params_by_device[m_device_str] = m_params_ui;
|
m_params_by_device[m_device_str] = m_params_ui;
|
||||||
m_device_str.clear();
|
m_device_str.clear();
|
||||||
m_connected = false;
|
m_connected = false;
|
||||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::Mouse3dDisconnected, *(wxGetApp().plater()->get_current_canvas3D()));
|
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::Mouse3dDisconnected);
|
||||||
|
|
||||||
wxGetApp().plater()->CallAfter([]() {
|
wxGetApp().plater()->CallAfter([]() {
|
||||||
Plater *plater = wxGetApp().plater();
|
Plater *plater = wxGetApp().plater();
|
||||||
|
@ -64,12 +64,9 @@ MsgDialog::MsgDialog(wxWindow *parent, const wxString &title, const wxString &he
|
|||||||
SetSizerAndFit(topsizer);
|
SetSizerAndFit(topsizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgDialog::~MsgDialog() {}
|
|
||||||
|
|
||||||
|
|
||||||
// ErrorDialog
|
// ErrorDialog
|
||||||
|
|
||||||
ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg)
|
ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg, bool monospaced_font)
|
||||||
: MsgDialog(parent, wxString::Format(_(L("%s error")), SLIC3R_APP_NAME),
|
: MsgDialog(parent, wxString::Format(_(L("%s error")), SLIC3R_APP_NAME),
|
||||||
wxString::Format(_(L("%s has encountered an error")), SLIC3R_APP_NAME),
|
wxString::Format(_(L("%s has encountered an error")), SLIC3R_APP_NAME),
|
||||||
wxID_NONE)
|
wxID_NONE)
|
||||||
@ -78,19 +75,23 @@ ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg)
|
|||||||
// Text shown as HTML, so that mouse selection and Ctrl-V to copy will work.
|
// Text shown as HTML, so that mouse selection and Ctrl-V to copy will work.
|
||||||
wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO);
|
wxHtmlWindow* html = new wxHtmlWindow(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO);
|
||||||
{
|
{
|
||||||
html->SetMinSize(wxSize(40 * wxGetApp().em_unit(), -1));
|
html->SetMinSize(wxSize(40 * wxGetApp().em_unit(), monospaced_font ? 30 * wxGetApp().em_unit() : -1));
|
||||||
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||||
|
wxFont monospace = wxSystemSettings::GetFont(wxSYS_ANSI_FIXED_FONT);
|
||||||
wxColour text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
wxColour text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||||
wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
wxColour bgr_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||||
auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue());
|
auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue());
|
||||||
auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue());
|
auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue());
|
||||||
const int font_size = font.GetPointSize()-1;
|
const int font_size = font.GetPointSize()-1;
|
||||||
int size[] = {font_size, font_size, font_size, font_size, font_size, font_size, font_size};
|
int size[] = {font_size, font_size, font_size, font_size, font_size, font_size, font_size};
|
||||||
html->SetFonts(font.GetFaceName(), font.GetFaceName(), size);
|
html->SetFonts(font.GetFaceName(), monospace.GetFaceName(), size);
|
||||||
html->SetBorders(2);
|
html->SetBorders(2);
|
||||||
std::string msg_escaped = xml_escape(msg.ToUTF8().data());
|
std::string msg_escaped = xml_escape(msg.ToUTF8().data());
|
||||||
boost::replace_all(msg_escaped, "\r\n", "<br>");
|
boost::replace_all(msg_escaped, "\r\n", "<br>");
|
||||||
boost::replace_all(msg_escaped, "\n", "<br>");
|
boost::replace_all(msg_escaped, "\n", "<br>");
|
||||||
|
if (monospaced_font)
|
||||||
|
// Code formatting will be preserved. This is useful for reporting errors from the placeholder parser.
|
||||||
|
msg_escaped = std::string("<pre><code>") + msg_escaped + "</code></pre>";
|
||||||
html->SetPage("<html><body bgcolor=\"" + bgr_clr_str + "\"><font color=\"" + text_clr_str + "\">" + wxString::FromUTF8(msg_escaped.data()) + "</font></body></html>");
|
html->SetPage("<html><body bgcolor=\"" + bgr_clr_str + "\"><font color=\"" + text_clr_str + "\">" + wxString::FromUTF8(msg_escaped.data()) + "</font></body></html>");
|
||||||
content_sizer->Add(html, 1, wxEXPAND);
|
content_sizer->Add(html, 1, wxEXPAND);
|
||||||
}
|
}
|
||||||
@ -99,15 +100,12 @@ ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg)
|
|||||||
btn_ok->SetFocus();
|
btn_ok->SetFocus();
|
||||||
btn_sizer->Add(btn_ok, 0, wxRIGHT, HORIZ_SPACING);
|
btn_sizer->Add(btn_ok, 0, wxRIGHT, HORIZ_SPACING);
|
||||||
|
|
||||||
logo->SetBitmap(create_scaled_bitmap("PrusaSlicer_192px_grayscale.png", this, 192));
|
// Use a small bitmap with monospaced font, as the error text will not be wrapped.
|
||||||
|
logo->SetBitmap(create_scaled_bitmap("PrusaSlicer_192px_grayscale.png", this, monospaced_font ? 48 : 192));
|
||||||
|
|
||||||
SetMaxSize(wxSize(-1, CONTENT_MAX_HEIGHT*wxGetApp().em_unit()));
|
SetMaxSize(wxSize(-1, CONTENT_MAX_HEIGHT*wxGetApp().em_unit()));
|
||||||
Fit();
|
Fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorDialog::~ErrorDialog() {}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ struct MsgDialog : wxDialog
|
|||||||
MsgDialog(const MsgDialog &) = delete;
|
MsgDialog(const MsgDialog &) = delete;
|
||||||
MsgDialog &operator=(MsgDialog &&) = delete;
|
MsgDialog &operator=(MsgDialog &&) = delete;
|
||||||
MsgDialog &operator=(const MsgDialog &) = delete;
|
MsgDialog &operator=(const MsgDialog &) = delete;
|
||||||
virtual ~MsgDialog();
|
virtual ~MsgDialog() = default;
|
||||||
|
|
||||||
// TODO: refactor with CreateStdDialogButtonSizer usage
|
// TODO: refactor with CreateStdDialogButtonSizer usage
|
||||||
|
|
||||||
@ -52,12 +52,14 @@ protected:
|
|||||||
class ErrorDialog : public MsgDialog
|
class ErrorDialog : public MsgDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ErrorDialog(wxWindow *parent, const wxString &msg);
|
// If monospaced_font is true, the error message is displayed using html <code><pre></pre></code> tags,
|
||||||
|
// so that the code formatting will be preserved. This is useful for reporting errors from the placeholder parser.
|
||||||
|
ErrorDialog(wxWindow *parent, const wxString &msg, bool courier_font);
|
||||||
ErrorDialog(ErrorDialog &&) = delete;
|
ErrorDialog(ErrorDialog &&) = delete;
|
||||||
ErrorDialog(const ErrorDialog &) = delete;
|
ErrorDialog(const ErrorDialog &) = delete;
|
||||||
ErrorDialog &operator=(ErrorDialog &&) = delete;
|
ErrorDialog &operator=(ErrorDialog &&) = delete;
|
||||||
ErrorDialog &operator=(const ErrorDialog &) = delete;
|
ErrorDialog &operator=(const ErrorDialog &) = delete;
|
||||||
virtual ~ErrorDialog();
|
virtual ~ErrorDialog() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxString msg;
|
wxString msg;
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
static constexpr float GAP_WIDTH = 10.0f;
|
static constexpr float GAP_WIDTH = 10.0f;
|
||||||
static constexpr float SPACE_RIGHT_PANEL = 10.0f;
|
static constexpr float SPACE_RIGHT_PANEL = 10.0f;
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
static constexpr float FADING_OUT_DURATION = 2.0f;
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
@ -134,6 +137,96 @@ NotificationManager::PopNotification::PopNotification(const NotificationData &n,
|
|||||||
{
|
{
|
||||||
//init();
|
//init();
|
||||||
}
|
}
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
void NotificationManager::PopNotification::render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width)
|
||||||
|
{
|
||||||
|
if (m_hidden) {
|
||||||
|
m_top_y = initial_y - GAP_WIDTH;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size cnv_size = canvas.get_canvas_size();
|
||||||
|
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||||
|
ImVec2 mouse_pos = ImGui::GetMousePos();
|
||||||
|
float right_gap = SPACE_RIGHT_PANEL + (move_from_overlay ? overlay_width + m_line_height * 5 : 0);
|
||||||
|
|
||||||
|
if (m_line_height != ImGui::CalcTextSize("A").y)
|
||||||
|
init();
|
||||||
|
|
||||||
|
set_next_window_size(imgui);
|
||||||
|
|
||||||
|
// top y of window
|
||||||
|
m_top_y = initial_y + m_window_height;
|
||||||
|
|
||||||
|
ImVec2 win_pos(1.0f * (float)cnv_size.get_width() - right_gap, 1.0f * (float)cnv_size.get_height() - m_top_y);
|
||||||
|
imgui.set_next_window_pos(win_pos.x, win_pos.y, ImGuiCond_Always, 1.0f, 0.0f);
|
||||||
|
imgui.set_next_window_size(m_window_width, m_window_height, ImGuiCond_Always);
|
||||||
|
|
||||||
|
// find if hovered
|
||||||
|
m_hovered = false;
|
||||||
|
if (mouse_pos.x < win_pos.x && mouse_pos.x > win_pos.x - m_window_width && mouse_pos.y > win_pos.y && mouse_pos.y < win_pos.y + m_window_height) {
|
||||||
|
ImGui::SetNextWindowFocus();
|
||||||
|
m_hovered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// color change based on fading out
|
||||||
|
bool fading_pop = false;
|
||||||
|
if (m_fading_out) {
|
||||||
|
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, ImGui::GetStyleColorVec4(ImGuiCol_WindowBg), m_fading_out, m_current_fade_opacity);
|
||||||
|
Notifications_Internal::push_style_color(ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_Text), m_fading_out, m_current_fade_opacity);
|
||||||
|
fading_pop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// background color
|
||||||
|
if (m_is_gray) {
|
||||||
|
ImVec4 backcolor(0.7f, 0.7f, 0.7f, 0.5f);
|
||||||
|
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_fading_out, m_current_fade_opacity);
|
||||||
|
}
|
||||||
|
else if (m_data.level == NotificationLevel::ErrorNotification) {
|
||||||
|
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
|
||||||
|
backcolor.x += 0.3f;
|
||||||
|
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_fading_out, m_current_fade_opacity);
|
||||||
|
}
|
||||||
|
else if (m_data.level == NotificationLevel::WarningNotification) {
|
||||||
|
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
|
||||||
|
backcolor.x += 0.3f;
|
||||||
|
backcolor.y += 0.15f;
|
||||||
|
Notifications_Internal::push_style_color(ImGuiCol_WindowBg, backcolor, m_fading_out, m_current_fade_opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// name of window - probably indentifies window and is shown so last_end add whitespaces according to id
|
||||||
|
if (m_id == 0)
|
||||||
|
m_id = m_id_provider.allocate_id();
|
||||||
|
std::string name = "!!Ntfctn" + std::to_string(m_id);
|
||||||
|
if (imgui.begin(name, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar)) {
|
||||||
|
ImVec2 win_size = ImGui::GetWindowSize();
|
||||||
|
|
||||||
|
//FIXME: dont forget to us this for texts
|
||||||
|
//GUI::format(_utf8(L()));
|
||||||
|
|
||||||
|
/*
|
||||||
|
//countdown numbers
|
||||||
|
ImGui::SetCursorPosX(15);
|
||||||
|
ImGui::SetCursorPosY(15);
|
||||||
|
imgui.text(std::to_string(m_remaining_time).c_str());
|
||||||
|
*/
|
||||||
|
|
||||||
|
render_left_sign(imgui);
|
||||||
|
render_text(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
|
||||||
|
render_close_button(imgui, win_size.x, win_size.y, win_pos.x, win_pos.y);
|
||||||
|
m_minimize_b_visible = false;
|
||||||
|
if (m_multiline && m_lines_count > 3)
|
||||||
|
render_minimize_button(imgui, win_pos.x, win_pos.y);
|
||||||
|
}
|
||||||
|
imgui.end();
|
||||||
|
|
||||||
|
if (m_is_gray || m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification)
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
|
if (fading_pop)
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
|
}
|
||||||
|
#else
|
||||||
NotificationManager::PopNotification::RenderResult NotificationManager::PopNotification::render(GLCanvas3D& canvas, const float& initial_y, bool move_from_overlay, float overlay_width)
|
NotificationManager::PopNotification::RenderResult NotificationManager::PopNotification::render(GLCanvas3D& canvas, const float& initial_y, bool move_from_overlay, float overlay_width)
|
||||||
{
|
{
|
||||||
if (!m_initialized) {
|
if (!m_initialized) {
|
||||||
@ -268,6 +361,7 @@ NotificationManager::PopNotification::RenderResult NotificationManager::PopNotif
|
|||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
return ret_val;
|
return ret_val;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
void NotificationManager::PopNotification::count_spaces()
|
void NotificationManager::PopNotification::count_spaces()
|
||||||
{
|
{
|
||||||
//determine line width
|
//determine line width
|
||||||
@ -528,6 +622,7 @@ void NotificationManager::PopNotification::render_close_button(ImGuiWrapper& img
|
|||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
}
|
}
|
||||||
|
#if !ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
void NotificationManager::PopNotification::render_countdown(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
void NotificationManager::PopNotification::render_countdown(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -575,6 +670,7 @@ void NotificationManager::PopNotification::render_countdown(ImGuiWrapper& imgui,
|
|||||||
m_countdown_frame++;
|
m_countdown_frame++;
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
void NotificationManager::PopNotification::render_left_sign(ImGuiWrapper& imgui)
|
void NotificationManager::PopNotification::render_left_sign(ImGuiWrapper& imgui)
|
||||||
{
|
{
|
||||||
if (m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification) {
|
if (m_data.level == NotificationLevel::ErrorNotification || m_data.level == NotificationLevel::WarningNotification) {
|
||||||
@ -643,6 +739,52 @@ bool NotificationManager::PopNotification::compare_text(const std::string& text)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
void NotificationManager::PopNotification::update_state()
|
||||||
|
{
|
||||||
|
if (!m_initialized)
|
||||||
|
init();
|
||||||
|
|
||||||
|
if (m_hidden) {
|
||||||
|
m_state = EState::Static;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hovered) {
|
||||||
|
// reset fading
|
||||||
|
m_fading_out = false;
|
||||||
|
m_current_fade_opacity = 1.0f;
|
||||||
|
m_remaining_time = m_data.duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_counting_down) {
|
||||||
|
if (m_fading_out && m_current_fade_opacity <= 0.0f)
|
||||||
|
m_finished = true;
|
||||||
|
else if (!m_fading_out && m_remaining_time == 0) {
|
||||||
|
m_fading_out = true;
|
||||||
|
m_fading_start = wxGetLocalTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_finished) {
|
||||||
|
m_state = EState::Finished;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_close_pending) {
|
||||||
|
m_finished = true;
|
||||||
|
m_state = EState::ClosePending;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_fading_out) {
|
||||||
|
if (!m_paused) {
|
||||||
|
wxMilliClock_t curr_time = wxGetLocalTimeMillis() - m_fading_start;
|
||||||
|
m_current_fade_opacity = std::clamp(1.0f - 0.001f * static_cast<float>(curr_time.GetValue()) / FADING_OUT_DURATION, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
m_state = EState::FadingOut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
|
||||||
NotificationManager::SlicingCompleteLargeNotification::SlicingCompleteLargeNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool large) :
|
NotificationManager::SlicingCompleteLargeNotification::SlicingCompleteLargeNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool large) :
|
||||||
NotificationManager::PopNotification(n, id_provider, evt_handler)
|
NotificationManager::PopNotification(n, id_provider, evt_handler)
|
||||||
{
|
{
|
||||||
@ -849,19 +991,19 @@ NotificationManager::NotificationManager(wxEvtHandler* evt_handler) :
|
|||||||
m_evt_handler(evt_handler)
|
m_evt_handler(evt_handler)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void NotificationManager::push_notification(const NotificationType type, GLCanvas3D& canvas, int timestamp)
|
void NotificationManager::push_notification(const NotificationType type, int timestamp)
|
||||||
{
|
{
|
||||||
auto it = std::find_if(basic_notifications.begin(), basic_notifications.end(),
|
auto it = std::find_if(basic_notifications.begin(), basic_notifications.end(),
|
||||||
boost::bind(&NotificationData::type, boost::placeholders::_1) == type);
|
boost::bind(&NotificationData::type, boost::placeholders::_1) == type);
|
||||||
assert(it != basic_notifications.end());
|
assert(it != basic_notifications.end());
|
||||||
if (it != basic_notifications.end())
|
if (it != basic_notifications.end())
|
||||||
push_notification_data( *it, canvas, timestamp);
|
push_notification_data(*it, timestamp);
|
||||||
}
|
}
|
||||||
void NotificationManager::push_notification(const std::string& text, GLCanvas3D& canvas, int timestamp)
|
void NotificationManager::push_notification(const std::string& text, int timestamp)
|
||||||
{
|
{
|
||||||
push_notification_data({ NotificationType::CustomNotification, NotificationLevel::RegularNotification, 10, text }, canvas, timestamp );
|
push_notification_data({ NotificationType::CustomNotification, NotificationLevel::RegularNotification, 10, text }, timestamp);
|
||||||
}
|
}
|
||||||
void NotificationManager::push_notification(const std::string& text, NotificationManager::NotificationLevel level, GLCanvas3D& canvas, int timestamp)
|
void NotificationManager::push_notification(const std::string& text, NotificationManager::NotificationLevel level, int timestamp)
|
||||||
{
|
{
|
||||||
int duration = 0;
|
int duration = 0;
|
||||||
switch (level) {
|
switch (level) {
|
||||||
@ -872,32 +1014,32 @@ void NotificationManager::push_notification(const std::string& text, Notificatio
|
|||||||
assert(false);
|
assert(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
push_notification_data({ NotificationType::CustomNotification, level, duration, text }, canvas, timestamp);
|
push_notification_data({ NotificationType::CustomNotification, level, duration, text }, timestamp);
|
||||||
}
|
}
|
||||||
void NotificationManager::push_slicing_error_notification(const std::string& text, GLCanvas3D& canvas)
|
void NotificationManager::push_slicing_error_notification(const std::string& text)
|
||||||
{
|
{
|
||||||
set_all_slicing_errors_gray(false);
|
set_all_slicing_errors_gray(false);
|
||||||
push_notification_data({ NotificationType::SlicingError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, canvas, 0);
|
push_notification_data({ NotificationType::SlicingError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, 0);
|
||||||
close_notification_of_type(NotificationType::SlicingComplete);
|
close_notification_of_type(NotificationType::SlicingComplete);
|
||||||
}
|
}
|
||||||
void NotificationManager::push_slicing_warning_notification(const std::string& text, bool gray, GLCanvas3D& canvas, ObjectID oid, int warning_step)
|
void NotificationManager::push_slicing_warning_notification(const std::string& text, bool gray, ObjectID oid, int warning_step)
|
||||||
{
|
{
|
||||||
NotificationData data { NotificationType::SlicingWarning, NotificationLevel::WarningNotification, 0, _u8L("WARNING:") + "\n" + text };
|
NotificationData data { NotificationType::SlicingWarning, NotificationLevel::WarningNotification, 0, _u8L("WARNING:") + "\n" + text };
|
||||||
|
|
||||||
auto notification = std::make_unique<NotificationManager::SlicingWarningNotification>(data, m_id_provider, m_evt_handler);
|
auto notification = std::make_unique<NotificationManager::SlicingWarningNotification>(data, m_id_provider, m_evt_handler);
|
||||||
notification->object_id = oid;
|
notification->object_id = oid;
|
||||||
notification->warning_step = warning_step;
|
notification->warning_step = warning_step;
|
||||||
if (push_notification_data(std::move(notification), canvas, 0)) {
|
if (push_notification_data(std::move(notification), 0)) {
|
||||||
m_pop_notifications.back()->set_gray(gray);
|
m_pop_notifications.back()->set_gray(gray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void NotificationManager::push_plater_error_notification(const std::string& text, GLCanvas3D& canvas)
|
void NotificationManager::push_plater_error_notification(const std::string& text)
|
||||||
{
|
{
|
||||||
push_notification_data({ NotificationType::PlaterError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, canvas, 0);
|
push_notification_data({ NotificationType::PlaterError, NotificationLevel::ErrorNotification, 0, _u8L("ERROR:") + "\n" + text }, 0);
|
||||||
}
|
}
|
||||||
void NotificationManager::push_plater_warning_notification(const std::string& text, GLCanvas3D& canvas)
|
void NotificationManager::push_plater_warning_notification(const std::string& text)
|
||||||
{
|
{
|
||||||
push_notification_data({ NotificationType::PlaterWarning, NotificationLevel::WarningNotification, 0, _u8L("WARNING:") + "\n" + text }, canvas, 0);
|
push_notification_data({ NotificationType::PlaterWarning, NotificationLevel::WarningNotification, 0, _u8L("WARNING:") + "\n" + text }, 0);
|
||||||
// dissaper if in preview
|
// dissaper if in preview
|
||||||
set_in_preview(m_in_preview);
|
set_in_preview(m_in_preview);
|
||||||
}
|
}
|
||||||
@ -951,7 +1093,7 @@ void NotificationManager::close_slicing_errors_and_warnings()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void NotificationManager::push_slicing_complete_notification(GLCanvas3D& canvas, int timestamp, bool large)
|
void NotificationManager::push_slicing_complete_notification(int timestamp, bool large)
|
||||||
{
|
{
|
||||||
std::string hypertext;
|
std::string hypertext;
|
||||||
int time = 10;
|
int time = 10;
|
||||||
@ -963,8 +1105,7 @@ void NotificationManager::push_slicing_complete_notification(GLCanvas3D& canvas,
|
|||||||
}
|
}
|
||||||
NotificationData data{ NotificationType::SlicingComplete, NotificationLevel::RegularNotification, time, _u8L("Slicing finished."), hypertext, [](wxEvtHandler* evnthndlr){
|
NotificationData data{ NotificationType::SlicingComplete, NotificationLevel::RegularNotification, time, _u8L("Slicing finished."), hypertext, [](wxEvtHandler* evnthndlr){
|
||||||
if (evnthndlr != nullptr) wxPostEvent(evnthndlr, ExportGcodeNotificationClickedEvent(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED)); return true; } };
|
if (evnthndlr != nullptr) wxPostEvent(evnthndlr, ExportGcodeNotificationClickedEvent(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED)); return true; } };
|
||||||
push_notification_data(std::make_unique<NotificationManager::SlicingCompleteLargeNotification>(data, m_id_provider, m_evt_handler, large),
|
push_notification_data(std::make_unique<NotificationManager::SlicingCompleteLargeNotification>(data, m_id_provider, m_evt_handler, large), timestamp);
|
||||||
canvas, timestamp);
|
|
||||||
}
|
}
|
||||||
void NotificationManager::set_slicing_complete_print_time(const std::string &info)
|
void NotificationManager::set_slicing_complete_print_time(const std::string &info)
|
||||||
{
|
{
|
||||||
@ -1001,38 +1142,41 @@ void NotificationManager::remove_slicing_warnings_of_released_objects(const std:
|
|||||||
notification->close();
|
notification->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void NotificationManager::push_exporting_finished_notification(GLCanvas3D& canvas, std::string path, std::string dir_path, bool on_removable)
|
void NotificationManager::push_exporting_finished_notification(const std::string& path, const std::string& dir_path, bool on_removable)
|
||||||
{
|
{
|
||||||
close_notification_of_type(NotificationType::ExportFinished);
|
close_notification_of_type(NotificationType::ExportFinished);
|
||||||
NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotification, 0, _u8L("Exporting finished.") +"\n"+ path };
|
NotificationData data{ NotificationType::ExportFinished, NotificationLevel::RegularNotification, 0, _u8L("Exporting finished.") + "\n" + path };
|
||||||
push_notification_data(std::make_unique<NotificationManager::ExportFinishedNotification>(data, m_id_provider, m_evt_handler, on_removable, path, dir_path),
|
push_notification_data(std::make_unique<NotificationManager::ExportFinishedNotification>(data, m_id_provider, m_evt_handler, on_removable, path, dir_path), 0);
|
||||||
canvas, 0);
|
|
||||||
}
|
}
|
||||||
void NotificationManager::push_progress_bar_notification(const std::string& text, GLCanvas3D& canvas, float percentage)
|
void NotificationManager::push_progress_bar_notification(const std::string& text, float percentage)
|
||||||
{
|
{
|
||||||
NotificationData data{ NotificationType::ProgressBar, NotificationLevel::ProgressBarNotification, 0, text };
|
NotificationData data{ NotificationType::ProgressBar, NotificationLevel::ProgressBarNotification, 0, text };
|
||||||
push_notification_data(std::make_unique<NotificationManager::ProgressBarNotification>(data, m_id_provider, m_evt_handler, 0),canvas, 0);
|
push_notification_data(std::make_unique<NotificationManager::ProgressBarNotification>(data, m_id_provider, m_evt_handler, 0), 0);
|
||||||
}
|
}
|
||||||
void NotificationManager::set_progress_bar_percentage(const std::string& text, float percentage, GLCanvas3D& canvas)
|
void NotificationManager::set_progress_bar_percentage(const std::string& text, float percentage)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||||
if (notification->get_type() == NotificationType::ProgressBar && notification->compare_text(text)) {
|
if (notification->get_type() == NotificationType::ProgressBar && notification->compare_text(text)) {
|
||||||
dynamic_cast<ProgressBarNotification*>(notification.get())->set_percentage(percentage);
|
dynamic_cast<ProgressBarNotification*>(notification.get())->set_percentage(percentage);
|
||||||
canvas.request_extra_frame();
|
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame();
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
push_progress_bar_notification(text, canvas, percentage);
|
push_progress_bar_notification(text, percentage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool NotificationManager::push_notification_data(const NotificationData ¬ification_data, GLCanvas3D& canvas, int timestamp)
|
bool NotificationManager::push_notification_data(const NotificationData& notification_data, int timestamp)
|
||||||
{
|
{
|
||||||
return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler), canvas, timestamp);
|
return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler), timestamp);
|
||||||
}
|
}
|
||||||
bool NotificationManager::push_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, GLCanvas3D& canvas, int timestamp)
|
bool NotificationManager::push_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, int timestamp)
|
||||||
{
|
{
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
m_requires_update = true;
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
|
||||||
// if timestamped notif, push only new one
|
// if timestamped notif, push only new one
|
||||||
if (timestamp != 0) {
|
if (timestamp != 0) {
|
||||||
if (m_used_timestamps.find(timestamp) == m_used_timestamps.end()) {
|
if (m_used_timestamps.find(timestamp) == m_used_timestamps.end()) {
|
||||||
@ -1041,6 +1185,9 @@ bool NotificationManager::push_notification_data(std::unique_ptr<NotificationMan
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLCanvas3D& canvas = *wxGetApp().plater()->get_current_canvas3D();
|
||||||
|
|
||||||
if (this->activate_existing(notification.get())) {
|
if (this->activate_existing(notification.get())) {
|
||||||
m_pop_notifications.back()->update(notification->get_data());
|
m_pop_notifications.back()->update(notification->get_data());
|
||||||
canvas.request_extra_frame();
|
canvas.request_extra_frame();
|
||||||
@ -1051,7 +1198,22 @@ bool NotificationManager::push_notification_data(std::unique_ptr<NotificationMan
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay_width)
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
void NotificationManager::render_notifications(float overlay_width)
|
||||||
|
{
|
||||||
|
sort_notifications();
|
||||||
|
|
||||||
|
GLCanvas3D& canvas = *wxGetApp().plater()->get_current_canvas3D();
|
||||||
|
float last_y = 0.0f;
|
||||||
|
|
||||||
|
for (const auto& notification : m_pop_notifications) {
|
||||||
|
notification->render(canvas, last_y, m_move_from_overlay && !m_in_preview, overlay_width);
|
||||||
|
if (notification->get_state() != PopNotification::EState::Finished)
|
||||||
|
last_y = notification->get_top() + GAP_WIDTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void NotificationManager::render_notifications(float overlay_width)
|
||||||
{
|
{
|
||||||
float last_x = 0.0f;
|
float last_x = 0.0f;
|
||||||
float current_height = 0.0f;
|
float current_height = 0.0f;
|
||||||
@ -1059,9 +1221,12 @@ void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay
|
|||||||
bool render_main = false;
|
bool render_main = false;
|
||||||
bool hovered = false;
|
bool hovered = false;
|
||||||
sort_notifications();
|
sort_notifications();
|
||||||
// iterate thru notifications and render them / erease them
|
|
||||||
|
GLCanvas3D& canvas = *wxGetApp().plater()->get_current_canvas3D();
|
||||||
|
|
||||||
|
// iterate thru notifications and render them / erase them
|
||||||
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
|
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
|
||||||
if ((*it)->get_finished()) {
|
if ((*it)->is_finished()) {
|
||||||
it = m_pop_notifications.erase(it);
|
it = m_pop_notifications.erase(it);
|
||||||
} else {
|
} else {
|
||||||
(*it)->set_paused(m_hovered);
|
(*it)->set_paused(m_hovered);
|
||||||
@ -1111,6 +1276,7 @@ void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay
|
|||||||
// If any of the notifications is fading out, 100% of the CPU/GPU is consumed.
|
// If any of the notifications is fading out, 100% of the CPU/GPU is consumed.
|
||||||
canvas.request_extra_frame();
|
canvas.request_extra_frame();
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
|
||||||
void NotificationManager::sort_notifications()
|
void NotificationManager::sort_notifications()
|
||||||
{
|
{
|
||||||
@ -1118,7 +1284,7 @@ void NotificationManager::sort_notifications()
|
|||||||
std::stable_sort(m_pop_notifications.begin(), m_pop_notifications.end(), [](const std::unique_ptr<PopNotification> &n1, const std::unique_ptr<PopNotification> &n2) {
|
std::stable_sort(m_pop_notifications.begin(), m_pop_notifications.end(), [](const std::unique_ptr<PopNotification> &n1, const std::unique_ptr<PopNotification> &n2) {
|
||||||
int n1l = (int)n1->get_data().level;
|
int n1l = (int)n1->get_data().level;
|
||||||
int n2l = (int)n2->get_data().level;
|
int n2l = (int)n2->get_data().level;
|
||||||
if (n1l == n2l && n1->get_is_gray() && !n2->get_is_gray())
|
if (n1l == n2l && n1->is_gray() && !n2->is_gray())
|
||||||
return true;
|
return true;
|
||||||
return (n1l < n2l);
|
return (n1l < n2l);
|
||||||
});
|
});
|
||||||
@ -1129,7 +1295,7 @@ bool NotificationManager::activate_existing(const NotificationManager::PopNotifi
|
|||||||
NotificationType new_type = notification->get_type();
|
NotificationType new_type = notification->get_type();
|
||||||
const std::string &new_text = notification->get_data().text1;
|
const std::string &new_text = notification->get_data().text1;
|
||||||
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end(); ++it) {
|
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end(); ++it) {
|
||||||
if ((*it)->get_type() == new_type && !(*it)->get_finished()) {
|
if ((*it)->get_type() == new_type && !(*it)->is_finished()) {
|
||||||
if (new_type == NotificationType::CustomNotification || new_type == NotificationType::PlaterWarning) {
|
if (new_type == NotificationType::CustomNotification || new_type == NotificationType::PlaterWarning) {
|
||||||
if (!(*it)->compare_text(new_text))
|
if (!(*it)->compare_text(new_text))
|
||||||
continue;
|
continue;
|
||||||
@ -1162,6 +1328,78 @@ void NotificationManager::set_in_preview(bool preview)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
void NotificationManager::update_notifications()
|
||||||
|
{
|
||||||
|
static size_t last_size = 0;
|
||||||
|
|
||||||
|
for (auto it = m_pop_notifications.begin(); it != m_pop_notifications.end();) {
|
||||||
|
std::unique_ptr<PopNotification>& notification = *it;
|
||||||
|
if (notification->get_state() == PopNotification::EState::Finished)
|
||||||
|
it = m_pop_notifications.erase(it);
|
||||||
|
else {
|
||||||
|
notification->set_paused(m_hovered);
|
||||||
|
notification->update_state();
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_requires_update = false;
|
||||||
|
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||||
|
if (notification->requires_update()) {
|
||||||
|
m_requires_update = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update hovering state
|
||||||
|
m_hovered = false;
|
||||||
|
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||||
|
if (notification->is_hovered()) {
|
||||||
|
m_hovered = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t curr_size = m_pop_notifications.size();
|
||||||
|
m_requires_render = m_hovered || (last_size != curr_size);
|
||||||
|
last_size = curr_size;
|
||||||
|
|
||||||
|
if (!m_requires_render) {
|
||||||
|
for (const std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||||
|
if (notification->requires_render()) {
|
||||||
|
m_requires_render = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// actualizate timers
|
||||||
|
wxWindow* p = dynamic_cast<wxWindow*>(wxGetApp().plater());
|
||||||
|
while (p->GetParent() != nullptr)
|
||||||
|
p = p->GetParent();
|
||||||
|
wxTopLevelWindow* top_level_wnd = dynamic_cast<wxTopLevelWindow*>(p);
|
||||||
|
if (!top_level_wnd->IsActive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
{
|
||||||
|
// Control the fade-out.
|
||||||
|
// time in seconds
|
||||||
|
long now = wxGetLocalTime();
|
||||||
|
// Pausing fade-out when the mouse is over some notification.
|
||||||
|
if (!m_hovered && m_last_time < now) {
|
||||||
|
if (now - m_last_time >= 1) {
|
||||||
|
for (auto& notification : m_pop_notifications) {
|
||||||
|
if (notification->get_state() != PopNotification::EState::Static)
|
||||||
|
notification->substract_remaining_time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_last_time = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
|
||||||
bool NotificationManager::has_slicing_error_notification()
|
bool NotificationManager::has_slicing_error_notification()
|
||||||
{
|
{
|
||||||
return std::any_of(m_pop_notifications.begin(), m_pop_notifications.end(), [](auto &n) {
|
return std::any_of(m_pop_notifications.begin(), m_pop_notifications.end(), [](auto &n) {
|
||||||
|
@ -87,16 +87,16 @@ public:
|
|||||||
NotificationManager(wxEvtHandler* evt_handler);
|
NotificationManager(wxEvtHandler* evt_handler);
|
||||||
|
|
||||||
// Push a prefabricated notification from basic_notifications (see the table at the end of this file).
|
// Push a prefabricated notification from basic_notifications (see the table at the end of this file).
|
||||||
void push_notification(const NotificationType type, GLCanvas3D& canvas, int timestamp = 0);
|
void push_notification(const NotificationType type, int timestamp = 0);
|
||||||
// Push a NotificationType::CustomNotification with NotificationLevel::RegularNotification and 10s fade out interval.
|
// Push a NotificationType::CustomNotification with NotificationLevel::RegularNotification and 10s fade out interval.
|
||||||
void push_notification(const std::string& text, GLCanvas3D& canvas, int timestamp = 0);
|
void push_notification(const std::string& text, int timestamp = 0);
|
||||||
// Push a NotificationType::CustomNotification with provided notification level and 10s for RegularNotification.
|
// Push a NotificationType::CustomNotification with provided notification level and 10s for RegularNotification.
|
||||||
// ErrorNotification and ImportantNotification are never faded out.
|
// ErrorNotification and ImportantNotification are never faded out.
|
||||||
void push_notification(const std::string& text, NotificationLevel level, GLCanvas3D& canvas, int timestamp = 0);
|
void push_notification(const std::string& text, NotificationLevel level, int timestamp = 0);
|
||||||
// Creates Slicing Error notification with a custom text and no fade out.
|
// Creates Slicing Error notification with a custom text and no fade out.
|
||||||
void push_slicing_error_notification(const std::string& text, GLCanvas3D& canvas);
|
void push_slicing_error_notification(const std::string& text);
|
||||||
// Creates Slicing Warning notification with a custom text and no fade out.
|
// Creates Slicing Warning notification with a custom text and no fade out.
|
||||||
void push_slicing_warning_notification(const std::string& text, bool gray, GLCanvas3D& canvas, ObjectID oid, int warning_step);
|
void push_slicing_warning_notification(const std::string& text, bool gray, ObjectID oid, int warning_step);
|
||||||
// marks slicing errors as gray
|
// marks slicing errors as gray
|
||||||
void set_all_slicing_errors_gray(bool g);
|
void set_all_slicing_errors_gray(bool g);
|
||||||
// marks slicing warings as gray
|
// marks slicing warings as gray
|
||||||
@ -108,39 +108,45 @@ public:
|
|||||||
// living_oids is expected to be sorted.
|
// living_oids is expected to be sorted.
|
||||||
void remove_slicing_warnings_of_released_objects(const std::vector<ObjectID>& living_oids);
|
void remove_slicing_warnings_of_released_objects(const std::vector<ObjectID>& living_oids);
|
||||||
// Object partially outside of the printer working space, cannot print. No fade out.
|
// Object partially outside of the printer working space, cannot print. No fade out.
|
||||||
void push_plater_error_notification(const std::string& text, GLCanvas3D& canvas);
|
void push_plater_error_notification(const std::string& text);
|
||||||
// Object fully out of the printer working space and such. No fade out.
|
// Object fully out of the printer working space and such. No fade out.
|
||||||
void push_plater_warning_notification(const std::string& text, GLCanvas3D& canvas);
|
void push_plater_warning_notification(const std::string& text);
|
||||||
// Closes error or warning of the same text
|
// Closes error or warning of the same text
|
||||||
void close_plater_error_notification(const std::string& text);
|
void close_plater_error_notification(const std::string& text);
|
||||||
void close_plater_warning_notification(const std::string& text);
|
void close_plater_warning_notification(const std::string& text);
|
||||||
// Creates special notification slicing complete.
|
// Creates special notification slicing complete.
|
||||||
// If large = true (Plater side bar is closed), then printing time and export button is shown
|
// If large = true (Plater side bar is closed), then printing time and export button is shown
|
||||||
// at the notification and fade-out is disabled. Otherwise the fade out time is set to 10s.
|
// at the notification and fade-out is disabled. Otherwise the fade out time is set to 10s.
|
||||||
void push_slicing_complete_notification(GLCanvas3D& canvas, int timestamp, bool large);
|
void push_slicing_complete_notification(int timestamp, bool large);
|
||||||
// Add a print time estimate to an existing SlicingComplete notification.
|
// Add a print time estimate to an existing SlicingComplete notification.
|
||||||
void set_slicing_complete_print_time(const std::string &info);
|
void set_slicing_complete_print_time(const std::string &info);
|
||||||
// Called when the side bar changes its visibility, as the "slicing complete" notification supplements
|
// Called when the side bar changes its visibility, as the "slicing complete" notification supplements
|
||||||
// the "slicing info" normally shown at the side bar.
|
// the "slicing info" normally shown at the side bar.
|
||||||
void set_slicing_complete_large(bool large);
|
void set_slicing_complete_large(bool large);
|
||||||
// Exporting finished, show this information with path, button to open containing folder and if ejectable - eject button
|
// Exporting finished, show this information with path, button to open containing folder and if ejectable - eject button
|
||||||
void push_exporting_finished_notification(GLCanvas3D& canvas, std::string path, std::string dir_path, bool on_removable);
|
void push_exporting_finished_notification(const std::string& path, const std::string& dir_path, bool on_removable);
|
||||||
// notification with progress bar
|
// notification with progress bar
|
||||||
void push_progress_bar_notification(const std::string& text, GLCanvas3D& canvas, float percentage = 0);
|
void push_progress_bar_notification(const std::string& text, float percentage = 0);
|
||||||
void set_progress_bar_percentage(const std::string& text, float percentage, GLCanvas3D& canvas);
|
void set_progress_bar_percentage(const std::string& text, float percentage);
|
||||||
// Close old notification ExportFinished.
|
// Close old notification ExportFinished.
|
||||||
void new_export_began(bool on_removable);
|
void new_export_began(bool on_removable);
|
||||||
// finds ExportFinished notification and closes it if it was to removable device
|
// finds ExportFinished notification and closes it if it was to removable device
|
||||||
void device_ejected();
|
void device_ejected();
|
||||||
// renders notifications in queue and deletes expired ones
|
// renders notifications in queue and deletes expired ones
|
||||||
void render_notifications(GLCanvas3D& canvas, float overlay_width);
|
void render_notifications(float overlay_width);
|
||||||
// finds and closes all notifications of given type
|
// finds and closes all notifications of given type
|
||||||
void close_notification_of_type(const NotificationType type);
|
void close_notification_of_type(const NotificationType type);
|
||||||
// Which view is active? Plater or G-code preview? Hide warnings in G-code preview.
|
// Which view is active? Plater or G-code preview? Hide warnings in G-code preview.
|
||||||
void set_in_preview(bool preview);
|
void set_in_preview(bool preview);
|
||||||
// Move to left to avoid colision with variable layer height gizmo.
|
// Move to left to avoid colision with variable layer height gizmo.
|
||||||
void set_move_from_overlay(bool move) { m_move_from_overlay = move; }
|
void set_move_from_overlay(bool move) { m_move_from_overlay = move; }
|
||||||
|
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
void update_notifications();
|
||||||
|
bool requires_update() const { return m_requires_update; }
|
||||||
|
bool requires_render() const { return m_requires_render; }
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// duration 0 means not disapearing
|
// duration 0 means not disapearing
|
||||||
struct NotificationData {
|
struct NotificationData {
|
||||||
@ -175,6 +181,17 @@ private:
|
|||||||
class PopNotification
|
class PopNotification
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
enum class EState
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Static,
|
||||||
|
Countdown,
|
||||||
|
FadingOut,
|
||||||
|
ClosePending,
|
||||||
|
Finished
|
||||||
|
};
|
||||||
|
#else
|
||||||
enum class RenderResult
|
enum class RenderResult
|
||||||
{
|
{
|
||||||
Finished,
|
Finished,
|
||||||
@ -183,27 +200,41 @@ private:
|
|||||||
Countdown,
|
Countdown,
|
||||||
Hovered
|
Hovered
|
||||||
};
|
};
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler);
|
PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler);
|
||||||
virtual ~PopNotification() { if (m_id) m_id_provider.release_id(m_id); }
|
virtual ~PopNotification() { if (m_id) m_id_provider.release_id(m_id); }
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
void render(GLCanvas3D& canvas, float initial_y, bool move_from_overlay, float overlay_width);
|
||||||
|
#else
|
||||||
RenderResult render(GLCanvas3D& canvas, const float& initial_y, bool move_from_overlay, float overlay_width);
|
RenderResult render(GLCanvas3D& canvas, const float& initial_y, bool move_from_overlay, float overlay_width);
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
// close will dissapear notification on next render
|
// close will dissapear notification on next render
|
||||||
void close() { m_close_pending = true; }
|
void close() { m_close_pending = true; }
|
||||||
// data from newer notification of same type
|
// data from newer notification of same type
|
||||||
void update(const NotificationData& n);
|
void update(const NotificationData& n);
|
||||||
bool get_finished() const { return m_finished || m_close_pending; }
|
bool is_finished() const { return m_finished || m_close_pending; }
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
bool is_hovered() const { return m_hovered; }
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
// returns top after movement
|
// returns top after movement
|
||||||
float get_top() const { return m_top_y; }
|
float get_top() const { return m_top_y; }
|
||||||
//returns top in actual frame
|
//returns top in actual frame
|
||||||
float get_current_top() const { return m_top_y; }
|
float get_current_top() const { return m_top_y; }
|
||||||
const NotificationType get_type() const { return m_data.type; }
|
const NotificationType get_type() const { return m_data.type; }
|
||||||
const NotificationData get_data() const { return m_data; }
|
const NotificationData get_data() const { return m_data; }
|
||||||
const bool get_is_gray() const { return m_is_gray; }
|
const bool is_gray() const { return m_is_gray; }
|
||||||
// Call equals one second down
|
// Call equals one second down
|
||||||
void substract_remaining_time() { m_remaining_time--; }
|
void substract_remaining_time() { m_remaining_time--; }
|
||||||
void set_gray(bool g) { m_is_gray = g; }
|
void set_gray(bool g) { m_is_gray = g; }
|
||||||
void set_paused(bool p) { m_paused = p; }
|
void set_paused(bool p) { m_paused = p; }
|
||||||
bool compare_text(const std::string& text);
|
bool compare_text(const std::string& text);
|
||||||
void hide(bool h) { m_hidden = h; }
|
void hide(bool h) { m_hidden = h; }
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
void update_state();
|
||||||
|
bool requires_render() const { return m_fading_out || m_close_pending || m_finished; }
|
||||||
|
bool requires_update() const { return m_state != EState::Static; }
|
||||||
|
EState get_state() const { return m_state; }
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Call after every size change
|
// Call after every size change
|
||||||
@ -218,9 +249,11 @@ private:
|
|||||||
virtual void render_close_button(ImGuiWrapper& imgui,
|
virtual void render_close_button(ImGuiWrapper& imgui,
|
||||||
const float win_size_x, const float win_size_y,
|
const float win_size_x, const float win_size_y,
|
||||||
const float win_pos_x , const float win_pos_y);
|
const float win_pos_x , const float win_pos_y);
|
||||||
|
#if !ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
void render_countdown(ImGuiWrapper& imgui,
|
void render_countdown(ImGuiWrapper& imgui,
|
||||||
const float win_size_x, const float win_size_y,
|
const float win_size_x, const float win_size_y,
|
||||||
const float win_pos_x , const float win_pos_y);
|
const float win_pos_x , const float win_pos_y);
|
||||||
|
#endif // !ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
virtual void render_hypertext(ImGuiWrapper& imgui,
|
virtual void render_hypertext(ImGuiWrapper& imgui,
|
||||||
const float text_x, const float text_y,
|
const float text_x, const float text_y,
|
||||||
const std::string text,
|
const std::string text,
|
||||||
@ -237,7 +270,10 @@ private:
|
|||||||
|
|
||||||
// For reusing ImGUI windows.
|
// For reusing ImGUI windows.
|
||||||
NotificationIDProvider &m_id_provider;
|
NotificationIDProvider &m_id_provider;
|
||||||
int m_id { 0 };
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
EState m_state { EState::Unknown };
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
int m_id { 0 };
|
||||||
bool m_initialized { false };
|
bool m_initialized { false };
|
||||||
// Main text
|
// Main text
|
||||||
std::string m_text1;
|
std::string m_text1;
|
||||||
@ -252,15 +288,22 @@ private:
|
|||||||
bool m_paused { false };
|
bool m_paused { false };
|
||||||
int m_countdown_frame { 0 };
|
int m_countdown_frame { 0 };
|
||||||
bool m_fading_out { false };
|
bool m_fading_out { false };
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
wxMilliClock_t m_fading_start { 0LL };
|
||||||
|
#else
|
||||||
// total time left when fading beggins
|
// total time left when fading beggins
|
||||||
float m_fading_time { 0.0f };
|
float m_fading_time{ 0.0f };
|
||||||
float m_current_fade_opacity { 1.f };
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
float m_current_fade_opacity { 1.0f };
|
||||||
// If hidden the notif is alive but not visible to user
|
// If hidden the notif is alive but not visible to user
|
||||||
bool m_hidden { false };
|
bool m_hidden { false };
|
||||||
// m_finished = true - does not render, marked to delete
|
// m_finished = true - does not render, marked to delete
|
||||||
bool m_finished { false };
|
bool m_finished { false };
|
||||||
// Will go to m_finished next render
|
// Will go to m_finished next render
|
||||||
bool m_close_pending { false };
|
bool m_close_pending { false };
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
bool m_hovered { false };
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
// variables to count positions correctly
|
// variables to count positions correctly
|
||||||
// all space without text
|
// all space without text
|
||||||
float m_window_width_offset;
|
float m_window_width_offset;
|
||||||
@ -366,8 +409,8 @@ private:
|
|||||||
|
|
||||||
//pushes notification into the queue of notifications that are rendered
|
//pushes notification into the queue of notifications that are rendered
|
||||||
//can be used to create custom notification
|
//can be used to create custom notification
|
||||||
bool push_notification_data(const NotificationData& notification_data, GLCanvas3D& canvas, int timestamp);
|
bool push_notification_data(const NotificationData& notification_data, int timestamp);
|
||||||
bool push_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, GLCanvas3D& canvas, int timestamp);
|
bool push_notification_data(std::unique_ptr<NotificationManager::PopNotification> notification, int timestamp);
|
||||||
//finds older notification of same type and moves it to the end of queue. returns true if found
|
//finds older notification of same type and moves it to the end of queue. returns true if found
|
||||||
bool activate_existing(const NotificationManager::PopNotification* notification);
|
bool activate_existing(const NotificationManager::PopNotification* notification);
|
||||||
// Put the more important notifications to the bottom of the list.
|
// Put the more important notifications to the bottom of the list.
|
||||||
@ -390,6 +433,10 @@ private:
|
|||||||
bool m_in_preview { false };
|
bool m_in_preview { false };
|
||||||
// True if the layer editing is enabled in Plater, so that the notifications are shifted left of it.
|
// True if the layer editing is enabled in Plater, so that the notifications are shifted left of it.
|
||||||
bool m_move_from_overlay { false };
|
bool m_move_from_overlay { false };
|
||||||
|
#if ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
bool m_requires_update{ false };
|
||||||
|
bool m_requires_render{ false };
|
||||||
|
#endif // ENABLE_NEW_NOTIFICATIONS_FADE_OUT
|
||||||
|
|
||||||
//prepared (basic) notifications
|
//prepared (basic) notifications
|
||||||
const std::vector<NotificationData> basic_notifications = {
|
const std::vector<NotificationData> basic_notifications = {
|
||||||
|
@ -387,7 +387,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) :
|
|||||||
|
|
||||||
option = m_og->get_option("fill_density");
|
option = m_og->get_option("fill_density");
|
||||||
option.opt.label = L("Infill");
|
option.opt.label = L("Infill");
|
||||||
option.opt.width = 7/*6*/;
|
option.opt.width = 8;
|
||||||
option.opt.sidetext = " ";
|
option.opt.sidetext = " ";
|
||||||
line.append_option(option);
|
line.append_option(option);
|
||||||
|
|
||||||
@ -2002,9 +2002,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||||||
sidebar->Bind(EVT_SCHEDULE_BACKGROUND_PROCESS, [this](SimpleEvent&) { this->schedule_background_process(); });
|
sidebar->Bind(EVT_SCHEDULE_BACKGROUND_PROCESS, [this](SimpleEvent&) { this->schedule_background_process(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
wxGLCanvas* view3D_canvas = view3D->get_wxglcanvas();
|
wxGLCanvas* view3D_canvas = view3D->get_wxglcanvas();
|
||||||
|
|
||||||
if (wxGetApp().is_editor()) {
|
if (wxGetApp().is_editor()) {
|
||||||
// 3DScene events:
|
// 3DScene events:
|
||||||
view3D_canvas->Bind(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, [this](SimpleEvent&) { this->schedule_background_process(); });
|
view3D_canvas->Bind(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS, [this](SimpleEvent&) { this->schedule_background_process(); });
|
||||||
view3D_canvas->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this);
|
view3D_canvas->Bind(EVT_GLCANVAS_OBJECT_SELECT, &priv::on_object_select, this);
|
||||||
@ -2046,8 +2046,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||||||
view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this);
|
view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_OBJECTS, &priv::on_action_split_objects, this);
|
||||||
view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_VOLUMES, &priv::on_action_split_volumes, this);
|
view3D_canvas->Bind(EVT_GLTOOLBAR_SPLIT_VOLUMES, &priv::on_action_split_volumes, this);
|
||||||
view3D_canvas->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this);
|
view3D_canvas->Bind(EVT_GLTOOLBAR_LAYERSEDITING, &priv::on_action_layersediting, this);
|
||||||
}
|
}
|
||||||
view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_BED_SHAPE, [q](SimpleEvent&) { q->set_bed_shape(); });
|
view3D_canvas->Bind(EVT_GLCANVAS_UPDATE_BED_SHAPE, [q](SimpleEvent&) { q->set_bed_shape(); });
|
||||||
|
|
||||||
// Preview events:
|
// Preview events:
|
||||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); });
|
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_QUESTION_MARK, [this](SimpleEvent&) { wxGetApp().keyboard_shortcuts(); });
|
||||||
@ -2064,6 +2064,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, [this](wxKeyEvent& evt) { preview->move_layers_slider(evt); });
|
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_MOVE_LAYERS_SLIDER, [this](wxKeyEvent& evt) { preview->move_layers_slider(evt); });
|
||||||
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
#endif // ENABLE_ARROW_KEYS_WITH_SLIDERS
|
||||||
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_EDIT_COLOR_CHANGE, [this](wxKeyEvent& evt) { preview->edit_layers_slider(evt); });
|
preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_EDIT_COLOR_CHANGE, [this](wxKeyEvent& evt) { preview->edit_layers_slider(evt); });
|
||||||
|
if (wxGetApp().is_gcode_viewer())
|
||||||
|
preview->Bind(EVT_GLCANVAS_RELOAD_FROM_DISK, [this](SimpleEvent&) { this->q->reload_gcode_from_disk(); });
|
||||||
|
|
||||||
if (wxGetApp().is_editor()) {
|
if (wxGetApp().is_editor()) {
|
||||||
q->Bind(EVT_SLICING_COMPLETED, &priv::on_slicing_completed, this);
|
q->Bind(EVT_SLICING_COMPLETED, &priv::on_slicing_completed, this);
|
||||||
@ -2113,12 +2115,12 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
|||||||
if (evt.data.second) {
|
if (evt.data.second) {
|
||||||
this->show_action_buttons(this->ready_to_slice);
|
this->show_action_buttons(this->ready_to_slice);
|
||||||
notification_manager->close_notification_of_type(NotificationType::ExportFinished);
|
notification_manager->close_notification_of_type(NotificationType::ExportFinished);
|
||||||
notification_manager->push_notification(format(_L("Successfully unmounted. The device %s(%s) can now be safely removed from the computer."),evt.data.first.name, evt.data.first.path),
|
notification_manager->push_notification(format(_L("Successfully unmounted. The device %s(%s) can now be safely removed from the computer."), evt.data.first.name, evt.data.first.path),
|
||||||
NotificationManager::NotificationLevel::RegularNotification, *q->get_current_canvas3D());
|
NotificationManager::NotificationLevel::RegularNotification);
|
||||||
} else {
|
} else {
|
||||||
notification_manager->push_notification(format(_L("Ejecting of device %s(%s) has failed."), evt.data.first.name, evt.data.first.path),
|
notification_manager->push_notification(format(_L("Ejecting of device %s(%s) has failed."), evt.data.first.name, evt.data.first.path),
|
||||||
NotificationManager::NotificationLevel::ErrorNotification, *q->get_current_canvas3D());
|
NotificationManager::NotificationLevel::ErrorNotification);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this, q](RemovableDrivesChangedEvent &) {
|
this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this, q](RemovableDrivesChangedEvent &) {
|
||||||
this->show_action_buttons(this->ready_to_slice);
|
this->show_action_buttons(this->ready_to_slice);
|
||||||
@ -2363,7 +2365,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
|
|||||||
wxGetApp().preset_bundle->load_config_model(filename.string(), std::move(config));
|
wxGetApp().preset_bundle->load_config_model(filename.string(), std::move(config));
|
||||||
if (printer_technology == ptFFF)
|
if (printer_technology == ptFFF)
|
||||||
CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, &wxGetApp().preset_bundle->project_config);
|
CustomGCode::update_custom_gcode_per_print_z_from_config(model.custom_gcode_per_print_z, &wxGetApp().preset_bundle->project_config);
|
||||||
wxGetApp().load_current_presets();
|
// For exporting from the amf/3mf we shouldn't check printer_presets for the containing information about "Print Host upload"
|
||||||
|
wxGetApp().load_current_presets(false);
|
||||||
is_project_file = true;
|
is_project_file = true;
|
||||||
}
|
}
|
||||||
wxGetApp().app_config->update_config_dir(path.parent_path().string());
|
wxGetApp().app_config->update_config_dir(path.parent_path().string());
|
||||||
@ -2945,7 +2948,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
|||||||
} else {
|
} else {
|
||||||
// The print is not valid.
|
// The print is not valid.
|
||||||
// Show error as notification.
|
// Show error as notification.
|
||||||
notification_manager->push_slicing_error_notification(err, *q->get_current_canvas3D());
|
notification_manager->push_slicing_error_notification(err);
|
||||||
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
|
return_state |= UPDATE_BACKGROUND_PROCESS_INVALID;
|
||||||
}
|
}
|
||||||
} else if (! this->delayed_error_message.empty()) {
|
} else if (! this->delayed_error_message.empty()) {
|
||||||
@ -3506,7 +3509,7 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
|||||||
|
|
||||||
this->statusbar()->set_progress(evt.status.percent);
|
this->statusbar()->set_progress(evt.status.percent);
|
||||||
this->statusbar()->set_status_text(_(evt.status.text) + wxString::FromUTF8("…"));
|
this->statusbar()->set_status_text(_(evt.status.text) + wxString::FromUTF8("…"));
|
||||||
//notification_manager->set_progress_bar_percentage("Slicing progress", (float)evt.status.percent / 100.0f, *q->get_current_canvas3D());
|
//notification_manager->set_progress_bar_percentage("Slicing progress", (float)evt.status.percent / 100.0f);
|
||||||
}
|
}
|
||||||
if (evt.status.flags & (PrintBase::SlicingStatus::RELOAD_SCENE | PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS)) {
|
if (evt.status.flags & (PrintBase::SlicingStatus::RELOAD_SCENE | PrintBase::SlicingStatus::RELOAD_SLA_SUPPORT_POINTS)) {
|
||||||
switch (this->printer_technology) {
|
switch (this->printer_technology) {
|
||||||
@ -3548,8 +3551,8 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
|||||||
// Now process state.warnings.
|
// Now process state.warnings.
|
||||||
for (auto const& warning : state.warnings) {
|
for (auto const& warning : state.warnings) {
|
||||||
if (warning.current) {
|
if (warning.current) {
|
||||||
notification_manager->push_slicing_warning_notification(warning.message, false, *q->get_current_canvas3D(), object_id, warning_step);
|
notification_manager->push_slicing_warning_notification(warning.message, false, object_id, warning_step);
|
||||||
add_warning(warning, object_id.id);
|
add_warning(warning, object_id.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3557,7 +3560,7 @@ void Plater::priv::on_slicing_update(SlicingStatusEvent &evt)
|
|||||||
|
|
||||||
void Plater::priv::on_slicing_completed(wxCommandEvent & evt)
|
void Plater::priv::on_slicing_completed(wxCommandEvent & evt)
|
||||||
{
|
{
|
||||||
notification_manager->push_slicing_complete_notification(*q->get_current_canvas3D(), evt.GetInt(), is_sidebar_collapsed());
|
notification_manager->push_slicing_complete_notification(evt.GetInt(), is_sidebar_collapsed());
|
||||||
switch (this->printer_technology) {
|
switch (this->printer_technology) {
|
||||||
case ptFFF:
|
case ptFFF:
|
||||||
this->update_fff_scene();
|
this->update_fff_scene();
|
||||||
@ -3643,17 +3646,17 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
|||||||
// This bool stops showing export finished notification even when process_completed_with_error is false
|
// This bool stops showing export finished notification even when process_completed_with_error is false
|
||||||
bool has_error = false;
|
bool has_error = false;
|
||||||
if (evt.error()) {
|
if (evt.error()) {
|
||||||
std::string message = evt.format_error_message();
|
std::pair<std::string, bool> message = evt.format_error_message();
|
||||||
if (evt.critical_error()) {
|
if (evt.critical_error()) {
|
||||||
if (q->m_tracking_popup_menu)
|
if (q->m_tracking_popup_menu)
|
||||||
// We don't want to pop-up a message box when tracking a pop-up menu.
|
// We don't want to pop-up a message box when tracking a pop-up menu.
|
||||||
// We postpone the error message instead.
|
// We postpone the error message instead.
|
||||||
q->m_tracking_popup_menu_error_message = message;
|
q->m_tracking_popup_menu_error_message = message.first;
|
||||||
else
|
else
|
||||||
show_error(q, message);
|
show_error(q, message.first, message.second);
|
||||||
} else
|
} else
|
||||||
notification_manager->push_slicing_error_notification(message, *q->get_current_canvas3D());
|
notification_manager->push_slicing_error_notification(message.first);
|
||||||
this->statusbar()->set_status_text(from_u8(message));
|
this->statusbar()->set_status_text(from_u8(message.first));
|
||||||
if (evt.invalidate_plater())
|
if (evt.invalidate_plater())
|
||||||
{
|
{
|
||||||
const wxString invalid_str = _L("Invalid data");
|
const wxString invalid_str = _L("Invalid data");
|
||||||
@ -3698,10 +3701,10 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
|||||||
// If writing to removable drive was scheduled, show notification with eject button
|
// If writing to removable drive was scheduled, show notification with eject button
|
||||||
if (exporting_status == ExportingStatus::EXPORTING_TO_REMOVABLE && !has_error) {
|
if (exporting_status == ExportingStatus::EXPORTING_TO_REMOVABLE && !has_error) {
|
||||||
show_action_buttons(false);
|
show_action_buttons(false);
|
||||||
notification_manager->push_exporting_finished_notification(*q->get_current_canvas3D(), last_output_path, last_output_dir_path, true);
|
notification_manager->push_exporting_finished_notification(last_output_path, last_output_dir_path, true);
|
||||||
wxGetApp().removable_drive_manager()->set_exporting_finished(true);
|
wxGetApp().removable_drive_manager()->set_exporting_finished(true);
|
||||||
}else if (exporting_status == ExportingStatus::EXPORTING_TO_LOCAL && !has_error)
|
}else if (exporting_status == ExportingStatus::EXPORTING_TO_LOCAL && !has_error)
|
||||||
notification_manager->push_exporting_finished_notification(*q->get_current_canvas3D(), last_output_path, last_output_dir_path, false);
|
notification_manager->push_exporting_finished_notification(last_output_path, last_output_dir_path, false);
|
||||||
}
|
}
|
||||||
exporting_status = ExportingStatus::NOT_EXPORTING;
|
exporting_status = ExportingStatus::NOT_EXPORTING;
|
||||||
}
|
}
|
||||||
@ -4806,6 +4809,13 @@ void Plater::load_gcode(const wxString& filename)
|
|||||||
set_project_filename(filename);
|
set_project_filename(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Plater::reload_gcode_from_disk()
|
||||||
|
{
|
||||||
|
wxString filename(m_last_loaded_gcode);
|
||||||
|
m_last_loaded_gcode.clear();
|
||||||
|
load_gcode(filename);
|
||||||
|
}
|
||||||
|
|
||||||
void Plater::refresh_print()
|
void Plater::refresh_print()
|
||||||
{
|
{
|
||||||
p->preview->refresh_print();
|
p->preview->refresh_print();
|
||||||
@ -4923,7 +4933,7 @@ bool Plater::load_files(const wxArrayString& filenames)
|
|||||||
else if (std::regex_match(path.string(), pattern_gcode_drop))
|
else if (std::regex_match(path.string(), pattern_gcode_drop))
|
||||||
start_new_gcodeviewer(&filename);
|
start_new_gcodeviewer(&filename);
|
||||||
else
|
else
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
if (paths.empty())
|
if (paths.empty())
|
||||||
// Likely all paths processed were gcodes, for which a G-code viewer instance has hopefully been started.
|
// Likely all paths processed were gcodes, for which a G-code viewer instance has hopefully been started.
|
||||||
@ -5216,9 +5226,12 @@ void Plater::export_gcode(bool prefer_removable)
|
|||||||
if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID)
|
if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID)
|
||||||
return;
|
return;
|
||||||
default_output_file = this->p->background_process.output_filepath_for_project(into_path(get_project_filename(".3mf")));
|
default_output_file = this->p->background_process.output_filepath_for_project(into_path(get_project_filename(".3mf")));
|
||||||
}
|
} catch (const Slic3r::PlaceholderParserError &ex) {
|
||||||
catch (const std::exception &ex) {
|
// Show the error with monospaced font.
|
||||||
show_error(this, ex.what());
|
show_error(this, ex.what(), true);
|
||||||
|
return;
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
show_error(this, ex.what(), false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
|
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
|
||||||
@ -5576,9 +5589,12 @@ void Plater::send_gcode()
|
|||||||
if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID)
|
if (state & priv::UPDATE_BACKGROUND_PROCESS_INVALID)
|
||||||
return;
|
return;
|
||||||
default_output_file = this->p->background_process.output_filepath_for_project(into_path(get_project_filename(".3mf")));
|
default_output_file = this->p->background_process.output_filepath_for_project(into_path(get_project_filename(".3mf")));
|
||||||
}
|
} catch (const Slic3r::PlaceholderParserError& ex) {
|
||||||
catch (const std::exception &ex) {
|
// Show the error with monospaced font.
|
||||||
show_error(this, ex.what());
|
show_error(this, ex.what(), true);
|
||||||
|
return;
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
show_error(this, ex.what(), false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
|
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
|
||||||
|
@ -144,6 +144,7 @@ public:
|
|||||||
void extract_config_from_project();
|
void extract_config_from_project();
|
||||||
void load_gcode();
|
void load_gcode();
|
||||||
void load_gcode(const wxString& filename);
|
void load_gcode(const wxString& filename);
|
||||||
|
void reload_gcode_from_disk();
|
||||||
void refresh_print();
|
void refresh_print();
|
||||||
|
|
||||||
std::vector<size_t> load_files(const std::vector<boost::filesystem::path>& input_files, bool load_model = true, bool load_config = true, bool imperial_units = false);
|
std::vector<size_t> load_files(const std::vector<boost::filesystem::path>& input_files, bool load_model = true, bool load_config = true, bool imperial_units = false);
|
||||||
@ -154,6 +155,8 @@ public:
|
|||||||
bool load_files(const wxArrayString& filenames);
|
bool load_files(const wxArrayString& filenames);
|
||||||
#endif // ENABLE_DRAG_AND_DROP_FIX
|
#endif // ENABLE_DRAG_AND_DROP_FIX
|
||||||
|
|
||||||
|
const wxString& get_last_loaded_gcode() const { return m_last_loaded_gcode; }
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
void stop_jobs();
|
void stop_jobs();
|
||||||
void select_view(const std::string& direction);
|
void select_view(const std::string& direction);
|
||||||
|
@ -16,13 +16,11 @@
|
|||||||
#include "Plater.hpp"
|
#include "Plater.hpp"
|
||||||
#include "../Utils/MacDarkMode.hpp"
|
#include "../Utils/MacDarkMode.hpp"
|
||||||
|
|
||||||
#ifdef __Linux__
|
#ifdef __linux__
|
||||||
#define wxLinux true
|
#define wxLinux true
|
||||||
#else
|
#else
|
||||||
#define wxLinux false
|
#define wxLinux false
|
||||||
#endif
|
// msw_menuitem_bitmaps is used for MSW and OSX
|
||||||
|
|
||||||
#ifndef __WXGTK__// msw_menuitem_bitmaps is used for MSW and OSX
|
|
||||||
static std::map<int, std::string> msw_menuitem_bitmaps;
|
static std::map<int, std::string> msw_menuitem_bitmaps;
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
void msw_rescale_menu(wxMenu* menu)
|
void msw_rescale_menu(wxMenu* menu)
|
||||||
|
@ -163,13 +163,7 @@ Http::priv::priv(const std::string &url)
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_timeout_connect(DEFAULT_TIMEOUT_CONNECT);
|
set_timeout_connect(DEFAULT_TIMEOUT_CONNECT);
|
||||||
char *url_encoded = curl_easy_escape(curl, url.c_str(), url.size());
|
::curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // curl makes a copy internally
|
||||||
if (url_encoded) {
|
|
||||||
// libcurl makes an internal copy.
|
|
||||||
::curl_easy_setopt(curl, CURLOPT_URL, url_encoded);
|
|
||||||
::curl_free(url_encoded);
|
|
||||||
} else
|
|
||||||
throw Slic3r::RuntimeError(std::string("Curl failed to encode URL: ") + url);
|
|
||||||
::curl_easy_setopt(curl, CURLOPT_USERAGENT, SLIC3R_APP_NAME "/" SLIC3R_VERSION);
|
::curl_easy_setopt(curl, CURLOPT_USERAGENT, SLIC3R_APP_NAME "/" SLIC3R_VERSION);
|
||||||
::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer.front());
|
::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer.front());
|
||||||
}
|
}
|
||||||
|
@ -827,7 +827,7 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver& old_slic3
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p->set_waiting_updates(updates);
|
p->set_waiting_updates(updates);
|
||||||
GUI::wxGetApp().plater()->get_notification_manager()->push_notification(GUI::NotificationType::PresetUpdateAvailable, *(GUI::wxGetApp().plater()->get_current_canvas3D()));
|
GUI::wxGetApp().plater()->get_notification_manager()->push_notification(GUI::NotificationType::PresetUpdateAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MsgUpdateConfig will show after the notificaation is clicked
|
// MsgUpdateConfig will show after the notificaation is clicked
|
||||||
|
Loading…
x
Reference in New Issue
Block a user