From bed3eed3d2188f3960cbaa9edd02573668d56800 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 20 Nov 2018 13:22:26 +0100 Subject: [PATCH 1/3] The slicing progress message can now trigger refresh of the 3D scene. --- src/libslic3r/PrintBase.hpp | 34 +++++++---- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 2 +- src/slic3r/GUI/BackgroundSlicingProcess.hpp | 19 ++++-- src/slic3r/GUI/Plater.cpp | 66 ++++++++++++++------- 4 files changed, 83 insertions(+), 38 deletions(-) diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index 67f8c9e86..435b50dd3 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -31,12 +31,14 @@ public: DONE, }; + typedef size_t TimeStamp; + // A new unique timestamp is being assigned to the step every time the step changes its state. struct StateWithTimeStamp { StateWithTimeStamp() : state(INVALID), timestamp(0) {} - State state; - size_t timestamp; + State state; + TimeStamp timestamp; }; protected: @@ -90,13 +92,14 @@ public: // Set the step as done. Block on mutex while the Print / PrintObject / PrintRegion objects are being // modified by the UI thread. template - void set_done(StepType step, tbb::mutex &mtx, ThrowIfCanceled throw_if_canceled) { + TimeStamp set_done(StepType step, tbb::mutex &mtx, ThrowIfCanceled throw_if_canceled) { tbb::mutex::scoped_lock lock(mtx); // If canceled, throw before changing the step state. throw_if_canceled(); assert(m_state[step].state != DONE); m_state[step].state = DONE; m_state[step].timestamp = ++ g_last_timestamp; + return m_state[step].timestamp; } // Make the step invalid. @@ -236,16 +239,27 @@ public: virtual void process() = 0; - typedef std::function status_callback_type; + struct Status { + Status(int percent, const std::string &text, unsigned int flags = 0) : percent(percent), text(text), flags(flags) {} + int percent; + std::string text; + // Bitmap of flags. + enum FlagBits { + RELOAD_SCENE = 1, + }; + // Bitmap of FlagBits + unsigned int flags; + }; + typedef std::function status_callback_type; // Default status console print out in the form of percent => message. void set_status_default() { m_status_callback = nullptr; } // No status output or callback whatsoever, useful mostly for automatic tests. - void set_status_silent() { m_status_callback = [](int, const std::string&){}; } + void set_status_silent() { m_status_callback = [](const Status&){}; } // Register a custom status callback. void set_status_callback(status_callback_type cb) { m_status_callback = cb; } // Calls a registered callback to update the status, or print out the default message. - void set_status(int percent, const std::string &message) { - if (m_status_callback) m_status_callback(percent, message); + void set_status(int percent, const std::string &message, unsigned int flags = 0) { + if (m_status_callback) m_status_callback(Status(percent, message, flags)); else printf("%d => %s\n", percent, message.c_str()); } @@ -309,7 +323,7 @@ public: protected: bool set_started(PrintStepEnum step) { return m_state.set_started(step, this->state_mutex(), [this](){ this->throw_if_canceled(); }); } - void set_done(PrintStepEnum step) { m_state.set_done(step, this->state_mutex(), [this](){ this->throw_if_canceled(); }); } + PrintStateBase::TimeStamp set_done(PrintStepEnum step) { return m_state.set_done(step, this->state_mutex(), [this](){ this->throw_if_canceled(); }); } bool invalidate_step(PrintStepEnum step) { return m_state.invalidate(step, this->cancel_callback()); } template @@ -340,8 +354,8 @@ protected: bool set_started(PrintObjectStepEnum step) { return m_state.set_started(step, PrintObjectBase::state_mutex(m_print), [this](){ PrintObjectBase::throw_if_canceled(this->m_print); }); } - void set_done(PrintObjectStepEnum step) - { m_state.set_done(step, PrintObjectBase::state_mutex(m_print), [this](){ PrintObjectBase::throw_if_canceled(this->m_print); }); } + PrintStateBase::TimeStamp set_done(PrintObjectStepEnum step) + { return m_state.set_done(step, PrintObjectBase::state_mutex(m_print), [this](){ PrintObjectBase::throw_if_canceled(this->m_print); }); } bool invalidate_step(PrintObjectStepEnum step) { return m_state.invalidate(step, PrintObjectBase::cancel_callback(m_print)); } diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 5c3c24201..4a33065ab 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -60,7 +60,7 @@ void BackgroundSlicingProcess::process_fff() { assert(m_print == m_fff_print); m_print->process(); - wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_sliced_id)); + wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_slicing_completed_id)); m_fff_print->export_gcode(m_temp_output_path, m_gcode_preview_data); if (this->set_step_started(bspsGCodeFinalize)) { if (! m_export_path.empty()) { diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index ea24b0eda..123829050 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -15,6 +15,18 @@ class GCodePreviewData; class Model; class SLAPrint; +class SlicingStatusEvent : public wxEvent +{ +public: + SlicingStatusEvent(wxEventType eventType, int winid, const PrintBase::Status &status) : + wxEvent(winid, eventType), status(std::move(status)) {} + virtual wxEvent *Clone() const { return new SlicingStatusEvent(*this); } + + PrintBase::Status status; +}; + +wxDEFINE_EVENT(EVT_SLICING_UPDATE, SlicingStatusEvent); + // Print step IDs for keeping track of the print state. enum BackgroundSlicingProcessStep { bspsGCodeFinalize, bspsCount, @@ -35,7 +47,7 @@ public: // The following wxCommandEvent will be sent to the UI thread / Platter window, when the slicing is finished // and the background processing will transition into G-code export. // The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed. - void set_sliced_event(int event_id) { m_event_sliced_id = event_id; } + void set_slicing_completed_event(int event_id) { m_event_slicing_completed_id = event_id; } // The following wxCommandEvent will be sent to the UI thread / Platter window, when the G-code export is finished. // The wxCommandEvent is sent to the UI thread asynchronously without waiting for the event to be processed. void set_finished_event(int event_id) { m_event_finished_id = event_id; } @@ -133,11 +145,10 @@ private: // If the background processing stop was requested, throw CanceledException. void throw_if_canceled() const { if (m_print->canceled()) throw CanceledException(); } - // wxWidgets command ID to be sent to the platter to inform that the slicing is finished, and the G-code export will continue. - int m_event_sliced_id = 0; + int m_event_slicing_completed_id = 0; // wxWidgets command ID to be sent to the platter to inform that the task finished. - int m_event_finished_id = 0; + int m_event_finished_id = 0; }; }; // namespace Slic3r diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7768df7dd..632a203c8 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -65,8 +65,7 @@ using Slic3r::Preset; namespace Slic3r { namespace GUI { - -wxDEFINE_EVENT(EVT_PROGRESS_BAR, wxCommandEvent); +wxDEFINE_EVENT(EVT_SLICING_UPDATE, SlicingStatusEvent); wxDEFINE_EVENT(EVT_SLICING_COMPLETED, wxCommandEvent); wxDEFINE_EVENT(EVT_PROCESS_COMPLETED, wxCommandEvent); @@ -949,8 +948,8 @@ struct Plater::priv void on_notebook_changed(wxBookCtrlEvent&); void on_select_preset(wxCommandEvent&); - void on_progress_event(wxCommandEvent&); - void on_update_print_preview(wxCommandEvent&); + void on_slicing_update(SlicingStatusEvent&); + void on_slicing_completed(wxCommandEvent&); void on_process_completed(wxCommandEvent&); void on_layer_editing_toggled(bool enable); @@ -1009,21 +1008,18 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : background_process.set_fff_print(&print); background_process.set_sla_print(&sla_print); background_process.set_gcode_preview_data(&gcode_preview_data); - background_process.set_sliced_event(EVT_SLICING_COMPLETED); + background_process.set_slicing_completed_event(EVT_SLICING_COMPLETED); background_process.set_finished_event(EVT_PROCESS_COMPLETED); // Default printer technology for default config. background_process.select_technology(this->printer_technology); // Register progress callback from the Print class to the Platter. - auto statuscb = [this](int percent, const std::string &message) { - wxCommandEvent event(EVT_PROGRESS_BAR); - event.SetInt(percent); - event.SetString(message); - wxQueueEvent(this->q, event.Clone()); + auto statuscb = [this](const Slic3r::PrintBase::Status &status) { + wxQueueEvent(this->q, new Slic3r::SlicingStatusEvent(EVT_SLICING_UPDATE, 0, status)); }; print.set_status_callback(statuscb); sla_print.set_status_callback(statuscb); - this->q->Bind(EVT_PROGRESS_BAR, &priv::on_progress_event, this); + this->q->Bind(EVT_SLICING_UPDATE, &priv::on_slicing_update, this); _3DScene::add_canvas(canvas3D); _3DScene::allow_multisample(canvas3D, GLCanvas3DManager::can_multisample()); @@ -1098,7 +1094,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) : // Preview events: preview->get_wxglcanvas()->Bind(EVT_GLCANVAS_VIEWPORT_CHANGED, &priv::on_viewport_changed, this); - q->Bind(EVT_SLICING_COMPLETED, &priv::on_update_print_preview, this); + q->Bind(EVT_SLICING_COMPLETED, &priv::on_slicing_completed, this); q->Bind(EVT_PROCESS_COMPLETED, &priv::on_process_completed, this); // Drop target: @@ -1869,21 +1865,43 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) wxGetApp().plater()->on_config_change(wxGetApp().preset_bundle->full_config()); } -void Plater::priv::on_progress_event(wxCommandEvent &evt) +void Plater::priv::on_slicing_update(SlicingStatusEvent &evt) { - this->statusbar()->set_progress(evt.GetInt()); - this->statusbar()->set_status_text(evt.GetString() + wxString::FromUTF8("…")); + this->statusbar()->set_progress(evt.status.percent); + this->statusbar()->set_status_text(_(L(evt.status.text)) + wxString::FromUTF8("…")); + if (evt.status.flags & PrintBase::Status::RELOAD_SCENE) { + switch (this->printer_technology) { + case ptFFF: + if (this->preview != nullptr) + this->preview->reload_print(); + break; + case ptSLA: + // Refresh the scene lazily by updating only SLA meshes. + //FIXME update SLAPrint? + _3DScene::reload_scene(canvas3D, true); + break; + } + } } -void Plater::priv::on_update_print_preview(wxCommandEvent &) +void Plater::priv::on_slicing_completed(wxCommandEvent &) { - if (this->preview != nullptr) - this->preview->reload_print(); - // in case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth: -// auto selections = collect_selections(); -// _3DScene::set_objects_selections(canvas3D, selections); -// if (canvas3D) -// _3DScene::reload_scene(canvas3D, true); + switch (this->printer_technology) { + case ptFFF: + if (this->preview != nullptr) + this->preview->reload_print(); + // in case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth: + // auto selections = collect_selections(); + // _3DScene::set_objects_selections(canvas3D, selections); + // if (canvas3D) + // _3DScene::reload_scene(canvas3D, true); + break; + case ptSLA: + // Refresh the scene lazily by updating only SLA meshes. + //FIXME update SLAPrint? + _3DScene::reload_scene(canvas3D, true); + break; + } } void Plater::priv::on_process_completed(wxCommandEvent &evt) @@ -2526,6 +2544,8 @@ void Plater::on_config_change(const DynamicPrintConfig &config) if (opt_key == "printer_technology") { p->printer_technology = config.opt_enum(opt_key); p->background_process.select_technology(this->printer_technology()); + //FIXME for SLA synchronize + //p->background_process.apply(Model)! } else if (opt_key == "bed_shape") { if (p->canvas3D) _3DScene::set_bed_shape(p->canvas3D, p->config->option(opt_key)->values); From 0ec37ae038fec3f69c9e87332dbdefb195389bcc Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 20 Nov 2018 15:01:32 +0100 Subject: [PATCH 2/3] Fixed missing wxEvent type on GCC, fixed some compiler warnings. --- src/libslic3r/GCodeReader.hpp | 12 ++++++++++-- src/slic3r/GUI/BackgroundSlicingProcess.cpp | 1 - src/slic3r/GUI/BackgroundSlicingProcess.hpp | 2 ++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/GCodeReader.hpp b/src/libslic3r/GCodeReader.hpp index 84ed89a7c..13f9e7dd7 100644 --- a/src/libslic3r/GCodeReader.hpp +++ b/src/libslic3r/GCodeReader.hpp @@ -126,8 +126,16 @@ private: static bool is_end_of_line(char c) { return c == '\r' || c == '\n' || c == 0; } static bool is_end_of_gcode_line(char c) { return c == ';' || is_end_of_line(c); } static bool is_end_of_word(char c) { return is_whitespace(c) || is_end_of_gcode_line(c); } - static const char* skip_whitespaces(const char *c) { for (; is_whitespace(*c); ++ c); return c; } - static const char* skip_word(const char *c) { for (; ! is_end_of_word(*c); ++ c); return c; } + static const char* skip_whitespaces(const char *c) { + for (; is_whitespace(*c); ++ c) + ; // silence -Wempty-body + return c; + } + static const char* skip_word(const char *c) { + for (; ! is_end_of_word(*c); ++ c) + ; // silence -Wempty-body + return c; + } GCodeConfig m_config; char m_extrusion_axis; diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index 4a33065ab..35dfcdf0e 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -2,7 +2,6 @@ #include "GUI_App.hpp" #include -#include #include #include diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index 123829050..9cfaa4317 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -6,6 +6,8 @@ #include #include +#include + #include "Print.hpp" namespace Slic3r { From 8ecb2163b638c212a7549c752d98a188f138fb03 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 20 Nov 2018 15:18:46 +0100 Subject: [PATCH 3/3] Hopefully a fix of OSX compilation issue. --- src/libslic3r/PrintBase.cpp | 5 ----- src/libslic3r/PrintBase.hpp | 11 ++++++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/PrintBase.cpp b/src/libslic3r/PrintBase.cpp index 7ae5b1f9f..a44f42fbd 100644 --- a/src/libslic3r/PrintBase.cpp +++ b/src/libslic3r/PrintBase.cpp @@ -15,9 +15,4 @@ std::function PrintObjectBase::cancel_callback(PrintBase *print) return print->cancel_callback(); } -void PrintObjectBase::throw_if_canceled(PrintBase *print) -{ - print->throw_if_canceled(); -} - } // namespace Slic3r diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index 435b50dd3..94c732c0b 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -190,9 +190,6 @@ protected: // Declared here to allow access from PrintBase through friendship. static tbb::mutex& state_mutex(PrintBase *print); static std::function cancel_callback(PrintBase *print); - // If the background processing stop was requested, throw CanceledException. - // To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly. - static void throw_if_canceled(PrintBase *print); ModelObject *m_model_object; }; @@ -353,9 +350,9 @@ protected: PrintObjectBaseWithState(PrintType *print, ModelObject *model_object) : PrintObjectBase(model_object), m_print(print) {} bool set_started(PrintObjectStepEnum step) - { return m_state.set_started(step, PrintObjectBase::state_mutex(m_print), [this](){ PrintObjectBase::throw_if_canceled(this->m_print); }); } + { return m_state.set_started(step, PrintObjectBase::state_mutex(m_print), [this](){ this->throw_if_canceled(); }); } PrintStateBase::TimeStamp set_done(PrintObjectStepEnum step) - { return m_state.set_done(step, PrintObjectBase::state_mutex(m_print), [this](){ PrintObjectBase::throw_if_canceled(this->m_print); }); } + { return m_state.set_done(step, PrintObjectBase::state_mutex(m_print), [this](){ this->throw_if_canceled(); }); } bool invalidate_step(PrintObjectStepEnum step) { return m_state.invalidate(step, PrintObjectBase::cancel_callback(m_print)); } @@ -368,6 +365,10 @@ protected: { return m_state.invalidate_all(PrintObjectBase::cancel_callback(m_print)); } protected: + // If the background processing stop was requested, throw CanceledException. + // To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly. + void throw_if_canceled() { if (m_print->canceled()) throw CanceledException(); } + friend PrintType; PrintType *m_print;