Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
This commit is contained in:
commit
3fc12fdaaa
19 changed files with 374 additions and 262 deletions
|
@ -518,9 +518,12 @@ int CLI::run(int argc, char **argv)
|
||||||
outfile_final = sla_print.print_statistics().finalize_output_path(outfile);
|
outfile_final = sla_print.print_statistics().finalize_output_path(outfile);
|
||||||
sla_archive.export_print(outfile_final, sla_print);
|
sla_archive.export_print(outfile_final, sla_print);
|
||||||
}
|
}
|
||||||
if (outfile != outfile_final && Slic3r::rename_file(outfile, outfile_final)) {
|
if (outfile != outfile_final) {
|
||||||
boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl;
|
if (Slic3r::rename_file(outfile, outfile_final)) {
|
||||||
return 1;
|
boost::nowide::cerr << "Renaming file " << outfile << " to " << outfile_final << " failed" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
outfile = outfile_final;
|
||||||
}
|
}
|
||||||
boost::nowide::cout << "Slicing result exported to " << outfile << std::endl;
|
boost::nowide::cout << "Slicing result exported to " << outfile << std::endl;
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
|
@ -588,9 +591,9 @@ int CLI::run(int argc, char **argv)
|
||||||
// gui->autosave = m_config.opt_string("autosave");
|
// gui->autosave = m_config.opt_string("autosave");
|
||||||
GUI::GUI_App::SetInstance(gui);
|
GUI::GUI_App::SetInstance(gui);
|
||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
gui->m_after_init_loads.set_params(load_configs, m_extra_config, m_input_files, start_as_gcodeviewer);
|
gui->after_init_loads.set_params(load_configs, m_extra_config, m_input_files, start_as_gcodeviewer);
|
||||||
#else
|
#else
|
||||||
gui->m_after_init_loads.set_params(load_configs, m_extra_config, m_input_files);
|
gui->after_init_loads.set_params(load_configs, m_extra_config, m_input_files);
|
||||||
#endif // ENABLE_GCODE_VIEWER
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
/*
|
/*
|
||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
|
|
|
@ -577,6 +577,16 @@ void Print::config_diffs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ObjectID> Print::print_object_ids() const
|
||||||
|
{
|
||||||
|
std::vector<ObjectID> out;
|
||||||
|
// Reserve one more for the caller to append the ID of the Print itself.
|
||||||
|
out.reserve(m_objects.size() + 1);
|
||||||
|
for (const PrintObject *print_object : m_objects)
|
||||||
|
out.emplace_back(print_object->id());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_config)
|
Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_config)
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
|
|
@ -370,6 +370,8 @@ public:
|
||||||
// a cancellation callback is executed to stop the background processing before the operation.
|
// a cancellation callback is executed to stop the background processing before the operation.
|
||||||
void clear() override;
|
void clear() override;
|
||||||
bool empty() const override { return m_objects.empty(); }
|
bool empty() const override { return m_objects.empty(); }
|
||||||
|
// List of existing PrintObject IDs, to remove notifications for non-existent IDs.
|
||||||
|
std::vector<ObjectID> print_object_ids() const override;
|
||||||
|
|
||||||
ApplyStatus apply(const Model &model, DynamicPrintConfig config) override;
|
ApplyStatus apply(const Model &model, DynamicPrintConfig config) override;
|
||||||
|
|
||||||
|
|
|
@ -348,6 +348,8 @@ public:
|
||||||
// The Print is empty either after clear() or after apply() over an empty model,
|
// The Print is empty either after clear() or after apply() over an empty model,
|
||||||
// or after apply() over a model, where no object is printable (all outside the print volume).
|
// or after apply() over a model, where no object is printable (all outside the print volume).
|
||||||
virtual bool empty() const = 0;
|
virtual bool empty() const = 0;
|
||||||
|
// List of existing PrintObject IDs, to remove notifications for non-existent IDs.
|
||||||
|
virtual std::vector<ObjectID> print_object_ids() const = 0;
|
||||||
|
|
||||||
// Validate the print, return empty string if valid, return error if process() cannot (or should not) be started.
|
// Validate the print, return empty string if valid, return error if process() cannot (or should not) be started.
|
||||||
virtual std::string validate() const { return std::string(); }
|
virtual std::string validate() const { return std::string(); }
|
||||||
|
@ -406,7 +408,7 @@ public:
|
||||||
// set to an ObjectID of a Print or a PrintObject based on flags
|
// set to an ObjectID of a Print or a PrintObject based on flags
|
||||||
// (whether UPDATE_PRINT_STEP_WARNINGS or UPDATE_PRINT_OBJECT_STEP_WARNINGS is set).
|
// (whether UPDATE_PRINT_STEP_WARNINGS or UPDATE_PRINT_OBJECT_STEP_WARNINGS is set).
|
||||||
ObjectID warning_object_id;
|
ObjectID warning_object_id;
|
||||||
// For which Print or PrintObject step a new warning is beeing issued?
|
// For which Print or PrintObject step a new warning is being issued?
|
||||||
int warning_step { -1 };
|
int warning_step { -1 };
|
||||||
};
|
};
|
||||||
typedef std::function<void(const SlicingStatus&)> status_callback_type;
|
typedef std::function<void(const SlicingStatus&)> status_callback_type;
|
||||||
|
|
|
@ -357,13 +357,26 @@ std::vector<Vec2f> sample_expolygon(const ExPolygon &expoly, float samples_per_m
|
||||||
double r = random_triangle(rng);
|
double r = random_triangle(rng);
|
||||||
size_t idx_triangle = std::min<size_t>(std::upper_bound(areas.begin(), areas.end(), (float)r) - areas.begin(), areas.size() - 1) * 3;
|
size_t idx_triangle = std::min<size_t>(std::upper_bound(areas.begin(), areas.end(), (float)r) - areas.begin(), areas.size() - 1) * 3;
|
||||||
// Select a random point on the triangle.
|
// Select a random point on the triangle.
|
||||||
double u = float(std::sqrt(random_float(rng)));
|
|
||||||
double v = float(random_float(rng));
|
|
||||||
const Vec2f &a = triangles[idx_triangle ++];
|
const Vec2f &a = triangles[idx_triangle ++];
|
||||||
const Vec2f &b = triangles[idx_triangle++];
|
const Vec2f &b = triangles[idx_triangle++];
|
||||||
const Vec2f &c = triangles[idx_triangle];
|
const Vec2f &c = triangles[idx_triangle];
|
||||||
const Vec2f x = a * (1.f - u) + b * (u * (1.f - v)) + c * (v * u);
|
#if 0
|
||||||
out.emplace_back(x);
|
// https://www.cs.princeton.edu/~funk/tog02.pdf
|
||||||
|
// page 814, formula 1.
|
||||||
|
double u = float(std::sqrt(random_float(rng)));
|
||||||
|
double v = float(random_float(rng));
|
||||||
|
out.emplace_back(a * (1.f - u) + b * (u * (1.f - v)) + c * (v * u));
|
||||||
|
#else
|
||||||
|
// Greg Turk, Graphics Gems
|
||||||
|
// https://devsplorer.wordpress.com/2019/08/07/find-a-random-point-on-a-plane-using-barycentric-coordinates-in-unity/
|
||||||
|
double u = float(random_float(rng));
|
||||||
|
double v = float(random_float(rng));
|
||||||
|
if (u + v >= 1.f) {
|
||||||
|
u = 1.f - u;
|
||||||
|
v = 1.f - v;
|
||||||
|
}
|
||||||
|
out.emplace_back(a + u * (b - a) + v * (c - a));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
|
|
@ -175,6 +175,16 @@ static std::vector<SLAPrintObject::Instance> sla_instances(const ModelObject &mo
|
||||||
return instances;
|
return instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ObjectID> SLAPrint::print_object_ids() const
|
||||||
|
{
|
||||||
|
std::vector<ObjectID> out;
|
||||||
|
// Reserve one more for the caller to append the ID of the Print itself.
|
||||||
|
out.reserve(m_objects.size() + 1);
|
||||||
|
for (const SLAPrintObject *print_object : m_objects)
|
||||||
|
out.emplace_back(print_object->id());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig config)
|
SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig config)
|
||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
|
|
@ -420,6 +420,8 @@ public:
|
||||||
|
|
||||||
void clear() override;
|
void clear() override;
|
||||||
bool empty() const override { return m_objects.empty(); }
|
bool empty() const override { return m_objects.empty(); }
|
||||||
|
// List of existing PrintObject IDs, to remove notifications for non-existent IDs.
|
||||||
|
std::vector<ObjectID> print_object_ids() const;
|
||||||
ApplyStatus apply(const Model &model, DynamicPrintConfig config) override;
|
ApplyStatus apply(const Model &model, DynamicPrintConfig config) override;
|
||||||
void set_task(const TaskParams ¶ms) override;
|
void set_task(const TaskParams ¶ms) override;
|
||||||
void process() override;
|
void process() override;
|
||||||
|
|
|
@ -640,16 +640,17 @@ void GLCanvas3D::WarningTexture::activate(WarningTexture::Warning warning, bool
|
||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(state) {
|
auto ¬ification_manager = *wxGetApp().plater()->get_notification_manager();
|
||||||
|
if (state) {
|
||||||
if(error)
|
if(error)
|
||||||
wxGetApp().plater()->get_notification_manager()->push_plater_error_notification(text,*(wxGetApp().plater()->get_current_canvas3D()));
|
notification_manager.push_plater_error_notification(text,*(wxGetApp().plater()->get_current_canvas3D()));
|
||||||
else
|
else
|
||||||
wxGetApp().plater()->get_notification_manager()->push_plater_warning_notification(text, *(wxGetApp().plater()->get_current_canvas3D()));
|
notification_manager.push_plater_warning_notification(text, *(wxGetApp().plater()->get_current_canvas3D()));
|
||||||
} else {
|
} else {
|
||||||
if (error)
|
if (error)
|
||||||
wxGetApp().plater()->get_notification_manager()->close_plater_error_notification(text);
|
notification_manager.close_plater_error_notification(text);
|
||||||
else
|
else
|
||||||
wxGetApp().plater()->get_notification_manager()->close_plater_warning_notification(text);
|
notification_manager.close_plater_warning_notification(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2087,7 +2088,7 @@ void GLCanvas3D::render()
|
||||||
|
|
||||||
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(*this, get_overelay_window_width(), get_slope_window_width());
|
wxGetApp().plater()->get_notification_manager()->render_notifications(*this, get_overlay_window_width());
|
||||||
|
|
||||||
wxGetApp().imgui()->render();
|
wxGetApp().imgui()->render();
|
||||||
|
|
||||||
|
|
|
@ -243,7 +243,7 @@ private:
|
||||||
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
|
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);
|
||||||
static Rect get_bar_rect_screen(const GLCanvas3D& canvas);
|
static Rect get_bar_rect_screen(const GLCanvas3D& canvas);
|
||||||
static Rect get_bar_rect_viewport(const GLCanvas3D& canvas);
|
static Rect get_bar_rect_viewport(const GLCanvas3D& canvas);
|
||||||
static float get_overelay_window_width() { return LayersEditing::s_overelay_window_width; }
|
static float get_overlay_window_width() { return LayersEditing::s_overelay_window_width; }
|
||||||
|
|
||||||
float object_max_z() const { return m_object_max_z; }
|
float object_max_z() const { return m_object_max_z; }
|
||||||
|
|
||||||
|
@ -885,8 +885,7 @@ private:
|
||||||
bool _activate_search_toolbar_item();
|
bool _activate_search_toolbar_item();
|
||||||
bool _deactivate_collapse_toolbar_items();
|
bool _deactivate_collapse_toolbar_items();
|
||||||
|
|
||||||
float get_overelay_window_width() { return LayersEditing::get_overelay_window_width(); }
|
float get_overlay_window_width() { return LayersEditing::get_overlay_window_width(); }
|
||||||
float get_slope_window_width() { return Slope::get_window_width(); }
|
|
||||||
|
|
||||||
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
|
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
|
||||||
|
|
||||||
|
|
|
@ -533,7 +533,7 @@ static void generic_exception_handle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI_App::AFTER_INIT_LOADS::on_loads(GUI_App* gui)
|
void GUI_App::AfterInitLoads::on_loads(GUI_App* gui)
|
||||||
{
|
{
|
||||||
if (!gui->initialized())
|
if (!gui->initialized())
|
||||||
return;
|
return;
|
||||||
|
@ -773,7 +773,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::NewAppAviable, *(this->plater_->get_current_canvas3D()));
|
this->plater_->get_notification_manager()->push_notification(NotificationType::NewAppAvailable, *(this->plater_->get_current_canvas3D()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -847,7 +847,10 @@ bool GUI_App::on_init_inner()
|
||||||
static bool update_gui_after_init = true;
|
static bool update_gui_after_init = true;
|
||||||
if (update_gui_after_init) {
|
if (update_gui_after_init) {
|
||||||
update_gui_after_init = false;
|
update_gui_after_init = false;
|
||||||
m_after_init_loads.on_loads(this);
|
#ifdef WIN32
|
||||||
|
this->mainframe->register_win32_callbacks();
|
||||||
|
#endif
|
||||||
|
this->after_init_loads.on_loads(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preset updating & Configwizard are done after the above initializations,
|
// Preset updating & Configwizard are done after the above initializations,
|
||||||
|
|
|
@ -143,7 +143,7 @@ private:
|
||||||
size_t m_instance_hash_int;
|
size_t m_instance_hash_int;
|
||||||
|
|
||||||
// parameters needed for the after OnInit() loads
|
// parameters needed for the after OnInit() loads
|
||||||
struct AFTER_INIT_LOADS
|
struct AfterInitLoads
|
||||||
{
|
{
|
||||||
std::vector<std::string> m_load_configs;
|
std::vector<std::string> m_load_configs;
|
||||||
DynamicPrintConfig m_extra_config;
|
DynamicPrintConfig m_extra_config;
|
||||||
|
@ -272,7 +272,7 @@ public:
|
||||||
PresetUpdater* preset_updater{ nullptr };
|
PresetUpdater* preset_updater{ nullptr };
|
||||||
MainFrame* mainframe{ nullptr };
|
MainFrame* mainframe{ nullptr };
|
||||||
Plater* plater_{ nullptr };
|
Plater* plater_{ nullptr };
|
||||||
AFTER_INIT_LOADS m_after_init_loads;
|
AfterInitLoads after_init_loads;
|
||||||
|
|
||||||
PresetUpdater* get_preset_updater() { return preset_updater; }
|
PresetUpdater* get_preset_updater() { return preset_updater; }
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,9 @@ namespace instance_check_internal
|
||||||
};
|
};
|
||||||
static CommandLineAnalysis process_command_line(int argc, char** argv)
|
static CommandLineAnalysis process_command_line(int argc, char** argv)
|
||||||
{
|
{
|
||||||
CommandLineAnalysis ret { false };
|
CommandLineAnalysis ret;
|
||||||
if (argc < 2)
|
//if (argc < 2)
|
||||||
return ret;
|
// return ret;
|
||||||
std::vector<std::string> arguments { argv[0] };
|
std::vector<std::string> arguments { argv[0] };
|
||||||
for (size_t i = 1; i < argc; ++i) {
|
for (size_t i = 1; i < argc; ++i) {
|
||||||
const std::string token = argv[i];
|
const std::string token = argv[i];
|
||||||
|
@ -254,7 +254,8 @@ bool instance_check(int argc, char** argv, bool app_config_single_instance)
|
||||||
GUI::wxGetApp().init_single_instance_checker(lock_name + ".lock", data_dir() + "/cache/");
|
GUI::wxGetApp().init_single_instance_checker(lock_name + ".lock", data_dir() + "/cache/");
|
||||||
if (cla.should_send.value() && GUI::wxGetApp().single_instance_checker()->IsAnotherRunning()) {
|
if (cla.should_send.value() && GUI::wxGetApp().single_instance_checker()->IsAnotherRunning()) {
|
||||||
#else // mac & linx
|
#else // mac & linx
|
||||||
if (*cla.should_send && instance_check_internal::get_lock(lock_name + ".lock", data_dir() + "/cache/")) {
|
// get_lock() creates the lockfile therefore *cla.should_send is checked after
|
||||||
|
if (instance_check_internal::get_lock(lock_name + ".lock", data_dir() + "/cache/") && *cla.should_send) {
|
||||||
#endif
|
#endif
|
||||||
instance_check_internal::send_message(cla.cl_string, lock_name);
|
instance_check_internal::send_message(cla.cl_string, lock_name);
|
||||||
BOOST_LOG_TRIVIAL(info) << "instance check: Another instance found. This instance will terminate.";
|
BOOST_LOG_TRIVIAL(info) << "instance check: Another instance found. This instance will terminate.";
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
-(void)message_update:(NSNotification *)msg
|
-(void)message_update:(NSNotification *)msg
|
||||||
{
|
{
|
||||||
|
[self bring_forward];
|
||||||
//pass message
|
//pass message
|
||||||
Slic3r::GUI::wxGetApp().other_instance_message_handler()->handle_message(std::string([msg.userInfo[@"data"] UTF8String]));
|
Slic3r::GUI::wxGetApp().other_instance_message_handler()->handle_message(std::string([msg.userInfo[@"data"] UTF8String]));
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,65 +217,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
||||||
update_title();
|
update_title();
|
||||||
|
|
||||||
// declare events
|
// declare events
|
||||||
Bind(wxEVT_CREATE, [this](wxWindowCreateEvent& event) {
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
//static GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED };
|
|
||||||
//static GUID GUID_DEVINTERFACE_DISK = { 0x53f56307, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b };
|
|
||||||
//static GUID GUID_DEVINTERFACE_VOLUME = { 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f };
|
|
||||||
static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 };
|
|
||||||
|
|
||||||
// Register USB HID (Human Interface Devices) notifications to trigger the 3DConnexion enumeration.
|
|
||||||
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = { 0 };
|
|
||||||
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
|
||||||
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
|
||||||
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
|
||||||
m_hDeviceNotify = ::RegisterDeviceNotification(this->GetHWND(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
|
|
||||||
|
|
||||||
// or register for file handle change?
|
|
||||||
// DEV_BROADCAST_HANDLE NotificationFilter = { 0 };
|
|
||||||
// NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
|
|
||||||
// NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
|
|
||||||
|
|
||||||
// Using Win32 Shell API to register for media insert / removal events.
|
|
||||||
LPITEMIDLIST ppidl;
|
|
||||||
if (SHGetSpecialFolderLocation(this->GetHWND(), CSIDL_DESKTOP, &ppidl) == NOERROR) {
|
|
||||||
SHChangeNotifyEntry shCNE;
|
|
||||||
shCNE.pidl = ppidl;
|
|
||||||
shCNE.fRecursive = TRUE;
|
|
||||||
// Returns a positive integer registration identifier (ID).
|
|
||||||
// Returns zero if out of memory or in response to invalid parameters.
|
|
||||||
m_ulSHChangeNotifyRegister = SHChangeNotifyRegister(this->GetHWND(), // Hwnd to receive notification
|
|
||||||
SHCNE_DISKEVENTS, // Event types of interest (sources)
|
|
||||||
SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED,
|
|
||||||
//SHCNE_UPDATEITEM, // Events of interest - use SHCNE_ALLEVENTS for all events
|
|
||||||
WM_USER_MEDIACHANGED, // Notification message to be sent upon the event
|
|
||||||
1, // Number of entries in the pfsne array
|
|
||||||
&shCNE); // Array of SHChangeNotifyEntry structures that
|
|
||||||
// contain the notifications. This array should
|
|
||||||
// always be set to one when calling SHChnageNotifyRegister
|
|
||||||
// or SHChangeNotifyDeregister will not work properly.
|
|
||||||
assert(m_ulSHChangeNotifyRegister != 0); // Shell notification failed
|
|
||||||
} else {
|
|
||||||
// Failed to get desktop location
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
static constexpr int device_count = 1;
|
|
||||||
RAWINPUTDEVICE devices[device_count] = { 0 };
|
|
||||||
// multi-axis mouse (SpaceNavigator, etc.)
|
|
||||||
devices[0].usUsagePage = 0x01;
|
|
||||||
devices[0].usUsage = 0x08;
|
|
||||||
if (! RegisterRawInputDevices(devices, device_count, sizeof(RAWINPUTDEVICE)))
|
|
||||||
BOOST_LOG_TRIVIAL(error) << "RegisterRawInputDevices failed";
|
|
||||||
}
|
|
||||||
#endif // _WIN32
|
|
||||||
|
|
||||||
// propagate event
|
|
||||||
event.Skip();
|
|
||||||
});
|
|
||||||
|
|
||||||
Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) {
|
Bind(wxEVT_CLOSE_WINDOW, [this](wxCloseEvent& event) {
|
||||||
if (event.CanVeto() && !wxGetApp().check_unsaved_changes()) {
|
if (event.CanVeto() && !wxGetApp().check_unsaved_changes()) {
|
||||||
event.Veto();
|
event.Veto();
|
||||||
|
@ -286,6 +227,8 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_S
|
||||||
event.Skip();
|
event.Skip();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//FIXME it seems this method is not called on application start-up, at least not on Windows. Why?
|
||||||
|
// The same applies to wxEVT_CREATE, it is not being called on startup on Windows.
|
||||||
Bind(wxEVT_ACTIVATE, [this](wxActivateEvent& event) {
|
Bind(wxEVT_ACTIVATE, [this](wxActivateEvent& event) {
|
||||||
if (m_plater != nullptr && event.GetActive())
|
if (m_plater != nullptr && event.GetActive())
|
||||||
m_plater->on_activate();
|
m_plater->on_activate();
|
||||||
|
@ -656,6 +599,62 @@ void MainFrame::init_tabpanel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
void MainFrame::register_win32_callbacks()
|
||||||
|
{
|
||||||
|
//static GUID GUID_DEVINTERFACE_USB_DEVICE = { 0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED };
|
||||||
|
//static GUID GUID_DEVINTERFACE_DISK = { 0x53f56307, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b };
|
||||||
|
//static GUID GUID_DEVINTERFACE_VOLUME = { 0x71a27cdd, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f };
|
||||||
|
static GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 };
|
||||||
|
|
||||||
|
// Register USB HID (Human Interface Devices) notifications to trigger the 3DConnexion enumeration.
|
||||||
|
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter = { 0 };
|
||||||
|
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
||||||
|
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||||
|
NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
||||||
|
m_hDeviceNotify = ::RegisterDeviceNotification(this->GetHWND(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||||
|
|
||||||
|
// or register for file handle change?
|
||||||
|
// DEV_BROADCAST_HANDLE NotificationFilter = { 0 };
|
||||||
|
// NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
|
||||||
|
// NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
|
||||||
|
|
||||||
|
// Using Win32 Shell API to register for media insert / removal events.
|
||||||
|
LPITEMIDLIST ppidl;
|
||||||
|
if (SHGetSpecialFolderLocation(this->GetHWND(), CSIDL_DESKTOP, &ppidl) == NOERROR) {
|
||||||
|
SHChangeNotifyEntry shCNE;
|
||||||
|
shCNE.pidl = ppidl;
|
||||||
|
shCNE.fRecursive = TRUE;
|
||||||
|
// Returns a positive integer registration identifier (ID).
|
||||||
|
// Returns zero if out of memory or in response to invalid parameters.
|
||||||
|
m_ulSHChangeNotifyRegister = SHChangeNotifyRegister(this->GetHWND(), // Hwnd to receive notification
|
||||||
|
SHCNE_DISKEVENTS, // Event types of interest (sources)
|
||||||
|
SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED,
|
||||||
|
//SHCNE_UPDATEITEM, // Events of interest - use SHCNE_ALLEVENTS for all events
|
||||||
|
WM_USER_MEDIACHANGED, // Notification message to be sent upon the event
|
||||||
|
1, // Number of entries in the pfsne array
|
||||||
|
&shCNE); // Array of SHChangeNotifyEntry structures that
|
||||||
|
// contain the notifications. This array should
|
||||||
|
// always be set to one when calling SHChnageNotifyRegister
|
||||||
|
// or SHChangeNotifyDeregister will not work properly.
|
||||||
|
assert(m_ulSHChangeNotifyRegister != 0); // Shell notification failed
|
||||||
|
} else {
|
||||||
|
// Failed to get desktop location
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
static constexpr int device_count = 1;
|
||||||
|
RAWINPUTDEVICE devices[device_count] = { 0 };
|
||||||
|
// multi-axis mouse (SpaceNavigator, etc.)
|
||||||
|
devices[0].usUsagePage = 0x01;
|
||||||
|
devices[0].usUsage = 0x08;
|
||||||
|
if (! RegisterRawInputDevices(devices, device_count, sizeof(RAWINPUTDEVICE)))
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "RegisterRawInputDevices failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
void MainFrame::create_preset_tabs()
|
void MainFrame::create_preset_tabs()
|
||||||
{
|
{
|
||||||
wxGetApp().update_label_colours_from_appconfig();
|
wxGetApp().update_label_colours_from_appconfig();
|
||||||
|
|
|
@ -156,6 +156,9 @@ public:
|
||||||
void create_preset_tabs();
|
void create_preset_tabs();
|
||||||
void add_created_tab(Tab* panel);
|
void add_created_tab(Tab* panel);
|
||||||
bool is_active_and_shown_tab(Tab* tab);
|
bool is_active_and_shown_tab(Tab* tab);
|
||||||
|
// Register Win32 RawInput callbacks (3DConnexion) and removable media insert / remove callbacks.
|
||||||
|
// Called from wxEVT_ACTIVATE, as wxEVT_CREATE was not reliable (bug in wxWidgets?).
|
||||||
|
void register_win32_callbacks();
|
||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
void init_menubar_as_editor();
|
void init_menubar_as_editor();
|
||||||
void init_menubar_as_gcodeviewer();
|
void init_menubar_as_gcodeviewer();
|
||||||
|
|
|
@ -9,26 +9,22 @@
|
||||||
|
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <wx/glcanvas.h>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <wx/glcanvas.h>
|
||||||
|
|
||||||
|
static constexpr float GAP_WIDTH = 10.0f;
|
||||||
|
static constexpr float SPACE_RIGHT_PANEL = 10.0f;
|
||||||
#define NOTIFICATION_MAX_MOVE 3.0f
|
|
||||||
|
|
||||||
#define GAP_WIDTH 10.0f
|
|
||||||
#define SPACE_RIGHT_PANEL 10.0f
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
wxDEFINE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClickedEvent);
|
wxDEFINE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClickedEvent);
|
||||||
wxDEFINE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent);
|
wxDEFINE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent);
|
||||||
wxDEFINE_EVENT(EVT_PRESET_UPDATE_AVIABLE_CLICKED, PresetUpdateAviableClickedEvent);
|
wxDEFINE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent);
|
||||||
|
|
||||||
namespace Notifications_Internal{
|
namespace Notifications_Internal{
|
||||||
void push_style_color(ImGuiCol idx, const ImVec4& col, bool fading_out, float current_fade_opacity)
|
static inline void push_style_color(ImGuiCol idx, const ImVec4& col, bool fading_out, float current_fade_opacity)
|
||||||
{
|
{
|
||||||
if (fading_out)
|
if (fading_out)
|
||||||
ImGui::PushStyleColor(idx, ImVec4(col.x, col.y, col.z, col.w * current_fade_opacity));
|
ImGui::PushStyleColor(idx, ImVec4(col.x, col.y, col.z, col.w * current_fade_opacity));
|
||||||
|
@ -36,11 +32,34 @@ namespace Notifications_Internal{
|
||||||
ImGui::PushStyleColor(idx, col);
|
ImGui::PushStyleColor(idx, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//ScalableBitmap bmp_icon;
|
|
||||||
|
#if 1
|
||||||
|
// Reuse ImGUI Windows.
|
||||||
|
int NotificationManager::NotificationIDProvider::allocate_id()
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
if (m_released_ids.empty())
|
||||||
|
id = ++m_next_id;
|
||||||
|
else {
|
||||||
|
id = m_released_ids.back();
|
||||||
|
m_released_ids.pop_back();
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
void NotificationManager::NotificationIDProvider::release_id(int id)
|
||||||
|
{
|
||||||
|
m_released_ids.push_back(id);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Don't reuse ImGUI Windows, allocate a new ID every time.
|
||||||
|
int NotificationManager::NotificationIDProvider::allocate_id() { return ++ m_next_id; }
|
||||||
|
void NotificationManager::NotificationIDProvider::release_id(int) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
//------PopNotification--------
|
//------PopNotification--------
|
||||||
NotificationManager::PopNotification::PopNotification(const NotificationData &n, const int id, wxEvtHandler* evt_handler) :
|
NotificationManager::PopNotification::PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler) :
|
||||||
m_data (n)
|
m_data (n)
|
||||||
, m_id (id)
|
, m_id_provider (id_provider)
|
||||||
, m_remaining_time (n.duration)
|
, m_remaining_time (n.duration)
|
||||||
, m_last_remaining_time (n.duration)
|
, m_last_remaining_time (n.duration)
|
||||||
, m_counting_down (n.duration != 0)
|
, m_counting_down (n.duration != 0)
|
||||||
|
@ -51,7 +70,7 @@ NotificationManager::PopNotification::PopNotification(const NotificationData &n,
|
||||||
{
|
{
|
||||||
//init();
|
//init();
|
||||||
}
|
}
|
||||||
NotificationManager::PopNotification::RenderResult NotificationManager::PopNotification::render(GLCanvas3D& canvas, const float& initial_y, bool move_from_overlay, float overlay_width, bool move_from_slope, float slope_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) {
|
||||||
init();
|
init();
|
||||||
|
@ -71,9 +90,8 @@ NotificationManager::PopNotification::RenderResult NotificationManager::PopNotif
|
||||||
Size cnv_size = canvas.get_canvas_size();
|
Size cnv_size = canvas.get_canvas_size();
|
||||||
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
||||||
bool shown = true;
|
bool shown = true;
|
||||||
std::string name;
|
|
||||||
ImVec2 mouse_pos = ImGui::GetMousePos();
|
ImVec2 mouse_pos = ImGui::GetMousePos();
|
||||||
float right_gap = SPACE_RIGHT_PANEL + (move_from_overlay ? overlay_width + m_line_height * 5 : (move_from_slope ? slope_width /*+ m_line_height * 0.3f*/ : 0));
|
float right_gap = SPACE_RIGHT_PANEL + (move_from_overlay ? overlay_width + m_line_height * 5 : 0);
|
||||||
|
|
||||||
if (m_line_height != ImGui::CalcTextSize("A").y)
|
if (m_line_height != ImGui::CalcTextSize("A").y)
|
||||||
init();
|
init();
|
||||||
|
@ -134,8 +152,15 @@ NotificationManager::PopNotification::RenderResult NotificationManager::PopNotif
|
||||||
}
|
}
|
||||||
|
|
||||||
//name of window - probably indentifies window and is shown so last_end add whitespaces according to id
|
//name of window - probably indentifies window and is shown so last_end add whitespaces according to id
|
||||||
for (size_t i = 0; i < m_id; i++)
|
if (! m_id)
|
||||||
name += " ";
|
m_id = m_id_provider.allocate_id();
|
||||||
|
std::string name;
|
||||||
|
{
|
||||||
|
// Create a unique ImGUI window name. The name may be recycled using a name of an already released notification.
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf, "!!Ntfctn%d", m_id);
|
||||||
|
name = buf;
|
||||||
|
}
|
||||||
if (imgui.begin(name, &shown, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar )) {
|
if (imgui.begin(name, &shown, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar )) {
|
||||||
if (shown) {
|
if (shown) {
|
||||||
|
|
||||||
|
@ -234,12 +259,9 @@ void NotificationManager::PopNotification::init()
|
||||||
}
|
}
|
||||||
void NotificationManager::PopNotification::set_next_window_size(ImGuiWrapper& imgui)
|
void NotificationManager::PopNotification::set_next_window_size(ImGuiWrapper& imgui)
|
||||||
{
|
{
|
||||||
if (m_multiline) {
|
m_window_height = m_multiline ?
|
||||||
m_window_height = m_lines_count * m_line_height;
|
m_lines_count * m_line_height :
|
||||||
}else
|
2 * m_line_height;
|
||||||
{
|
|
||||||
m_window_height = 2 * m_line_height;
|
|
||||||
}
|
|
||||||
m_window_height += 1 * m_line_height; // top and bottom
|
m_window_height += 1 * m_line_height; // top and bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,13 +553,13 @@ void NotificationManager::PopNotification::on_text_click()
|
||||||
if (m_evt_handler != nullptr)
|
if (m_evt_handler != nullptr)
|
||||||
wxPostEvent(m_evt_handler, ExportGcodeNotificationClickedEvent(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED));
|
wxPostEvent(m_evt_handler, ExportGcodeNotificationClickedEvent(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED));
|
||||||
break;
|
break;
|
||||||
case NotificationType::PresetUpdateAviable :
|
case NotificationType::PresetUpdateAvailable :
|
||||||
//wxGetApp().plater()->export_gcode(false);
|
//wxGetApp().plater()->export_gcode(false);
|
||||||
assert(m_evt_handler != nullptr);
|
assert(m_evt_handler != nullptr);
|
||||||
if (m_evt_handler != nullptr)
|
if (m_evt_handler != nullptr)
|
||||||
wxPostEvent(m_evt_handler, PresetUpdateAviableClickedEvent(EVT_PRESET_UPDATE_AVIABLE_CLICKED));
|
wxPostEvent(m_evt_handler, PresetUpdateAvailableClickedEvent(EVT_PRESET_UPDATE_AVAILABLE_CLICKED));
|
||||||
break;
|
break;
|
||||||
case NotificationType::NewAppAviable:
|
case NotificationType::NewAppAvailable:
|
||||||
wxLaunchDefaultBrowser("https://github.com/prusa3d/PrusaSlicer/releases");
|
wxLaunchDefaultBrowser("https://github.com/prusa3d/PrusaSlicer/releases");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -562,8 +584,8 @@ bool NotificationManager::PopNotification::compare_text(const std::string& text)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationManager::SlicingCompleteLargeNotification::SlicingCompleteLargeNotification(const NotificationData& n, const int id, wxEvtHandler* evt_handler, bool large) :
|
NotificationManager::SlicingCompleteLargeNotification::SlicingCompleteLargeNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool large) :
|
||||||
NotificationManager::PopNotification(n, id, evt_handler)
|
NotificationManager::PopNotification(n, id_provider, evt_handler)
|
||||||
{
|
{
|
||||||
set_large(large);
|
set_large(large);
|
||||||
}
|
}
|
||||||
|
@ -593,14 +615,13 @@ void NotificationManager::SlicingCompleteLargeNotification::render_text(ImGuiWra
|
||||||
imgui.text(m_text1.c_str());
|
imgui.text(m_text1.c_str());
|
||||||
|
|
||||||
render_hypertext(imgui, x_offset + text1_size.x + 4, cursor_y, m_hypertext);
|
render_hypertext(imgui, x_offset + text1_size.x + 4, cursor_y, m_hypertext);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void NotificationManager::SlicingCompleteLargeNotification::set_print_info(std::string info)
|
void NotificationManager::SlicingCompleteLargeNotification::set_print_info(const std::string &info)
|
||||||
{
|
{
|
||||||
m_print_info = info;
|
m_print_info = info;
|
||||||
m_has_print_info = true;
|
m_has_print_info = true;
|
||||||
if(m_is_large)
|
if (m_is_large)
|
||||||
m_lines_count = 2;
|
m_lines_count = 2;
|
||||||
}
|
}
|
||||||
void NotificationManager::SlicingCompleteLargeNotification::set_large(bool l)
|
void NotificationManager::SlicingCompleteLargeNotification::set_large(bool l)
|
||||||
|
@ -618,7 +639,8 @@ NotificationManager::NotificationManager(wxEvtHandler* evt_handler) :
|
||||||
void NotificationManager::push_notification(const NotificationType type, GLCanvas3D& canvas, int timestamp)
|
void NotificationManager::push_notification(const NotificationType type, GLCanvas3D& canvas, 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, _1) == type);
|
boost::bind(&NotificationData::type, _1) == type);
|
||||||
|
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, canvas, timestamp);
|
||||||
}
|
}
|
||||||
|
@ -628,21 +650,16 @@ void NotificationManager::push_notification(const std::string& text, GLCanvas3D&
|
||||||
}
|
}
|
||||||
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, GLCanvas3D& canvas, int timestamp)
|
||||||
{
|
{
|
||||||
switch (level)
|
int duration = 0;
|
||||||
{
|
switch (level) {
|
||||||
case Slic3r::GUI::NotificationManager::NotificationLevel::RegularNotification:
|
case NotificationLevel::RegularNotification: duration = 10; break;
|
||||||
push_notification_data({ NotificationType::CustomNotification, level, 10, text }, canvas, timestamp);
|
case NotificationLevel::ErrorNotification: break;
|
||||||
break;
|
case NotificationLevel::ImportantNotification: break;
|
||||||
case Slic3r::GUI::NotificationManager::NotificationLevel::ErrorNotification:
|
|
||||||
push_notification_data({ NotificationType::CustomNotification, level, 0, text }, canvas, timestamp);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case Slic3r::GUI::NotificationManager::NotificationLevel::ImportantNotification:
|
|
||||||
push_notification_data({ NotificationType::CustomNotification, level, 0, text }, canvas, timestamp);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
assert(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
push_notification_data({ NotificationType::CustomNotification, level, duration, text }, canvas, timestamp);
|
||||||
}
|
}
|
||||||
void NotificationManager::push_slicing_error_notification(const std::string& text, GLCanvas3D& canvas)
|
void NotificationManager::push_slicing_error_notification(const std::string& text, GLCanvas3D& canvas)
|
||||||
{
|
{
|
||||||
|
@ -650,15 +667,15 @@ void NotificationManager::push_slicing_error_notification(const std::string& tex
|
||||||
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 }, canvas, 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, size_t oid, int warning_step)
|
void NotificationManager::push_slicing_warning_notification(const std::string& text, bool gray, GLCanvas3D& canvas, 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_next_id++, m_evt_handler);
|
auto notification = std::make_unique<NotificationManager::SlicingWarningNotification>(data, m_id_provider, m_evt_handler);
|
||||||
notification->set_object_id(oid);
|
notification->object_id = oid;
|
||||||
notification->set_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), canvas, 0)) {
|
||||||
notification->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, GLCanvas3D& canvas)
|
||||||
|
@ -703,6 +720,7 @@ void NotificationManager::set_all_slicing_warnings_gray(bool g)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
void NotificationManager::set_slicing_warning_gray(const std::string& text, bool g)
|
void NotificationManager::set_slicing_warning_gray(const std::string& text, bool g)
|
||||||
{
|
{
|
||||||
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
||||||
|
@ -711,6 +729,7 @@ void NotificationManager::set_slicing_warning_gray(const std::string& text, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
void NotificationManager::close_slicing_errors_and_warnings()
|
void NotificationManager::close_slicing_errors_and_warnings()
|
||||||
{
|
{
|
||||||
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
||||||
|
@ -723,17 +742,17 @@ void NotificationManager::push_slicing_complete_notification(GLCanvas3D& canvas,
|
||||||
{
|
{
|
||||||
std::string hypertext;
|
std::string hypertext;
|
||||||
int time = 10;
|
int time = 10;
|
||||||
if (has_error_notification())
|
if (has_slicing_error_notification())
|
||||||
return;
|
return;
|
||||||
if (large) {
|
if (large) {
|
||||||
hypertext = _u8L("Export G-Code.");
|
hypertext = _u8L("Export G-Code.");
|
||||||
time = 0;
|
time = 0;
|
||||||
}
|
}
|
||||||
NotificationData data{ NotificationType::SlicingComplete, NotificationLevel::RegularNotification, time, _u8L("Slicing finished."), hypertext };
|
NotificationData data{ NotificationType::SlicingComplete, NotificationLevel::RegularNotification, time, _u8L("Slicing finished."), hypertext };
|
||||||
push_notification_data(std::make_unique<NotificationManager::SlicingCompleteLargeNotification>(data, m_next_id++, m_evt_handler, large),
|
push_notification_data(std::make_unique<NotificationManager::SlicingCompleteLargeNotification>(data, m_id_provider, m_evt_handler, large),
|
||||||
canvas, timestamp);
|
canvas, timestamp);
|
||||||
}
|
}
|
||||||
void NotificationManager::set_slicing_complete_print_time(std::string info)
|
void NotificationManager::set_slicing_complete_print_time(const std::string &info)
|
||||||
{
|
{
|
||||||
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
||||||
if (notification->get_type() == NotificationType::SlicingComplete) {
|
if (notification->get_type() == NotificationType::SlicingComplete) {
|
||||||
|
@ -759,26 +778,18 @@ void NotificationManager::close_notification_of_type(const NotificationType type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void NotificationManager::compare_warning_oids(const std::vector<size_t>& living_oids)
|
void NotificationManager::remove_slicing_warnings_of_released_objects(const std::vector<ObjectID>& living_oids)
|
||||||
{
|
{
|
||||||
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications)
|
||||||
if (notification->get_type() == NotificationType::SlicingWarning) {
|
if (notification->get_type() == NotificationType::SlicingWarning) {
|
||||||
auto w = dynamic_cast<SlicingWarningNotification*>(notification.get());
|
if (! std::binary_search(living_oids.begin(), living_oids.end(),
|
||||||
bool found = false;
|
static_cast<SlicingWarningNotification*>(notification.get())->object_id))
|
||||||
for (size_t oid : living_oids) {
|
|
||||||
if (w->get_object_id() == oid) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
notification->close();
|
notification->close();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
bool NotificationManager::push_notification_data(const NotificationData ¬ification_data, GLCanvas3D& canvas, int timestamp)
|
bool NotificationManager::push_notification_data(const NotificationData ¬ification_data, GLCanvas3D& canvas, int timestamp)
|
||||||
{
|
{
|
||||||
return push_notification_data(std::make_unique<PopNotification>(notification_data, m_next_id++, m_evt_handler), canvas, timestamp);
|
return push_notification_data(std::make_unique<PopNotification>(notification_data, m_id_provider, m_evt_handler), canvas, 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, GLCanvas3D& canvas, int timestamp)
|
||||||
{
|
{
|
||||||
|
@ -790,23 +801,23 @@ bool NotificationManager::push_notification_data(std::unique_ptr<NotificationMan
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this->find_older(notification.get())) {
|
if (this->activate_existing(notification.get())) {
|
||||||
m_pop_notifications.emplace_back(std::move(notification));
|
|
||||||
canvas.request_extra_frame();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
m_pop_notifications.back()->update(notification->get_data());
|
m_pop_notifications.back()->update(notification->get_data());
|
||||||
canvas.request_extra_frame();
|
canvas.request_extra_frame();
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
m_pop_notifications.emplace_back(std::move(notification));
|
||||||
|
canvas.request_extra_frame();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay_width, float slope_width)
|
void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay_width)
|
||||||
{
|
{
|
||||||
float last_x = 0.0f;
|
float last_x = 0.0f;
|
||||||
float current_height = 0.0f;
|
float current_height = 0.0f;
|
||||||
bool request_next_frame = false;
|
bool request_next_frame = false;
|
||||||
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
|
// iterate thru notifications and render them / erease 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();) {
|
||||||
|
@ -814,7 +825,7 @@ void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay
|
||||||
it = m_pop_notifications.erase(it);
|
it = m_pop_notifications.erase(it);
|
||||||
} else {
|
} else {
|
||||||
(*it)->set_paused(m_hovered);
|
(*it)->set_paused(m_hovered);
|
||||||
PopNotification::RenderResult res = (*it)->render(canvas, last_x, m_move_from_overlay, overlay_width, m_move_from_slope, slope_width);
|
PopNotification::RenderResult res = (*it)->render(canvas, last_x, m_move_from_overlay, overlay_width);
|
||||||
if (res != PopNotification::RenderResult::Finished) {
|
if (res != PopNotification::RenderResult::Finished) {
|
||||||
last_x = (*it)->get_top() + GAP_WIDTH;
|
last_x = (*it)->get_top() + GAP_WIDTH;
|
||||||
current_height = std::max(current_height, (*it)->get_current_top());
|
current_height = std::max(current_height, (*it)->get_current_top());
|
||||||
|
@ -837,26 +848,34 @@ void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay
|
||||||
if (!top_level_wnd->IsActive())
|
if (!top_level_wnd->IsActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_hovered && m_last_time < wxGetLocalTime())
|
|
||||||
{
|
{
|
||||||
if (wxGetLocalTime() - m_last_time == 1)
|
// 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)
|
||||||
{
|
{
|
||||||
for(auto ¬ification : m_pop_notifications)
|
if (now - m_last_time == 1)
|
||||||
{
|
{
|
||||||
notification->substract_remaining_time();
|
for (auto ¬ification : m_pop_notifications)
|
||||||
|
{
|
||||||
|
notification->substract_remaining_time();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
m_last_time = now;
|
||||||
}
|
}
|
||||||
m_last_time = wxGetLocalTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request_next_frame)
|
if (request_next_frame)
|
||||||
|
//FIXME this is very expensive for fade-out control.
|
||||||
|
// If any of the notifications is fading out, 100% of the CPU/GPU is consumed.
|
||||||
canvas.request_extra_frame();
|
canvas.request_extra_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NotificationManager::sort_notifications()
|
void NotificationManager::sort_notifications()
|
||||||
{
|
{
|
||||||
std::sort(m_pop_notifications.begin(), m_pop_notifications.end(), [](const std::unique_ptr<PopNotification> &n1, const std::unique_ptr<PopNotification> &n2) {
|
// Stable sorting, so that the order of equal ranges is stable.
|
||||||
|
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->get_is_gray() && !n2->get_is_gray())
|
||||||
|
@ -865,20 +884,20 @@ void NotificationManager::sort_notifications()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NotificationManager::find_older(NotificationManager::PopNotification* notification)
|
bool NotificationManager::activate_existing(const NotificationManager::PopNotification* notification)
|
||||||
{
|
{
|
||||||
NotificationType type = notification->get_type();
|
NotificationType new_type = notification->get_type();
|
||||||
std::string 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() == type && !(*it)->get_finished()) {
|
if ((*it)->get_type() == new_type && !(*it)->get_finished()) {
|
||||||
if (type == NotificationType::CustomNotification || type == NotificationType::PlaterWarning) {
|
if (new_type == NotificationType::CustomNotification || new_type == NotificationType::PlaterWarning) {
|
||||||
if (!(*it)->compare_text(text))
|
if (!(*it)->compare_text(new_text))
|
||||||
continue;
|
continue;
|
||||||
}else if (type == NotificationType::SlicingWarning) {
|
} else if (new_type == NotificationType::SlicingWarning) {
|
||||||
auto w1 = dynamic_cast<SlicingWarningNotification*>(notification);
|
auto w1 = dynamic_cast<const SlicingWarningNotification*>(notification);
|
||||||
auto w2 = dynamic_cast<SlicingWarningNotification*>(it->get());
|
auto w2 = dynamic_cast<const SlicingWarningNotification*>(it->get());
|
||||||
if (w1 != nullptr && w2 != nullptr) {
|
if (w1 != nullptr && w2 != nullptr) {
|
||||||
if (!(*it)->compare_text(text) || w1->get_object_id() != w2->get_object_id()) {
|
if (!(*it)->compare_text(new_text) || w1->object_id != w2->object_id) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -894,7 +913,7 @@ bool NotificationManager::find_older(NotificationManager::PopNotification* notif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotificationManager::set_in_preview(bool preview)
|
void NotificationManager::set_in_preview(bool preview)
|
||||||
{
|
{
|
||||||
m_in_preview = preview;
|
m_in_preview = preview;
|
||||||
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
||||||
|
@ -902,18 +921,12 @@ void NotificationManager::set_in_preview(bool preview)
|
||||||
notification->hide(preview);
|
notification->hide(preview);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool NotificationManager::has_error_notification()
|
|
||||||
{
|
|
||||||
for (std::unique_ptr<PopNotification> ¬ification : m_pop_notifications) {
|
|
||||||
if (notification->get_data().level == NotificationLevel::ErrorNotification)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotificationManager::dpi_changed()
|
bool NotificationManager::has_slicing_error_notification()
|
||||||
{
|
{
|
||||||
|
return std::any_of(m_pop_notifications.begin(), m_pop_notifications.end(), [](auto &n) {
|
||||||
|
return n->get_type() == NotificationType::SlicingError;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}//namespace GUI
|
}//namespace GUI
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "Event.hpp"
|
#include "Event.hpp"
|
||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
|
|
||||||
|
#include <libslic3r/ObjectID.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
@ -16,8 +18,8 @@ using EjectDriveNotificationClickedEvent = SimpleEvent;
|
||||||
wxDECLARE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClickedEvent);
|
wxDECLARE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClickedEvent);
|
||||||
using ExportGcodeNotificationClickedEvent = SimpleEvent;
|
using ExportGcodeNotificationClickedEvent = SimpleEvent;
|
||||||
wxDECLARE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent);
|
wxDECLARE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent);
|
||||||
using PresetUpdateAviableClickedEvent = SimpleEvent;
|
using PresetUpdateAvailableClickedEvent = SimpleEvent;
|
||||||
wxDECLARE_EVENT(EVT_PRESET_UPDATE_AVIABLE_CLICKED, PresetUpdateAviableClickedEvent);
|
wxDECLARE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent);
|
||||||
|
|
||||||
class GLCanvas3D;
|
class GLCanvas3D;
|
||||||
class ImGuiWrapper;
|
class ImGuiWrapper;
|
||||||
|
@ -25,22 +27,36 @@ class ImGuiWrapper;
|
||||||
enum class NotificationType
|
enum class NotificationType
|
||||||
{
|
{
|
||||||
CustomNotification,
|
CustomNotification,
|
||||||
|
// Notification on end of slicing and G-code processing (the full G-code preview is available).
|
||||||
|
// Contains a hyperlink to export the G-code to a removable media.
|
||||||
SlicingComplete,
|
SlicingComplete,
|
||||||
SlicingNotPossible,
|
// SlicingNotPossible,
|
||||||
|
// Notification on end of export to a removable media, with hyperling to eject the external media.
|
||||||
ExportToRemovableFinished,
|
ExportToRemovableFinished,
|
||||||
|
// Works on OSX only.
|
||||||
|
//FIXME Do we want to have it on Linux and Windows? Is it possible to get the Disconnect event on Windows?
|
||||||
Mouse3dDisconnected,
|
Mouse3dDisconnected,
|
||||||
Mouse3dConnected,
|
// Mouse3dConnected,
|
||||||
NewPresetsAviable,
|
// NewPresetsAviable,
|
||||||
NewAppAviable,
|
// Notification on the start of PrusaSlicer, when a new PrusaSlicer version is published.
|
||||||
PresetUpdateAviable,
|
// Contains a hyperlink to open a web browser pointing to the PrusaSlicer download location.
|
||||||
LoadingFailed,
|
NewAppAvailable,
|
||||||
ValidateError, // currently not used - instead Slicing error is used for both slicing and validate errors
|
// Notification on the start of PrusaSlicer, when updates of system profiles are detected.
|
||||||
|
// Contains a hyperlink to execute installation of the new system profiles.
|
||||||
|
PresetUpdateAvailable,
|
||||||
|
// LoadingFailed,
|
||||||
|
// Not used - instead Slicing error is used for both slicing and validate errors.
|
||||||
|
// ValidateError,
|
||||||
|
// Slicing error produced by BackgroundSlicingProcess::validate() or by the BackgroundSlicingProcess background
|
||||||
|
// thread thowing a SlicingError exception.
|
||||||
SlicingError,
|
SlicingError,
|
||||||
|
// Slicing warnings, issued by the slicing process.
|
||||||
|
// Slicing warnings are registered for a particular Print milestone or a PrintObject and its milestone.
|
||||||
SlicingWarning,
|
SlicingWarning,
|
||||||
|
// Object partially outside the print volume. Cannot slice.
|
||||||
PlaterError,
|
PlaterError,
|
||||||
PlaterWarning,
|
// Object fully outside the print volume, or extrusion outside the print volume. Slicing is not disabled.
|
||||||
ApplyError
|
PlaterWarning
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class NotificationManager
|
class NotificationManager
|
||||||
|
@ -48,46 +64,62 @@ class NotificationManager
|
||||||
public:
|
public:
|
||||||
enum class NotificationLevel : int
|
enum class NotificationLevel : int
|
||||||
{
|
{
|
||||||
ErrorNotification = 4,
|
// The notifications will be presented in the order of importance, thus these enum values
|
||||||
WarningNotification = 3,
|
// are sorted by the importance.
|
||||||
ImportantNotification = 2,
|
// "Good to know" notification, usually but not always with a quick fade-out.
|
||||||
RegularNotification = 1,
|
RegularNotification = 1,
|
||||||
|
// Information notification without a fade-out or with a longer fade-out.
|
||||||
|
ImportantNotification,
|
||||||
|
// Warning, no fade-out.
|
||||||
|
WarningNotification,
|
||||||
|
// Error, no fade-out.
|
||||||
|
ErrorNotification,
|
||||||
};
|
};
|
||||||
|
|
||||||
NotificationManager(wxEvtHandler* evt_handler);
|
NotificationManager(wxEvtHandler* evt_handler);
|
||||||
|
|
||||||
// only type means one of basic_notification (see below)
|
// 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, GLCanvas3D& canvas, int timestamp = 0);
|
||||||
// only text means Undefined type
|
// 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, GLCanvas3D& canvas, int timestamp = 0);
|
||||||
|
// Push a NotificationType::CustomNotification with provided notification level and 10s for RegularNotification.
|
||||||
|
// 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, GLCanvas3D& canvas, int timestamp = 0);
|
||||||
// creates Slicing Error notification with custom text
|
// 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, GLCanvas3D& canvas);
|
||||||
// creates Slicing Warning notification with custom text
|
// 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, size_t oid, int warning_step);
|
void push_slicing_warning_notification(const std::string& text, bool gray, GLCanvas3D& canvas, 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
|
||||||
void set_all_slicing_warnings_gray(bool g);
|
void set_all_slicing_warnings_gray(bool g);
|
||||||
void set_slicing_warning_gray(const std::string& text, bool g);
|
// void set_slicing_warning_gray(const std::string& text, bool g);
|
||||||
// imidietly stops showing slicing errors
|
// immediately stops showing slicing errors
|
||||||
void close_slicing_errors_and_warnings();
|
void close_slicing_errors_and_warnings();
|
||||||
void compare_warning_oids(const std::vector<size_t>& living_oids);
|
// Release those slicing warnings, which refer to an ObjectID, which is not in the list.
|
||||||
|
// living_oids is expected to be sorted.
|
||||||
|
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.
|
||||||
void push_plater_error_notification(const std::string& text, GLCanvas3D& canvas);
|
void push_plater_error_notification(const std::string& text, GLCanvas3D& canvas);
|
||||||
|
// 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, GLCanvas3D& canvas);
|
||||||
// Closes error or warning of 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 prints printing time and export button
|
// 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.
|
||||||
void push_slicing_complete_notification(GLCanvas3D& canvas, int timestamp, bool large);
|
void push_slicing_complete_notification(GLCanvas3D& canvas, int timestamp, bool large);
|
||||||
void set_slicing_complete_print_time(std::string info);
|
// Add a print time estimate to an existing SlicingComplete notification.
|
||||||
|
void set_slicing_complete_print_time(const std::string &info);
|
||||||
|
// Called when the side bar changes its visibility, as the "slicing complete" notification supplements
|
||||||
|
// the "slicing info" normally shown at the side bar.
|
||||||
void set_slicing_complete_large(bool large);
|
void set_slicing_complete_large(bool large);
|
||||||
// renders notifications in queue and deletes expired ones
|
// renders notifications in queue and deletes expired ones
|
||||||
void render_notifications(GLCanvas3D& canvas, float overlay_width, float slope_width);
|
void render_notifications(GLCanvas3D& canvas, 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);
|
||||||
void dpi_changed();
|
// 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; }
|
||||||
|
@ -97,10 +129,25 @@ private:
|
||||||
struct NotificationData {
|
struct NotificationData {
|
||||||
NotificationType type;
|
NotificationType type;
|
||||||
NotificationLevel level;
|
NotificationLevel level;
|
||||||
|
// Fade out time
|
||||||
const int duration;
|
const int duration;
|
||||||
const std::string text1;
|
const std::string text1;
|
||||||
const std::string hypertext = std::string();
|
const std::string hypertext;
|
||||||
const std::string text2 = std::string();
|
const std::string text2;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cache of IDs to identify and reuse ImGUI windows.
|
||||||
|
class NotificationIDProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int allocate_id();
|
||||||
|
void release_id(int id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Next ID used for naming the ImGUI windows.
|
||||||
|
int m_next_id{ 1 };
|
||||||
|
// IDs of ImGUI windows, which were released and they are ready for reuse.
|
||||||
|
std::vector<int> m_released_ids;
|
||||||
};
|
};
|
||||||
|
|
||||||
//Pop notification - shows only once to user.
|
//Pop notification - shows only once to user.
|
||||||
|
@ -115,9 +162,9 @@ private:
|
||||||
Countdown,
|
Countdown,
|
||||||
Hovered
|
Hovered
|
||||||
};
|
};
|
||||||
PopNotification(const NotificationData &n, const int id, wxEvtHandler* evt_handler);
|
PopNotification(const NotificationData &n, NotificationIDProvider &id_provider, wxEvtHandler* evt_handler);
|
||||||
virtual ~PopNotification() = default;
|
virtual ~PopNotification() { if (m_id) m_id_provider.release_id(m_id); }
|
||||||
RenderResult render(GLCanvas3D& canvas, const float& initial_y, bool move_from_overlay, float overlay_width, bool move_from_slope, float slope_width);
|
RenderResult render(GLCanvas3D& canvas, const float& initial_y, bool move_from_overlay, float overlay_width);
|
||||||
// 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
|
||||||
|
@ -136,6 +183,7 @@ private:
|
||||||
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; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Call after every size change
|
// Call after every size change
|
||||||
void init();
|
void init();
|
||||||
|
@ -161,7 +209,9 @@ private:
|
||||||
|
|
||||||
const NotificationData m_data;
|
const NotificationData m_data;
|
||||||
|
|
||||||
int m_id;
|
// For reusing ImGUI windows.
|
||||||
|
NotificationIDProvider &m_id_provider;
|
||||||
|
int m_id { 0 };
|
||||||
bool m_initialized { false };
|
bool m_initialized { false };
|
||||||
// Main text
|
// Main text
|
||||||
std::string m_text1;
|
std::string m_text1;
|
||||||
|
@ -203,17 +253,18 @@ private:
|
||||||
//if multiline = true, notification is showing all lines(>2)
|
//if multiline = true, notification is showing all lines(>2)
|
||||||
bool m_multiline { false };
|
bool m_multiline { false };
|
||||||
int m_lines_count{ 1 };
|
int m_lines_count{ 1 };
|
||||||
|
// Target for wxWidgets events sent by clicking on the hyperlink available at some notifications.
|
||||||
wxEvtHandler* m_evt_handler;
|
wxEvtHandler* m_evt_handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SlicingCompleteLargeNotification : public PopNotification
|
class SlicingCompleteLargeNotification : public PopNotification
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SlicingCompleteLargeNotification(const NotificationData& n, const int id, wxEvtHandler* evt_handler, bool largeds);
|
SlicingCompleteLargeNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, bool largeds);
|
||||||
void set_large(bool l);
|
void set_large(bool l);
|
||||||
bool get_large() { return m_is_large; }
|
bool get_large() { return m_is_large; }
|
||||||
|
|
||||||
void set_print_info(std::string info);
|
void set_print_info(const std::string &info);
|
||||||
protected:
|
protected:
|
||||||
virtual void render_text(ImGuiWrapper& imgui,
|
virtual void render_text(ImGuiWrapper& imgui,
|
||||||
const float win_size_x, const float win_size_y,
|
const float win_size_x, const float win_size_y,
|
||||||
|
@ -228,14 +279,9 @@ private:
|
||||||
class SlicingWarningNotification : public PopNotification
|
class SlicingWarningNotification : public PopNotification
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SlicingWarningNotification(const NotificationData& n, const int id, wxEvtHandler* evt_handler) : PopNotification(n, id, evt_handler) {}
|
SlicingWarningNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler) : PopNotification(n, id_provider, evt_handler) {}
|
||||||
void set_object_id(size_t id) { object_id = id; }
|
ObjectID object_id;
|
||||||
const size_t get_object_id() { return object_id; }
|
int warning_step;
|
||||||
void set_warning_step(int ws) { warning_step = ws; }
|
|
||||||
const int get_warning_step() { return warning_step; }
|
|
||||||
protected:
|
|
||||||
size_t object_id;
|
|
||||||
int warning_step;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//pushes notification into the queue of notifications that are rendered
|
//pushes notification into the queue of notifications that are rendered
|
||||||
|
@ -243,31 +289,38 @@ private:
|
||||||
bool push_notification_data(const NotificationData& notification_data, GLCanvas3D& canvas, int timestamp);
|
bool push_notification_data(const NotificationData& notification_data, GLCanvas3D& canvas, 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, GLCanvas3D& canvas, 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 find_older(NotificationManager::PopNotification* notification);
|
bool activate_existing(const NotificationManager::PopNotification* notification);
|
||||||
|
// Put the more important notifications to the bottom of the list.
|
||||||
void sort_notifications();
|
void sort_notifications();
|
||||||
bool has_error_notification();
|
// If there is some error notification active, then the "Export G-code" notification after the slicing is finished is suppressed.
|
||||||
|
bool has_slicing_error_notification();
|
||||||
|
|
||||||
|
// Target for wxWidgets events sent by clicking on the hyperlink available at some notifications.
|
||||||
wxEvtHandler* m_evt_handler;
|
wxEvtHandler* m_evt_handler;
|
||||||
|
// Cache of IDs to identify and reuse ImGUI windows.
|
||||||
|
NotificationIDProvider m_id_provider;
|
||||||
std::deque<std::unique_ptr<PopNotification>> m_pop_notifications;
|
std::deque<std::unique_ptr<PopNotification>> m_pop_notifications;
|
||||||
int m_next_id { 1 };
|
// Last render time in seconds for fade out control.
|
||||||
long m_last_time { 0 };
|
long m_last_time { 0 };
|
||||||
|
// When mouse hovers over some notification, the fade-out of all notifications is suppressed.
|
||||||
bool m_hovered { false };
|
bool m_hovered { false };
|
||||||
//timestamps used for slining finished - notification could be gone so it needs to be stored here
|
//timestamps used for slicing finished - notification could be gone so it needs to be stored here
|
||||||
std::unordered_set<int> m_used_timestamps;
|
std::unordered_set<int> m_used_timestamps;
|
||||||
|
// True if G-code preview is active. False if the Plater is active.
|
||||||
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.
|
||||||
bool m_move_from_overlay { false };
|
bool m_move_from_overlay { false };
|
||||||
bool m_move_from_slope{ false };
|
|
||||||
|
|
||||||
//prepared (basic) notifications
|
//prepared (basic) notifications
|
||||||
const std::vector<NotificationData> basic_notifications = {
|
const std::vector<NotificationData> basic_notifications = {
|
||||||
{NotificationType::SlicingNotPossible, NotificationLevel::RegularNotification, 10, _u8L("Slicing is not possible.")},
|
// {NotificationType::SlicingNotPossible, NotificationLevel::RegularNotification, 10, _u8L("Slicing is not possible.")},
|
||||||
{NotificationType::ExportToRemovableFinished, NotificationLevel::ImportantNotification, 0, _u8L("Exporting finished."), _u8L("Eject drive.") },
|
{NotificationType::ExportToRemovableFinished, NotificationLevel::ImportantNotification, 0, _u8L("Exporting finished."), _u8L("Eject drive.") },
|
||||||
{NotificationType::Mouse3dDisconnected, NotificationLevel::RegularNotification, 10, _u8L("3D Mouse disconnected.") },
|
{NotificationType::Mouse3dDisconnected, NotificationLevel::RegularNotification, 10, _u8L("3D Mouse disconnected.") },
|
||||||
{NotificationType::Mouse3dConnected, NotificationLevel::RegularNotification, 5, _u8L("3D Mouse connected.") },
|
// {NotificationType::Mouse3dConnected, NotificationLevel::RegularNotification, 5, _u8L("3D Mouse connected.") },
|
||||||
{NotificationType::NewPresetsAviable, NotificationLevel::ImportantNotification, 20, _u8L("New Presets are available."), _u8L("See here.") },
|
// {NotificationType::NewPresetsAviable, NotificationLevel::ImportantNotification, 20, _u8L("New Presets are available."), _u8L("See here.") },
|
||||||
{NotificationType::PresetUpdateAviable, NotificationLevel::ImportantNotification, 20, _u8L("Configuration update is available."), _u8L("See more.")},
|
{NotificationType::PresetUpdateAvailable, NotificationLevel::ImportantNotification, 20, _u8L("Configuration update is available."), _u8L("See more.")},
|
||||||
{NotificationType::NewAppAviable, NotificationLevel::ImportantNotification, 20, _u8L("New version is available."), _u8L("See Releases page.")},
|
{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotification, 20, _u8L("New version is available."), _u8L("See Releases page.")},
|
||||||
//{NotificationType::NewAppAviable, NotificationLevel::ImportantNotification, 20, _u8L("New vesion of PrusaSlicer is available.", _u8L("Download page.") },
|
//{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotification, 20, _u8L("New vesion of PrusaSlicer is available.", _u8L("Download page.") },
|
||||||
//{NotificationType::LoadingFailed, NotificationLevel::RegularNotification, 20, _u8L("Loading of model has Failed") },
|
//{NotificationType::LoadingFailed, NotificationLevel::RegularNotification, 20, _u8L("Loading of model has Failed") },
|
||||||
//{NotificationType::DeviceEjected, NotificationLevel::RegularNotification, 10, _u8L("Removable device has been safely ejected")} // if we want changeble text (like here name of device), we need to do it as CustomNotification
|
//{NotificationType::DeviceEjected, NotificationLevel::RegularNotification, 10, _u8L("Removable device has been safely ejected")} // if we want changeble text (like here name of device), we need to do it as CustomNotification
|
||||||
};
|
};
|
||||||
|
|
|
@ -1714,7 +1714,8 @@ struct Plater::priv
|
||||||
|
|
||||||
void clear_warnings();
|
void clear_warnings();
|
||||||
void add_warning(const Slic3r::PrintStateBase::Warning &warning, size_t oid);
|
void add_warning(const Slic3r::PrintStateBase::Warning &warning, size_t oid);
|
||||||
void actualizate_warnings(const Model& model, size_t print_oid);
|
// Update notification manager with the current state of warnings produced by the background process (slicing).
|
||||||
|
void actualize_slicing_warnings(const PrintBase &print);
|
||||||
// Displays dialog window with list of warnings.
|
// Displays dialog window with list of warnings.
|
||||||
// Returns true if user clicks OK.
|
// Returns true if user clicks OK.
|
||||||
// Returns true if current_warnings vector is empty without showning the dialog
|
// Returns true if current_warnings vector is empty without showning the dialog
|
||||||
|
@ -2023,7 +2024,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||||
#endif // ENABLE_GCODE_VIEWER
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
this->q->Bind(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, [this](EjectDriveNotificationClickedEvent&) { this->q->eject_drive(); });
|
this->q->Bind(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, [this](EjectDriveNotificationClickedEvent&) { this->q->eject_drive(); });
|
||||||
this->q->Bind(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, [this](ExportGcodeNotificationClickedEvent&) { this->q->export_gcode(true); });
|
this->q->Bind(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, [this](ExportGcodeNotificationClickedEvent&) { this->q->export_gcode(true); });
|
||||||
this->q->Bind(EVT_PRESET_UPDATE_AVIABLE_CLICKED, [this](PresetUpdateAviableClickedEvent&) { wxGetApp().get_preset_updater()->on_update_notification_confirm(); });
|
this->q->Bind(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, [this](PresetUpdateAvailableClickedEvent&) { wxGetApp().get_preset_updater()->on_update_notification_confirm(); });
|
||||||
this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this, q](RemovableDriveEjectEvent &evt) {
|
this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this, q](RemovableDriveEjectEvent &evt) {
|
||||||
if (evt.data.second) {
|
if (evt.data.second) {
|
||||||
this->show_action_buttons(this->ready_to_slice);
|
this->show_action_buttons(this->ready_to_slice);
|
||||||
|
@ -2885,8 +2886,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||||
|
|
||||||
//actualizate warnings
|
//actualizate warnings
|
||||||
if (invalidated != Print::APPLY_STATUS_UNCHANGED) {
|
if (invalidated != Print::APPLY_STATUS_UNCHANGED) {
|
||||||
actualizate_warnings(this->q->model(), this->background_process.current_print()->id().id);
|
actualize_slicing_warnings(*this->background_process.current_print());
|
||||||
notification_manager->set_all_slicing_warnings_gray(true);
|
|
||||||
show_warning_dialog = false;
|
show_warning_dialog = false;
|
||||||
process_completed_with_error = false;
|
process_completed_with_error = false;
|
||||||
}
|
}
|
||||||
|
@ -3474,7 +3474,7 @@ 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.id, warning_step);
|
notification_manager->push_slicing_warning_notification(warning.message, false, *q->get_current_canvas3D(), object_id, warning_step);
|
||||||
add_warning(warning, object_id.id);
|
add_warning(warning, object_id.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3483,7 +3483,6 @@ 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_notification(NotificationType::SlicingComplete, *q->get_current_canvas3D(), evt.GetInt());
|
|
||||||
notification_manager->push_slicing_complete_notification(*q->get_current_canvas3D(), evt.GetInt(), is_sidebar_collapsed());
|
notification_manager->push_slicing_complete_notification(*q->get_current_canvas3D(), evt.GetInt(), is_sidebar_collapsed());
|
||||||
|
|
||||||
switch (this->printer_technology) {
|
switch (this->printer_technology) {
|
||||||
|
@ -3520,19 +3519,17 @@ void Plater::priv::add_warning(const Slic3r::PrintStateBase::Warning& warning, s
|
||||||
}
|
}
|
||||||
current_warnings.emplace_back(std::pair<Slic3r::PrintStateBase::Warning, size_t>(warning, oid));
|
current_warnings.emplace_back(std::pair<Slic3r::PrintStateBase::Warning, size_t>(warning, oid));
|
||||||
}
|
}
|
||||||
void Plater::priv::actualizate_warnings(const Model& model, size_t print_oid)
|
void Plater::priv::actualize_slicing_warnings(const PrintBase &print)
|
||||||
{
|
{
|
||||||
if (model.objects.size() == 0) {
|
std::vector<ObjectID> ids = print.print_object_ids();
|
||||||
|
if (ids.empty()) {
|
||||||
clear_warnings();
|
clear_warnings();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::vector<size_t> living_oids;
|
ids.emplace_back(print.id());
|
||||||
living_oids.push_back(model.id().id);
|
std::sort(ids.begin(), ids.end());
|
||||||
living_oids.push_back(print_oid);
|
notification_manager->remove_slicing_warnings_of_released_objects(ids);
|
||||||
for (auto it = model.objects.begin(); it != model.objects.end(); ++it) {
|
notification_manager->set_all_slicing_warnings_gray(true);
|
||||||
living_oids.push_back((*it)->id().id);
|
|
||||||
}
|
|
||||||
notification_manager->compare_warning_oids(living_oids);
|
|
||||||
}
|
}
|
||||||
void Plater::priv::clear_warnings()
|
void Plater::priv::clear_warnings()
|
||||||
{
|
{
|
||||||
|
|
|
@ -826,7 +826,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::PresetUpdateAviable, *(GUI::wxGetApp().plater()->get_current_canvas3D()));
|
GUI::wxGetApp().plater()->get_notification_manager()->push_notification(GUI::NotificationType::PresetUpdateAvailable, *(GUI::wxGetApp().plater()->get_current_canvas3D()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// MsgUpdateConfig will show after the notificaation is clicked
|
// MsgUpdateConfig will show after the notificaation is clicked
|
||||||
|
|
Loading…
Reference in a new issue