Fixing crash on linux. Exporting png in the UI thread.

This commit is contained in:
tamasmeszaros 2018-07-02 14:50:54 +02:00
parent 18bfe4f2dc
commit 4f27f6c6dc
5 changed files with 72 additions and 63 deletions

View File

@ -289,16 +289,19 @@ void print_to(Print& print,
int st_prev = 0; int st_prev = 0;
const std::string jobdesc = "Rasterizing and compressing sliced layers"; const std::string jobdesc = "Rasterizing and compressing sliced layers";
print.set_status(0, jobdesc);
tbb::spin_mutex m; tbb::spin_mutex m;
std::vector<long long> keys; std::vector<long long> keys;
keys.reserve(layers.size()); keys.reserve(layers.size());
for(auto& e : layers) keys.push_back(e.first); for(auto& e : layers) keys.push_back(e.first);
int initstatus = print.progressindicator? print.progressindicator->state()
: 0;
print.set_status(initstatus, jobdesc);
// Method that prints one layer // Method that prints one layer
auto process_layer = [&layers, &keys, &printer, &st_prev, &m, auto process_layer = [&layers, &keys, &printer, &st_prev, &m,
&jobdesc, print_bb, dir, cx, cy, &print] (unsigned layer_id) &jobdesc, print_bb, dir, cx, cy, &print, initstatus] (unsigned layer_id)
{ {
LayerPtrs lrange = layers[keys[layer_id]]; LayerPtrs lrange = layers[keys[layer_id]];
@ -345,10 +348,10 @@ void print_to(Print& print,
printer.finishLayer(layer_id); // Finish the layer for later saving it. printer.finishLayer(layer_id); // Finish the layer for later saving it.
auto st = static_cast<int>(layer_id*100.0/layers.size()); auto st = static_cast<int>(layer_id*80.0/layers.size());
m.lock(); m.lock();
if( st - st_prev > 10) { if( st - st_prev > 10) {
print.set_status(st, jobdesc); print.set_status(initstatus + st, jobdesc);
st_prev = st; st_prev = st;
} }
m.unlock(); m.unlock();
@ -364,12 +367,12 @@ void print_to(Print& print,
// Sequential version (for testing) // Sequential version (for testing)
// for(unsigned l = 0; l < layers.size(); ++l) process_layer(l); // for(unsigned l = 0; l < layers.size(); ++l) process_layer(l);
print.set_status(100, jobdesc); // print.set_status(100, jobdesc);
// Save the print into the file system. // Save the print into the file system.
print.set_status(0, "Writing layers to disk"); print.set_status(initstatus + 90, "Writing layers to disk");
printer.save(dir); printer.save(dir);
print.set_status(100, "Writing layers completed"); print.set_status(initstatus + 100, "Writing layers completed");
} }
} }

View File

@ -5,6 +5,7 @@
#include <cstdarg> #include <cstdarg>
#include <thread> #include <thread>
#include <unordered_map> #include <unordered_map>
#include <chrono>
#include <slic3r/GUI/GUI.hpp> #include <slic3r/GUI/GUI.hpp>
#include <slic3r/GUI/PresetBundle.hpp> #include <slic3r/GUI/PresetBundle.hpp>
@ -230,43 +231,52 @@ void PrintController::gen_support_material(PrintObject *pobj)
} }
} }
void PrintController::slice() void PrintController::slice(AppControllerBoilerplate::ProgresIndicatorPtr pri)
{ {
auto st = pri->state();
Slic3r::trace(3, "Starting the slicing process."); Slic3r::trace(3, "Starting the slicing process.");
progress_indicator()->update(20u, "Generating perimeters"); pri->update(st+20, "Generating perimeters");
for(auto obj : print_->objects) make_perimeters(obj); for(auto obj : print_->objects) make_perimeters(obj);
progress_indicator()->update(60u, "Infilling layers"); pri->update(st+60, "Infilling layers");
for(auto obj : print_->objects) infill(obj); for(auto obj : print_->objects) infill(obj);
progress_indicator()->update(70u, "Generating support material"); pri->update(st+70, "Generating support material");
for(auto obj : print_->objects) gen_support_material(obj); for(auto obj : print_->objects) gen_support_material(obj);
progress_indicator()->message_fmt("Weight: %.1fg, Cost: %.1f", pri->message_fmt("Weight: %.1fg, Cost: %.1f",
print_->total_weight, print_->total_weight,
print_->total_cost); print_->total_cost);
progress_indicator()->state(85u); pri->state(st+85);
progress_indicator()->update(88u, "Generating skirt"); pri->update(st+88, "Generating skirt");
make_skirt(); make_skirt();
progress_indicator()->update(90u, "Generating brim"); pri->update(st+90, "Generating brim");
make_brim(); make_brim();
progress_indicator()->update(95u, "Generating wipe tower"); pri->update(st+95, "Generating wipe tower");
make_wipe_tower(); make_wipe_tower();
progress_indicator()->update(100u, "Done"); pri->update(st+100, "Done");
// time to make some statistics.. // time to make some statistics..
Slic3r::trace(3, "Slicing process finished."); Slic3r::trace(3, "Slicing process finished.");
} }
void PrintController::slice()
{
auto pri = progress_indicator();
slice(pri);
}
void PrintController::slice_to_png() void PrintController::slice_to_png()
{ {
auto exd = query_png_export_data(); auto exd = query_png_export_data();
@ -319,22 +329,22 @@ void PrintController::slice_to_png()
report_issue(IssueType::WARN, ss.str(), "Warning"); report_issue(IssueType::WARN, ss.str(), "Warning");
} }
std::async(supports_asynch()? std::launch::async : std::launch::deferred, // std::async(supports_asynch()? std::launch::async : std::launch::deferred,
[this, exd, correction]() // [this, exd, correction]()
{ // {
progress_indicator(100, "Slicing to zipped png files..."); auto pri = create_progress_indicator(200, "Slicing to zipped png files...");
progress_indicator()->procedure_count(3);
try { try {
slice(); pri->update(0, "Slicing...");
slice(pri);
} catch (std::exception& e) { } catch (std::exception& e) {
report_issue(IssueType::ERR, e.what(), "Exception"); report_issue(IssueType::ERR, e.what(), "Exception");
progress_indicator()->cancel(); pri->cancel();
return; return;
} }
auto pbak = print_->progressindicator; auto pbak = print_->progressindicator;
print_->progressindicator = progress_indicator(); print_->progressindicator = pri;
try { try {
print_to<FilePrinterFormat::PNG>( *print_, exd.zippath, print_to<FilePrinterFormat::PNG>( *print_, exd.zippath,
@ -344,7 +354,7 @@ void PrintController::slice_to_png()
} catch (std::exception& e) { } catch (std::exception& e) {
report_issue(IssueType::ERR, e.what(), "Exception"); report_issue(IssueType::ERR, e.what(), "Exception");
progress_indicator()->cancel(); pri->cancel();
} }
if(correction) { // scale the model back if(correction) { // scale the model back
@ -360,7 +370,8 @@ void PrintController::slice_to_png()
} }
print_->progressindicator = pbak; print_->progressindicator = pbak;
}); // });
} }
void IProgressIndicator::message_fmt( void IProgressIndicator::message_fmt(

View File

@ -147,6 +147,8 @@ public:
*/ */
bool supports_asynch() const; bool supports_asynch() const;
void process_events();
protected: protected:
/** /**
@ -200,6 +202,8 @@ protected:
// The previous export data, to pre-populate the dialog // The previous export data, to pre-populate the dialog
PngExportData prev_expdata_; PngExportData prev_expdata_;
void slice(ProgresIndicatorPtr pri);
public: public:
// Must be public for perl to use it // Must be public for perl to use it

View File

@ -26,6 +26,11 @@ bool AppControllerBoilerplate::supports_asynch() const
return true; return true;
} }
void AppControllerBoilerplate::process_events()
{
wxSafeYield();
}
AppControllerBoilerplate::PathList AppControllerBoilerplate::PathList
AppControllerBoilerplate::query_destination_paths( AppControllerBoilerplate::query_destination_paths(
const std::string &title, const std::string &title,
@ -95,11 +100,11 @@ namespace {
class GuiProgressIndicator: class GuiProgressIndicator:
public IProgressIndicator, public wxEvtHandler { public IProgressIndicator, public wxEvtHandler {
std::shared_ptr<wxProgressDialog> gauge_; wxProgressDialog gauge_;
using Base = IProgressIndicator; using Base = IProgressIndicator;
wxString message_; wxString message_;
int range_; wxString title_; int range_; wxString title_;
unsigned prc_ = 0; // unsigned prc_ = 0;
bool is_asynch_ = false; bool is_asynch_ = false;
const int id_ = wxWindow::NewControlId(); const int id_ = wxWindow::NewControlId();
@ -107,29 +112,26 @@ class GuiProgressIndicator:
// status update handler // status update handler
void _state( wxCommandEvent& evt) { void _state( wxCommandEvent& evt) {
unsigned st = evt.GetInt(); unsigned st = evt.GetInt();
message_ = evt.GetString();
_state(st); _state(st);
} }
// Status update implementation // Status update implementation
void _state( unsigned st) { void _state( unsigned st) {
if(st < max()) { // if(st < max()) {
if(!gauge_) gauge_ = std::make_shared<wxProgressDialog>( if(!gauge_.IsShown()) gauge_.ShowModal();
title_, message_, range_, wxTheApp->GetTopWindow(),
wxPD_APP_MODAL | wxPD_AUTO_HIDE
);
if(!gauge_->IsShown()) gauge_->ShowModal();
Base::state(st); Base::state(st);
gauge_->Update(static_cast<int>(st), message_); gauge_.Update(static_cast<int>(st), message_);
} // }
if(st == max()) { // if(st == max()) {
prc_++; // prc_++;
if(prc_ == Base::procedure_count()) { // if(prc_ == Base::procedure_count()) {
gauge_.reset(); // //gauge_.reset();
prc_ = 0; // gauge_.Update(static_cast<int>(st), message_);
} // prc_ = 0;
} // }
// }
} }
public: public:
@ -142,7 +144,10 @@ public:
inline GuiProgressIndicator(int range, const std::string& title, inline GuiProgressIndicator(int range, const std::string& title,
const std::string& firstmsg) : const std::string& firstmsg) :
range_(range), message_(_(firstmsg)), title_(_(title)) gauge_(title, firstmsg, range, wxTheApp->GetTopWindow(),
wxPD_APP_MODAL | wxPD_AUTO_HIDE),
message_(_(firstmsg)),
range_(range), title_(_(title))
{ {
Base::max(static_cast<float>(range)); Base::max(static_cast<float>(range));
Base::states(static_cast<unsigned>(range)); Base::states(static_cast<unsigned>(range));
@ -158,7 +163,7 @@ public:
} }
virtual void state(float val) override { virtual void state(float val) override {
if( val >= 1.0) state(static_cast<unsigned>(val)); /*if( val >= 1.0) */state(static_cast<unsigned>(val));
} }
void state(unsigned st) { void state(unsigned st) {
@ -166,6 +171,7 @@ public:
if(is_asynch_) { if(is_asynch_) {
auto evt = new wxCommandEvent(PROGRESS_STATUS_UPDATE_EVENT, id_); auto evt = new wxCommandEvent(PROGRESS_STATUS_UPDATE_EVENT, id_);
evt->SetInt(st); evt->SetInt(st);
evt->SetString(message_);
wxQueueEvent(this, evt); wxQueueEvent(this, evt);
} else _state(st); } else _state(st);
} }
@ -223,7 +229,7 @@ class Wrapper: public IProgressIndicator, public wxEvtHandler {
if(!gauge_->IsShown()) showProgress(true); if(!gauge_->IsShown()) showProgress(true);
stbar_->SetStatusText(message_); stbar_->SetStatusText(message_);
if(st == gauge_->GetRange()) { if(static_cast<long>(st) == gauge_->GetRange()) {
gauge_->SetValue(0); gauge_->SetValue(0);
showProgress(false); showProgress(false);
} else { } else {
@ -409,5 +415,4 @@ PrintController::PngExportData PrintController::query_png_export_data()
return ret; return ret;
} }
} }

View File

@ -16,7 +16,6 @@ public:
private: private:
float state_ = .0f, max_ = 1.f, step_; float state_ = .0f, max_ = 1.f, step_;
CancelFn cancelfunc_ = [](){}; CancelFn cancelfunc_ = [](){};
unsigned proc_count_ = 1;
public: public:
@ -60,19 +59,6 @@ public:
*/ */
virtual void cancel() { cancelfunc_(); } virtual void cancel() { cancelfunc_(); }
/**
* \brief Set up how many subprocedures does the whole operation contain.
*
* This was neccesary from practical reasons. If the progress indicator is
* a dialog and we want to show the progress of a few sub operations than
* the dialog wont be closed and reopened each time a new sub operation is
* started. This is not a mandatory feature and can be ignored completely.
*/
inline void procedure_count(unsigned pc) { proc_count_ = pc; }
/// Get the current procedure count
inline unsigned procedure_count() const { return proc_count_; }
/// Convinience function to call message and status update in one function. /// Convinience function to call message and status update in one function.
void update(float st, const std::string& msg) { void update(float st, const std::string& msg) {
message(msg); state(st); message(msg); state(st);