diff --git a/README.md b/README.md index 40c22b98a..e3947b9f5 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,7 @@ The author of the Silk icon set is Mark James. --post-process Generated G-code will be processed with the supplied script; call this more than once to process through multiple scripts. --export-svg Export a SVG file containing slices instead of G-code. + --export-png Export zipped PNG files containing slices instead of G-code. -m, --merge If multiple files are supplied, they will be composed into a single print rather than processed individually. @@ -385,4 +386,4 @@ If you want to change a preset file, just do If you want to slice a file overriding an option contained in your preset file: - slic3r.pl --load config.ini --layer-height 0.25 file.stl \ No newline at end of file + slic3r.pl --load config.ini --layer-height 0.25 file.stl diff --git a/slic3r.pl b/slic3r.pl index d9bed0ab6..0ddd9662f 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -43,6 +43,7 @@ my %cli_options = (); 'gui-mode=s' => \$opt{obsolete_ignore_this_option_gui_mode}, 'datadir=s' => \$opt{datadir}, 'export-svg' => \$opt{export_svg}, + 'export-png' => \$opt{export_png}, 'merge|m' => \$opt{merge}, 'repair' => \$opt{repair}, 'cut=f' => \$opt{cut}, @@ -217,6 +218,8 @@ if (@ARGV) { # slicing from command line if ($opt{export_svg}) { $sprint->export_svg; + } elsif ($opt{export_png}) { + $sprint->export_png; } else { my $t0 = [gettimeofday]; # The following call may die if the output_filename_format template substitution fails, @@ -282,6 +285,7 @@ Usage: slic3r.pl [ OPTIONS ] [ file.stl ] [ file2.stl ] ... --post-process Generated G-code will be processed with the supplied script; call this more than once to process through multiple scripts. --export-svg Export a SVG file containing slices instead of G-code. + --export-png Export zipped PNG files containing slices instead of G-code. -m, --merge If multiple files are supplied, they will be composed into a single print rather than processed individually. diff --git a/xs/src/slic3r/AppController.hpp b/xs/src/slic3r/AppController.hpp index 783911387..2d51ad51e 100644 --- a/xs/src/slic3r/AppController.hpp +++ b/xs/src/slic3r/AppController.hpp @@ -17,14 +17,15 @@ class PrintObject; /** * @brief A boilerplate class for creating application logic. It should provide - * features as issue reporting, gauge and progress indication, etc... + * features as issue reporting and progress indication, etc... * - * The lower lever UI independent classes should be manipulated with a subclass + * The lower lever UI independent classes can be manipulated with a subclass * of this controller class. We can also catch any exceptions that lower level * methods could throw and display appropriate errors and warnings. * - * Note that even the inner interface of this class free from any UI toolkit. - * We can implement it with any UI framework or make it a cli client. + * Note that the outer and the inner interface of this class is free from any + * UI toolkit dependencies. We can implement it with any UI framework or make it + * a cli client. */ class AppControllerBoilerplate { class PriMap; // Some structure to store progress indication data @@ -73,7 +74,7 @@ public: const std::string& title) const; /** - * @brief Same as query_destination_path but returns only one path. + * @brief Same as query_destination_paths but returns only one path. */ Path query_destination_path( const std::string& title, @@ -124,7 +125,7 @@ public: * created the AppConroller object itself. This probably means that the * execution is in the UI thread. Otherwise it returns false meaning that * some worker thread called this function. - * @return Return true if for the same caller thread that created this + * @return Return true for the same caller thread that created this * object and false for every other. */ bool is_main_thread() const; @@ -132,7 +133,7 @@ public: protected: /** - * @brief Create a new progress indicator and retirn a smart pointer to it. + * @brief Create a new progress indicator and return a smart pointer to it. * @param statenum The number of states for the given procedure. * @param title The title of the procedure. * @param firstmsg The message for the first subtask to be displayed. @@ -143,7 +144,8 @@ protected: const std::string& title, const std::string& firstmsg = "") const; - // This is a global + // This is a global progress indicator placeholder. In the Slic3r UI it can + // contain the progress indicator on the statusbar. ProgresIndicatorPtr global_progressind_; }; @@ -162,16 +164,19 @@ protected: void infill(PrintObject *pobj); void gen_support_material(PrintObject *pobj); + // Data structure with the png export input data struct PngExportData { - std::string zippath; - unsigned long width_px = 1440; - unsigned long height_px = 2560; - double width_mm = 68.0, height_mm = 120.0; - double corr = 1.0; + std::string zippath; // output zip file + unsigned long width_px = 1440; // resolution - rows + unsigned long height_px = 2560; // resolution columns + double width_mm = 68.0, height_mm = 120.0; // dimensions in mm + double corr = 1.0; // multiplies the dimensions }; + // Should display a dialog with the input fields for printing to png PngExportData query_png_export_data(); + // The previous export data, to pre-populate the dialog PngExportData prev_expdata_; public: diff --git a/xs/src/slic3r/AppControllerWx.cpp b/xs/src/slic3r/AppControllerWx.cpp index 583506b9a..f417ae8c8 100644 --- a/xs/src/slic3r/AppControllerWx.cpp +++ b/xs/src/slic3r/AppControllerWx.cpp @@ -13,6 +13,11 @@ #include #include +// This source file implements the UI dependent methods of the AppControllers. +// It will be clear what is needed to be reimplemented in case of a UI framework +// change or a CLI client creation. In this particular case we use wxWidgets to +// implement everything. + namespace Slic3r { AppControllerBoilerplate::PathList @@ -73,6 +78,11 @@ void AppControllerBoilerplate::report_issue(IssueType issuetype, wxDEFINE_EVENT(PROGRESS_STATUS_UPDATE_EVENT, wxCommandEvent); namespace { + +/* + * A simple thread safe progress dialog implementation that can be used from + * the main thread as well. + */ class GuiProgressIndicator: public IProgressIndicator, public wxEvtHandler { @@ -91,6 +101,7 @@ class GuiProgressIndicator: _state(st); } + // Status update implementation void _state( unsigned st) { if(st < max()) { if(!gauge_) gauge_ = std::make_shared( @@ -114,7 +125,10 @@ class GuiProgressIndicator: public: + /// Setting whether it will be used from the UI thread or some worker thread inline void asynch(bool is) { is_asynch_ = is; } + + /// Get the mode of parallel operation. inline bool asynch() const { return is_asynch_; } inline GuiProgressIndicator(int range, const std::string& title, @@ -167,12 +181,16 @@ AppControllerBoilerplate::create_progress_indicator( auto pri = std::make_shared(statenum, title, firstmsg); + // We set up the mode of operation depending of the creator thread's + // identity pri->asynch(!is_main_thread()); return pri; } namespace { + +// A wrapper progress indicator class around the statusbar created in perl. class Wrapper: public IProgressIndicator, public wxEvtHandler { wxGauge *gauge_; wxStatusBar *stbar_; @@ -264,6 +282,7 @@ void AppController::set_global_progress_indicator( PrintController::PngExportData PrintController::query_png_export_data() { + // Implement the logic of the PngExportDialog class PngExportView: public PngExportDialog { double ratio_, bs_ratio_; public: @@ -308,26 +327,28 @@ PrintController::PngExportData PrintController::query_png_export_data() virtual void EvalResoSpin( wxCommandEvent& event ) override { if(reso_lock_btn_->GetValue()) { - if(event.GetId() == spin_reso_width_->GetId()) { spin_reso_height_->SetValue( std::round(spin_reso_width_->GetValue()/ratio_)); + spin_reso_height_->Update(); } else { spin_reso_width_->SetValue( std::round(spin_reso_height_->GetValue()*ratio_)); + spin_reso_width_->Update(); } } } virtual void EvalBedSpin( wxCommandEvent& event ) override { if(bedsize_lock_btn_->GetValue()) { - if(event.GetId() == bed_width_spin_->GetId()) { bed_height_spin_->SetValue( std::round(bed_width_spin_->GetValue()/bs_ratio_)); + bed_height_spin_->Update(); } else { bed_width_spin_->SetValue( std::round(bed_height_spin_->GetValue()*bs_ratio_)); + bed_width_spin_->Update(); } } } diff --git a/xs/src/slic3r/GUI/PngExportDialog.cpp b/xs/src/slic3r/GUI/PngExportDialog.cpp index 26d18e0ea..fc9b23123 100644 --- a/xs/src/slic3r/GUI/PngExportDialog.cpp +++ b/xs/src/slic3r/GUI/PngExportDialog.cpp @@ -73,7 +73,7 @@ PngExportDialog::PngExportDialog( wxWindow* parent, wxWindowID id, const wxStrin reso_lock_btn_ = new wxToggleButton( this, wxID_ANY, _("Lock"), wxDefaultPosition, wxDefaultSize, 0 ); reso_lock_btn_->SetValue(true); - resolution_spins_layout_->Add( reso_lock_btn_, 0, wxALL, 5 ); + resolution_spins_layout_->Add( reso_lock_btn_, 0, wxALIGN_CENTER|wxALL, 5 ); resolution_layout_->Add( resolution_spins_layout_, 1, wxEXPAND, 5 ); @@ -95,7 +95,7 @@ PngExportDialog::PngExportDialog( wxWindow* parent, wxWindowID id, const wxStrin bedsize_lock_btn_ = new wxToggleButton( this, wxID_ANY, _("Lock"), wxDefaultPosition, wxDefaultSize, 0 ); bedsize_lock_btn_->SetValue(true); - bedsize_spins_layout_->Add( bedsize_lock_btn_, 0, wxALL, 5 ); + bedsize_spins_layout_->Add( bedsize_lock_btn_, 0, wxALIGN_CENTER|wxALL, 5 ); bedsize_layout_->Add( bedsize_spins_layout_, 1, wxEXPAND, 5 );