diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 760a0f330..dce9f4be0 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -274,6 +274,13 @@ sub save_settings { Slic3r::Config->write_ini("$datadir/slic3r.ini", $Settings); } +# Called after the Preferences dialog is closed and the program settings are saved. +# Update the UI based on the current preferences. +sub update_ui_from_settings { + my ($self) = @_; + $self->{mainframe}->update_ui_from_settings; +} + sub presets { my ($self, $section) = @_; diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 970c754f7..675449228 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -94,10 +94,19 @@ sub new { # propagate event $event->Skip; }); + + $self->update_ui_from_settings; return $self; } +sub reslice_now { + my ($self) = @_; + + if ($self->{plater}) { + $self->{plater}->reslice; + } +} sub _init_tabpanel { my ($self) = @_; @@ -223,6 +232,9 @@ sub _init_menubar { $self->_append_menu_item($fileMenu, "Slice to SV&G…\tCtrl+G", 'Slice file to SVG', sub { $self->quick_slice(save_as => 1, export_svg => 1); }, undef, 'shape_handles.png'); + $self->{menu_item_reslice_now} = $self->_append_menu_item( + $fileMenu, "(&Re)Slice Now\tCtrl+S", 'Start new slicing process', + sub { $self->reslice_now; }, undef, 'shape_handles.png'); $fileMenu->AppendSeparator(); $self->_append_menu_item($fileMenu, "Repair STL file…", 'Automatically repair an STL file', sub { $self->repair_stl; @@ -471,6 +483,13 @@ sub quick_slice { Slic3r::GUI::catch_error($self, sub { $progress_dialog->Destroy if $progress_dialog }); } +sub reslice_now { + my ($self) = @_; + if ($self->{plater}) { + $self->{plater}->reslice; + } +} + sub repair_stl { my $self = shift; @@ -834,4 +853,12 @@ sub _set_menu_item_icon { } } +# Called after the Preferences dialog is closed and the program settings are saved. +# Update the UI based on the current preferences. +sub update_ui_from_settings { + my ($self) = @_; + $self->{menu_item_reslice_now}->Enable(! $Slic3r::GUI::Settings->{_}{background_processing}); + $self->{plater}->update_ui_from_settings if ($self->{plater}); +} + 1; diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index e496e1233..d565bd2ad 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -36,6 +36,7 @@ use constant TB_SETTINGS => &Wx::NewId; our $THUMBNAIL_DONE_EVENT : shared = Wx::NewEventType; our $PROGRESS_BAR_EVENT : shared = Wx::NewEventType; our $ERROR_EVENT : shared = Wx::NewEventType; +# Emitted from the worker thread when the G-code export is finished. our $EXPORT_COMPLETED_EVENT : shared = Wx::NewEventType; our $PROCESS_COMPLETED_EVENT : shared = Wx::NewEventType; @@ -195,6 +196,7 @@ sub new { # right pane buttons $self->{btn_export_gcode} = Wx::Button->new($self, -1, "Export G-code…", wxDefaultPosition, [-1, 30], wxBU_LEFT); + $self->{btn_reslice} = Wx::Button->new($self, -1, "Slice now", wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_print} = Wx::Button->new($self, -1, "Print…", wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_send_gcode} = Wx::Button->new($self, -1, "Send to printer", wxDefaultPosition, [-1, 30], wxBU_LEFT); $self->{btn_export_stl} = Wx::Button->new($self, -1, "Export STL…", wxDefaultPosition, [-1, 30], wxBU_LEFT); @@ -212,6 +214,7 @@ sub new { export_gcode cog_go.png print arrow_up.png send_gcode arrow_up.png + reslice reslice.png export_stl brick_go.png increase add.png @@ -232,6 +235,9 @@ sub new { EVT_BUTTON($self, $self->{btn_export_gcode}, sub { $self->export_gcode; }); + EVT_BUTTON($self, $self->{btn_reslice}, sub { + $self->reslice; + }); EVT_BUTTON($self, $self->{btn_print}, sub { $self->{print_file} = $self->export_gcode(Wx::StandardPaths::Get->GetTempDir()); }); @@ -264,6 +270,7 @@ sub new { $self->{send_gcode_file} = $self->export_gcode(Wx::StandardPaths::Get->GetTempDir() . "/$filename"); }); + EVT_BUTTON($self, $self->{btn_reslice}, \&reslice); EVT_BUTTON($self, $self->{btn_export_stl}, \&export_stl); if ($self->{htoolbar}) { @@ -416,11 +423,14 @@ sub new { } my $buttons_sizer = Wx::BoxSizer->new(wxHORIZONTAL); + $self->{buttons_sizer} = $buttons_sizer; $buttons_sizer->AddStretchSpacer(1); $buttons_sizer->Add($self->{btn_export_stl}, 0, wxALIGN_RIGHT, 0); + $buttons_sizer->Add($self->{btn_reslice}, 0, wxALIGN_RIGHT, 0); $buttons_sizer->Add($self->{btn_print}, 0, wxALIGN_RIGHT, 0); $buttons_sizer->Add($self->{btn_send_gcode}, 0, wxALIGN_RIGHT, 0); $buttons_sizer->Add($self->{btn_export_gcode}, 0, wxALIGN_RIGHT, 0); + $buttons_sizer->Add($self->{btn_reslice}, 0, wxALIGN_RIGHT, 0); my $right_sizer = Wx::BoxSizer->new(wxVERTICAL); $right_sizer->Add($presets, 0, wxEXPAND | wxTOP, 10) if defined $presets; @@ -440,6 +450,8 @@ sub new { $sizer->SetSizeHints($self); $self->SetSizer($sizer); } + + $self->update_ui_from_settings(); return $self; } @@ -477,6 +489,25 @@ sub GetFrame { return &Wx::GetTopLevelParent($self); } +# Called after the Preferences dialog is closed and the program settings are saved. +# Update the UI based on the current preferences. +sub update_ui_from_settings +{ + my ($self) = @_; + if (defined($self->{btn_reslice}) && $self->{buttons_sizer}->IsShown($self->{btn_reslice}) != (! $Slic3r::GUI::Settings->{_}{background_processing})) { + $self->{buttons_sizer}->Show($self->{btn_reslice}, ! $Slic3r::GUI::Settings->{_}{background_processing}); + $self->{buttons_sizer}->Layout; + } +} + +# Update presets (Print settings, Filament, Printer) from their respective tabs. +# Called by +# Slic3r::GUI::Tab::Print::_on_presets_changed +# Slic3r::GUI::Tab::Filament::_on_presets_changed +# Slic3r::GUI::Tab::Printer::_on_presets_changed +# when the presets are loaded or the user selects another preset. +# For Print settings and Printer, synchronize the selection index with their tabs. +# For Filament, synchronize the selection index for a single extruder printer only, otherwise keep the selection. sub update_presets { my $self = shift; my ($group, $presets, $selected, $is_dirty) = @_; @@ -694,6 +725,13 @@ sub bed_centerf { return Slic3r::Pointf->new(unscale($bed_center->x), unscale($bed_center->y)); #) } +sub reslice { + # explicitly cancel a previous thread and start a new one. + my ($self) = @_; + + $self->stop_background_process; + $self->start_background_process; +} sub remove { my $self = shift; my ($obj_idx) = @_; @@ -1162,6 +1200,22 @@ sub resume_background_process { } } +sub reslice { + # explicitly cancel a previous thread and start a new one. + my ($self) = @_; + # Don't reslice if export of G-code or sending to OctoPrint is running. + if ($Slic3r::have_threads && ! defined($self->{export_gcode_output_file}) && ! defined($self->{send_gcode_file})) { + $self->stop_background_process; + $self->statusbar->SetCancelCallback(sub { + $self->stop_background_process; + $self->statusbar->SetStatusText("Slicing cancelled"); + # this updates buttons status + $self->object_list_changed; + }); + $self->start_background_process; + } +} + sub export_gcode { my ($self, $output_file) = @_; @@ -1296,6 +1350,7 @@ sub on_progress_event { $self->statusbar->SetStatusText("$message…"); } +# Called when the G-code export finishes, either successfully or with an error. # This gets called also if we don't have threads. sub on_export_completed { my ($self, $result) = @_; @@ -1312,6 +1367,7 @@ sub on_export_completed { my $send_gcode = 0; my $do_print = 0; if ($result) { + # G-code file exported successfully. if ($self->{print_file}) { $message = "File added to print queue"; $do_print = 1; @@ -1329,6 +1385,7 @@ sub on_export_completed { wxTheApp->notify($message); $self->do_print if $do_print; + # Send $self->{send_gcode_file} to OctoPrint. $self->send_gcode if $send_gcode; $self->{print_file} = undef; $self->{send_gcode_file} = undef; @@ -1354,6 +1411,8 @@ sub do_print { $self->GetFrame->select_tab(1); } +# Send $self->{send_gcode_file} to OctoPrint. +#FIXME Currently this call blocks the UI. Make it asynchronous. sub send_gcode { my ($self) = @_; @@ -1698,18 +1757,23 @@ sub object_settings_dialog { } } +# Called to update various buttons depending on whether there are any objects or +# whether background processing (export of a G-code, sending to Octoprint, forced background re-slicing) is active. sub object_list_changed { my $self = shift; + # Enable/disable buttons depending on whether there are any objects on the platter. my $have_objects = @{$self->{objects}} ? 1 : 0; my $method = $have_objects ? 'Enable' : 'Disable'; $self->{"btn_$_"}->$method - for grep $self->{"btn_$_"}, qw(reset arrange export_gcode export_stl print send_gcode); + for grep $self->{"btn_$_"}, qw(reset arrange reslice export_gcode export_stl print send_gcode); if ($self->{export_gcode_output_file} || $self->{send_gcode_file}) { + $self->{btn_reslice}->Disable; $self->{btn_export_gcode}->Disable; $self->{btn_print}->Disable; $self->{btn_send_gcode}->Disable; + $self->{btn_reslice}->Disable; } if ($self->{htoolbar}) { diff --git a/lib/Slic3r/GUI/Preferences.pm b/lib/Slic3r/GUI/Preferences.pm index 431f642d6..26a78a570 100644 --- a/lib/Slic3r/GUI/Preferences.pm +++ b/lib/Slic3r/GUI/Preferences.pm @@ -93,6 +93,9 @@ sub _accept { $self->EndModal(wxID_OK); $self->Close; # needed on Linux + + # Nothify the UI to update itself from the ini file. + wxTheApp->update_ui_from_settings; } 1; diff --git a/var/reslice.png b/var/reslice.png new file mode 100644 index 000000000..167c0eccd Binary files /dev/null and b/var/reslice.png differ