Browse Source

Removed the DLP projector dialog as it is confusing to our customers
and we doubt anybody is using it.

bubnikv 7 years ago
parent
commit
a73a1a3f09
5 changed files with 1 additions and 930 deletions
  1. 1 0
      lib/Slic3r.pm
  2. 0 1
      lib/Slic3r/GUI.pm
  3. 0 7
      lib/Slic3r/GUI/MainFrame.pm
  4. 0 922
      lib/Slic3r/GUI/Projector.pm
  5. BIN
      var/film.png

+ 1 - 0
lib/Slic3r.pm

@@ -72,6 +72,7 @@ use Slic3r::Polygon;
 use Slic3r::Polyline;
 use Slic3r::Print;
 use Slic3r::Print::Object;
+use Slic3r::Print::Simple;
 use Slic3r::Surface;
 our $build = eval "use Slic3r::Build; 1";
 use Thread::Semaphore;

+ 0 - 1
lib/Slic3r/GUI.pm

@@ -28,7 +28,6 @@ use Slic3r::GUI::Plater::LambdaObjectDialog;
 use Slic3r::GUI::Plater::OverrideSettingsPanel;
 use Slic3r::GUI::Preferences;
 use Slic3r::GUI::ProgressStatusBar;
-use Slic3r::GUI::Projector;
 use Slic3r::GUI::OptionsGroup;
 use Slic3r::GUI::OptionsGroup::Field;
 use Slic3r::GUI::SystemInfo;

+ 0 - 7
lib/Slic3r/GUI/MainFrame.pm

@@ -235,13 +235,6 @@ sub _init_menubar {
         $self->_append_menu_item($self->{plater_menu}, "Export plate as AMF...", 'Export current plate as AMF', sub {
             $plater->export_amf;
         }, undef, 'brick_go.png');
-        $self->_append_menu_item($self->{plater_menu}, "Open DLP Projector…\tCtrl+L", 'Open projector window for DLP printing', sub {
-            my $projector = Slic3r::GUI::Projector->new($self);
-            
-            # this double invocation is needed for properly hiding the MainFrame
-            $projector->Show;
-            $projector->ShowModal;
-        }, undef, 'film.png');
         
         $self->{object_menu} = $self->{plater}->object_menu;
         $self->on_plater_selection_changed(0);

+ 0 - 922
lib/Slic3r/GUI/Projector.pm

@@ -1,922 +0,0 @@
-# DLP Projector screen for the SLA (stereolitography) print process
-
-package Slic3r::GUI::Projector;
-use strict;
-use warnings;
-use Wx qw(:dialog :id :misc :sizer :systemsettings :bitmap :button :icon wxTheApp);
-use Wx::Event qw(EVT_BUTTON EVT_TEXT_ENTER EVT_SPINCTRL EVT_SLIDER);
-use base qw(Wx::Dialog Class::Accessor);
-use utf8;
-
-__PACKAGE__->mk_accessors(qw(config config2 screen controller _optgroups));
-
-sub new {
-    my ($class, $parent) = @_;
-    my $self = $class->SUPER::new($parent, -1, "Projector for DLP", wxDefaultPosition, wxDefaultSize);
-    $self->config2({
-        display                 => 0,
-        show_bed                => 1,
-        invert_y                => 0,
-        zoom                    => 100,
-        exposure_time           => 2,
-        bottom_exposure_time    => 7,
-        settle_time             => 1.5,
-        bottom_layers           => 3,
-        z_lift                  => 5,
-        z_lift_speed            => 8,
-        offset                  => [0,0],
-    });
-    
-    my $ini = eval { Slic3r::Config->read_ini("$Slic3r::GUI::datadir/DLP.ini") };
-    if ($ini) {
-        foreach my $opt_id (keys %{$ini->{_}}) {
-            my $value = $ini->{_}{$opt_id};
-            if ($opt_id eq 'offset') {
-                $value = [ split /,/, $value ];
-            }
-            $self->config2->{$opt_id} = $value;
-        }
-    }
-    
-    my $sizer = Wx::BoxSizer->new(wxVERTICAL);
-    
-    $self->config(Slic3r::Config->new_from_defaults(
-        qw(serial_port serial_speed bed_shape start_gcode end_gcode z_offset)
-    ));
-    $self->config->apply(wxTheApp->{mainframe}->config);
-    
-    my @optgroups = ();
-    {
-        push @optgroups, my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
-            parent      => $self,
-            title       => 'USB/Serial connection',
-            config      => $self->config,
-            label_width => 200,
-        );
-        $sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
-        
-        {
-            my $line = Slic3r::GUI::OptionsGroup::Line->new(
-                label => 'Serial port',
-            );
-            my $serial_port = $optgroup->get_option('serial_port');
-            $serial_port->side_widget(sub {
-                my ($parent) = @_;
-            
-                my $btn = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new($Slic3r::var->("arrow_rotate_clockwise.png"), wxBITMAP_TYPE_PNG),
-                    wxDefaultPosition, wxDefaultSize, &Wx::wxBORDER_NONE);
-                $btn->SetToolTipString("Rescan serial ports")
-                    if $btn->can('SetToolTipString');
-                EVT_BUTTON($self, $btn, sub {
-                    $optgroup->get_field('serial_port')->set_values([ wxTheApp->scan_serial_ports ]);
-                });
-            
-                return $btn;
-            });
-            my $serial_test = sub {
-                my ($parent) = @_;
-            
-                my $btn = $self->{serial_test_btn} = Wx::Button->new($parent, -1,
-                    "Test", wxDefaultPosition, wxDefaultSize, wxBU_LEFT | wxBU_EXACTFIT);
-                $btn->SetFont($Slic3r::GUI::small_font);
-                if ($Slic3r::GUI::have_button_icons) {
-                    $btn->SetBitmap(Wx::Bitmap->new($Slic3r::var->("wrench.png"), wxBITMAP_TYPE_PNG));
-                }
-            
-                EVT_BUTTON($self, $btn, sub {
-                    my $sender = Slic3r::GCode::Sender->new;
-                    my $res = $sender->connect(
-                        $self->{config}->serial_port,
-                        $self->{config}->serial_speed,
-                    );
-                    if ($res && $sender->wait_connected) {
-                        Slic3r::GUI::show_info($self, "Connection to printer works correctly.", "Success!");
-                    } else {
-                        Slic3r::GUI::show_error($self, "Connection failed.");
-                    }
-                });
-                return $btn;
-            };
-            $line->append_option($serial_port);
-            $line->append_option($optgroup->get_option('serial_speed'));
-            $line->append_widget($serial_test);
-            $optgroup->append_line($line);
-        }
-    }
-    
-    {
-        push @optgroups, my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
-            parent      => $self,
-            title       => 'G-code',
-            config      => $self->config,
-            label_width => 200,
-        );
-        $sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
-        
-        {
-            my $option = $optgroup->get_option('start_gcode');
-            $option->height(50);
-            $option->full_width(1);
-            $optgroup->append_single_option_line($option);
-        }
-        {
-            my $option = $optgroup->get_option('end_gcode');
-            $option->height(50);
-            $option->full_width(1);
-            $optgroup->append_single_option_line($option);
-        }
-    }
-    
-    my $on_change = sub {
-        my ($opt_id, $value) = @_;
-        
-        $self->config2->{$opt_id} = $value;
-        $self->screen->reposition;
-        $self->show_print_time;
-        
-        my $serialized = {};
-        foreach my $opt_id (keys %{$self->config2}) {
-            my $value = $self->config2->{$opt_id};
-            if (ref($value) eq 'ARRAY') {
-                $value = join ',', @$value;
-            }
-            $serialized->{$opt_id} = $value;
-        }
-        Slic3r::Config->write_ini(
-            "$Slic3r::GUI::datadir/DLP.ini",
-            { _ => $serialized });
-    };
-    
-    {
-        push @optgroups, my $optgroup = Slic3r::GUI::OptionsGroup->new(
-            parent      => $self,
-            title       => 'Projection',
-            on_change   => $on_change,
-            label_width => 200,
-        );
-        $sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
-        
-        {
-            my $line = Slic3r::GUI::OptionsGroup::Line->new(
-                label => 'Display',
-            );
-        
-            my @displays = 0 .. (Wx::Display::GetCount()-1);
-            $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
-                opt_id      => 'display',
-                type        => 'select',
-                label       => 'Display',
-                tooltip     => '',
-                labels      => [@displays],
-                values      => [@displays],
-                default     => $self->config2->{display},
-            ));
-            $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
-                opt_id      => 'zoom',
-                type        => 'percent',
-                label       => 'Zoom %',
-                tooltip     => '',
-                default     => $self->config2->{zoom},
-                min         => 0.1,
-                max         => 100,
-            ));
-            $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
-                opt_id      => 'offset',
-                type        => 'point',
-                label       => 'Offset',
-                tooltip     => '',
-                default     => $self->config2->{offset},
-            ));
-            $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
-                opt_id      => 'invert_y',
-                type        => 'bool',
-                label       => 'Invert Y',
-                tooltip     => '',
-                default     => $self->config2->{invert_y},
-            ));
-            $optgroup->append_line($line);
-        }
-        
-        $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
-            opt_id      => 'show_bed',
-            type        => 'bool',
-            label       => 'Show bed',
-            tooltip     => '',
-            default     => $self->config2->{show_bed},
-        ));
-    }
-    
-    {
-        push @optgroups, my $optgroup = Slic3r::GUI::OptionsGroup->new(
-            parent      => $self,
-            title       => 'Print',
-            on_change   => $on_change,
-            label_width => 200,
-        );
-        $sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
-        
-        {
-            my $line = Slic3r::GUI::OptionsGroup::Line->new(
-                label => 'Time (seconds)',
-            );
-            $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
-                opt_id      => 'bottom_exposure_time',
-                type        => 'f',
-                label       => 'Bottom exposure',
-                tooltip     => '',
-                default     => $self->config2->{bottom_exposure_time},
-            ));
-            $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
-                opt_id      => 'exposure_time',
-                type        => 'f',
-                label       => 'Exposure',
-                tooltip     => '',
-                default     => $self->config2->{exposure_time},
-            ));
-            $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
-                opt_id      => 'settle_time',
-                type        => 'f',
-                label       => 'Settle',
-                tooltip     => '',
-                default     => $self->config2->{settle_time},
-            ));
-            $optgroup->append_line($line);
-        }
-        
-        $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
-            opt_id      => 'bottom_layers',
-            type        => 'i',
-            label       => 'Bottom layers',
-            tooltip     => '',
-            default     => $self->config2->{bottom_layers},
-        ));
-        
-        {
-            my $line = Slic3r::GUI::OptionsGroup::Line->new(
-                label => 'Z Lift',
-            );
-            $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
-                opt_id      => 'z_lift',
-                type        => 'f',
-                label       => 'Distance',
-                sidetext    => 'mm',
-                tooltip     => '',
-                default     => $self->config2->{z_lift},
-            ));
-            $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
-                opt_id      => 'z_lift_speed',
-                type        => 'f',
-                label       => 'Speed',
-                sidetext    => 'mm/s',
-                tooltip     => '',
-                default     => $self->config2->{z_lift_speed},
-            ));
-            $optgroup->append_line($line);
-        }
-    }
-    
-    $self->_optgroups([@optgroups]);
-    
-    {
-        my $sizer1 = Wx::BoxSizer->new(wxHORIZONTAL);
-        $sizer->Add($sizer1, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
-        
-        {
-            my $btn = $self->{btn_manual_control} = Wx::Button->new($self, -1, 'Manual Control', wxDefaultPosition, wxDefaultSize);
-            if ($Slic3r::GUI::have_button_icons) {
-                $btn->SetBitmap(Wx::Bitmap->new($Slic3r::var->("cog.png"), wxBITMAP_TYPE_PNG));
-            }
-            $sizer1->Add($btn, 0);
-            EVT_BUTTON($self, $btn, sub {
-                my $sender = Slic3r::GCode::Sender->new;
-                my $res = $sender->connect(
-                    $self->config->serial_port,
-                    $self->config->serial_speed,
-                );
-                if (!$res || !$sender->wait_connected) {
-                    Slic3r::GUI::show_error(undef, "Connection failed. Check serial port and speed.");
-                    return;
-                }
-                my $dlg = Slic3r::GUI::Controller::ManualControlDialog->new
-                    ($self, $self->config, $sender);
-                $dlg->ShowModal;
-                $sender->disconnect;
-            });
-            
-            
-        }
-        {
-            my $btn = $self->{btn_print} = Wx::Button->new($self, -1, 'Print', wxDefaultPosition, wxDefaultSize);
-            if ($Slic3r::GUI::have_button_icons) {
-                $btn->SetBitmap(Wx::Bitmap->new($Slic3r::var->("control_play.png"), wxBITMAP_TYPE_PNG));
-            }
-            $sizer1->Add($btn, 0);
-            EVT_BUTTON($self, $btn, sub {
-                $self->controller->start_print;
-                $self->_update_buttons;
-                $self->_set_status('');
-            });
-        }
-        {
-            my $btn = $self->{btn_stop} = Wx::Button->new($self, -1, 'Stop/Black', wxDefaultPosition, wxDefaultSize);
-            if ($Slic3r::GUI::have_button_icons) {
-                $btn->SetBitmap(Wx::Bitmap->new($Slic3r::var->("control_stop.png"), wxBITMAP_TYPE_PNG));
-            }
-            $sizer1->Add($btn, 0);
-            EVT_BUTTON($self, $btn, sub {
-                $self->controller->stop_print;
-                $self->_update_buttons;
-                $self->_set_status('');
-            });
-        }
-        
-        {
-            {
-                my $text = Wx::StaticText->new($self, -1, "Layer:", wxDefaultPosition, wxDefaultSize);
-                $text->SetFont($Slic3r::GUI::small_font);
-                $sizer1->Add($text, 0, wxEXPAND | wxLEFT, 10);
-            }
-            {
-                my $spin = $self->{layers_spinctrl} = Wx::SpinCtrl->new($self, -1, 0, wxDefaultPosition, [60,-1],
-                    0, 0, 300, 0);
-                $sizer1->Add($spin, 0);
-                EVT_SPINCTRL($self, $spin, sub {
-                    my $value = $spin->GetValue;
-                    $self->{layers_slider}->SetValue($value);
-                    $self->controller->project_layer($value);
-                    $self->_update_buttons;
-                });
-            }
-            {
-                my $slider = $self->{layers_slider} = Wx::Slider->new(
-                    $self, -1,
-                    0,           # default
-                    0,           # min
-                    300,         # max
-                    wxDefaultPosition,
-                    wxDefaultSize,
-                );
-                $sizer1->Add($slider, 1);
-                EVT_SLIDER($self, $slider, sub {
-                    my $value = $slider->GetValue;
-                    $self->{layers_spinctrl}->SetValue($value);
-                    $self->controller->project_layer($value);
-                    $self->_update_buttons;
-                });
-            }
-        }
-        
-        my $sizer2 = Wx::BoxSizer->new(wxHORIZONTAL);
-        $sizer->Add($sizer2, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
-        
-        {
-            $self->{status_text} = Wx::StaticText->new($self, -1, "", wxDefaultPosition, wxDefaultSize);
-            $self->{status_text}->SetFont($Slic3r::GUI::small_font);
-            $sizer2->Add($self->{status_text}, 1 | wxEXPAND);
-        }
-    }
-    
-    {
-        my $buttons = $self->CreateStdDialogButtonSizer(wxOK);
-        EVT_BUTTON($self, wxID_CLOSE, sub {
-            $self->_close;
-        });
-        $sizer->Add($buttons, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
-    }
-    
-    $self->SetSizer($sizer);
-    $sizer->SetSizeHints($self);
-    
-    # reuse existing screen if any
-    if ($Slic3r::GUI::DLP_projection_screen) {
-        $self->screen($Slic3r::GUI::DLP_projection_screen);
-        $self->screen->config($self->config);
-        $self->screen->config2($self->config2);
-    } else {
-        $self->screen(Slic3r::GUI::Projector::Screen->new($parent, $self->config, $self->config2));
-        $Slic3r::GUI::DLP_projection_screen = $self->screen;
-    }
-    $self->screen->reposition;
-    $self->screen->Show;
-    wxTheApp->{mainframe}->Hide;
-    
-    # initialize controller
-    $self->controller(Slic3r::GUI::Projector::Controller->new(
-        config  => $self->config,
-        config2 => $self->config2,
-        screen  => $self->screen,
-        on_project_layer => sub {
-            my ($layer_num) = @_;
-            
-            $self->{layers_spinctrl}->SetValue($layer_num);
-            $self->{layers_slider}->SetValue($layer_num);
-            
-            my $duration = $self->controller->remaining_print_time;
-            $self->_set_status(sprintf "Printing layer %d/%d (z = %.2f); %d minutes and %d seconds left",
-                $layer_num, $self->controller->layer_count,
-                $self->controller->current_layer_height,
-                int($duration/60), ($duration - int($duration/60)*60));  # % truncates to integer
-        },
-        on_print_completed => sub {
-            $self->_update_buttons;
-            $self->_set_status('');
-            Wx::Bell();
-        },
-    ));
-    {
-        my $max = $self->controller->layer_count-1;
-        $self->{layers_spinctrl}->SetRange(0, $max); 
-        $self->{layers_slider}->SetRange(0, $max);
-    }
-    
-    $self->_update_buttons;
-    $self->show_print_time;
-    
-    return $self;
-}
-
-sub _update_buttons {
-    my ($self) = @_;
-    
-    my $is_printing = $self->controller->is_printing;
-    my $is_projecting = $self->controller->is_projecting;
-    $self->{btn_manual_control}->Show(!$is_printing);
-    $self->{btn_print}->Show(!$is_printing && !$is_projecting);
-    $self->{btn_stop}->Show($is_printing || $is_projecting);
-    $self->{layers_spinctrl}->Enable(!$is_printing);
-    $self->{layers_slider}->Enable(!$is_printing);
-    if ($is_printing) {
-        $_->disable for @{$self->_optgroups};
-    } else {
-        $_->enable for @{$self->_optgroups};
-    }
-    $self->Layout;
-}
-
-sub _set_status {
-    my ($self, $status) = @_;
-    $self->{status_text}->SetLabel($status // '');
-    $self->{status_text}->Wrap($self->{status_text}->GetSize->GetWidth);
-    $self->{status_text}->Refresh;
-    $self->Layout;
-}
-
-sub show_print_time {
-    my ($self) = @_;
-    
-    
-    my $duration = $self->controller->print_time;
-    $self->_set_status(sprintf "Estimated print time: %d minutes and %d seconds",
-        int($duration/60), ($duration - int($duration/60)*60));  # % truncates to integer
-}
-
-sub _close {
-    my $self = shift;
-    
-    # if projection screen is not on the same display as our dialog,
-    # ask the user whether they want to keep it open
-    my $keep_screen = 0;
-    my $display_area = Wx::Display->new($self->config2->{display})->GetGeometry;
-    if (!$display_area->Contains($self->GetScreenPosition)) {
-        my $res = Wx::MessageDialog->new($self, "Do you want to keep the black screen open?", 'Black screen', wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION)->ShowModal;
-        $keep_screen = ($res == wxID_YES);
-    }
-    
-    if ($keep_screen) {
-        $self->screen->config(undef);
-        $self->screen->config2(undef);
-        $self->screen->Refresh;
-    } else {
-        $self->screen->Destroy;
-        $self->screen(undef);
-        $Slic3r::GUI::DLP_projection_screen = undef;
-    }
-    wxTheApp->{mainframe}->Show;
-    
-    my $printer_tab = wxTheApp->{mainframe}{options_tabs}{printer};
-    $printer_tab->load_config($self->config);
-    
-    $self->EndModal(wxID_OK);
-}
-
-package Slic3r::GUI::Projector::Controller;
-use Moo;
-use Wx qw(wxTheApp :id :timer);
-use Wx::Event qw(EVT_TIMER);
-use Slic3r::Print::State ':steps';
-use Time::HiRes qw(gettimeofday tv_interval);
-
-has 'config'                => (is => 'ro', required => 1);
-has 'config2'               => (is => 'ro', required => 1);
-has 'screen'                => (is => 'ro', required => 1);
-has 'on_project_layer'      => (is => 'rw');
-has 'on_print_completed'    => (is => 'rw');
-has 'sender'                => (is => 'rw');
-has 'timer'                 => (is => 'rw');
-has 'is_printing'           => (is => 'rw', default => sub { 0 });
-has '_print'                => (is => 'rw');
-has '_layers'               => (is => 'rw');
-has '_heights'              => (is => 'rw');
-has '_layer_num'            => (is => 'rw');
-has '_timer_cb'             => (is => 'rw');
-
-sub BUILD {
-    my ($self) = @_;
-    
-    Slic3r::GUI::disable_screensaver();
-    
-    $self->set_print(wxTheApp->{mainframe}->{plater}->{print});
-    
-    # projection timer
-    my $timer_id = &Wx::NewId();
-    $self->timer(Wx::Timer->new($self->screen, $timer_id));
-    EVT_TIMER($self->screen, $timer_id, sub {
-        my $cb = $self->_timer_cb;
-        $self->_timer_cb(undef);
-        $cb->();
-    });
-}
-
-sub delay {
-    my ($self, $wait, $cb) = @_;
-    
-    $self->_timer_cb($cb);
-    $self->timer->Start($wait * 1000, wxTIMER_ONE_SHOT);
-}
-
-sub set_print {
-    my ($self, $print) = @_;
-    
-    # make sure layers were sliced
-    {
-        my $progress_dialog;
-        foreach my $object (@{$print->objects}) {
-            next if $object->step_done(STEP_SLICE);
-            $progress_dialog //= Wx::ProgressDialog->new('Slicing…', "Processing layers…", 100, undef, 0);
-            $progress_dialog->Pulse;
-            $object->slice;
-        }
-        $progress_dialog->Destroy if $progress_dialog;
-    }
-    
-    $self->_print($print);
-    
-    # sort layers by Z
-    my %layers = ();
-    foreach my $layer (map { @{$_->layers}, @{$_->support_layers} } @{$print->objects}) {
-        my $height = $layer->print_z;
-        $layers{$height} //= [];
-        push @{$layers{$height}}, $layer;
-    }
-    $self->_layers({ %layers });
-    $self->_heights([ sort { $a <=> $b } keys %layers ]);
-}
-
-sub layer_count {
-    my ($self) = @_;
-    
-    return scalar @{$self->_heights};
-}
-
-sub current_layer_height {
-    my ($self) = @_;
-    
-    return $self->_heights->[$self->_layer_num];
-}
-
-sub start_print {
-    my ($self) = @_;
-    
-    {
-        $self->sender(Slic3r::GCode::Sender->new);
-        my $res = $self->sender->connect(
-            $self->config->serial_port,
-            $self->config->serial_speed,
-        );
-        if (!$res || !$self->sender->wait_connected) {
-            Slic3r::GUI::show_error(undef, "Connection failed. Check serial port and speed.");
-            return;
-        }
-        Slic3r::debugf "connected to " . $self->config->serial_port . "\n";
-        
-        # send custom start G-code
-        $self->sender->send($_, 1) for grep !/^;/, split /\n/, $self->config->start_gcode;
-    }
-    
-    $self->is_printing(1);
-    
-    # TODO: block until the G1 command has been performed
-    # we could do this with M400 + M115 but maybe it's not portable
-    $self->delay(5, sub {
-        # start with black
-        Slic3r::debugf "starting black projection\n";
-        $self->_layer_num(-1);
-        $self->screen->project_layers(undef);
-        $self->delay($self->config2->{settle_time}, sub {
-            $self->project_next_layer;
-        });
-    });
-}
-
-sub stop_print {
-    my ($self) = @_;
-    
-    if ($self->sender) {
-        $self->sender->disconnect;
-    }
-    
-    $self->is_printing(0);
-    $self->timer->Stop;
-    $self->_timer_cb(undef);
-    $self->screen->project_layers(undef);
-}
-
-sub print_completed {
-    my ($self) = @_;
-    
-    # send custom end G-code
-    if ($self->sender) {
-        $self->sender->send($_, 1) for grep !/^;/, split /\n/, $self->config->end_gcode;
-    }
-    
-    # call this before the on_print_completed callback otherwise buttons
-    # won't be updated correctly
-    $self->stop_print;
-    
-    $self->on_print_completed->()
-        if $self->is_printing && $self->on_print_completed;
-}
-
-sub is_projecting {
-    my ($self) = @_;
-    
-    return defined $self->screen->layers;
-}
-
-sub project_layer {
-    my ($self, $layer_num) = @_;
-    
-    if (!defined $layer_num || $layer_num >= $self->layer_count) {
-        $self->screen->project_layers(undef);
-        return;
-    }
-    
-    my @layers = @{ $self->_layers->{ $self->_heights->[$layer_num] } };
-    $self->screen->project_layers([ @layers ]);
-}
-
-sub project_next_layer {
-    my ($self) = @_;
-    
-    $self->_layer_num($self->_layer_num + 1);
-    Slic3r::debugf "projecting layer %d\n", $self->_layer_num;
-    if ($self->_layer_num >= $self->layer_count) {
-        $self->print_completed;
-        return;
-    }
-    
-    $self->on_project_layer->($self->_layer_num) if $self->on_project_layer;
-    
-    if ($self->sender) {
-        my $z = $self->current_layer_height + $self->config->z_offset;
-        my $F = $self->config2->{z_lift_speed} * 60;
-        if ($self->config2->{z_lift} != 0) {
-            $self->sender->send(sprintf("G1 Z%.5f F%d", $z + $self->config2->{z_lift}, $F), 1);
-        }
-        $self->sender->send(sprintf("G1 Z%.5f F%d", $z, $F), 1);
-    }
-    
-    # TODO: we should block until G1 commands have been performed, see note below
-    $self->delay($self->config2->{settle_time}, sub {
-        $self->project_layer($self->_layer_num);
-        
-        # get exposure time
-        my $time = $self->config2->{exposure_time};
-        if ($self->_layer_num < $self->config2->{bottom_layers}) {
-            $time = $self->config2->{bottom_exposure_time};
-        }
-        
-        $self->delay($time, sub {
-            $self->screen->project_layers(undef);
-            $self->project_next_layer;
-        });
-    });
-}
-
-sub remaining_print_time {
-    my ($self) = @_;
-    
-    my $remaining_layers = @{$self->_heights} - $self->_layer_num;
-    my $remaining_bottom_layers = $self->_layer_num >= $self->config2->{bottom_layers}
-        ? 0
-        : $self->config2->{bottom_layers} - $self->_layer_num;
-    
-    return $remaining_bottom_layers * $self->config2->{bottom_exposure_time}
-        + ($remaining_layers - $remaining_bottom_layers) * $self->config2->{exposure_time}
-        + $remaining_layers * $self->config2->{settle_time};
-}
-
-sub print_time {
-    my ($self) = @_;
-    
-    return $self->config2->{bottom_layers} * $self->config2->{bottom_exposure_time}
-        + (@{$self->_heights} - $self->config2->{bottom_layers}) * $self->config2->{exposure_time}
-        + @{$self->_heights} * $self->config2->{settle_time};
-}
-
-sub DESTROY {
-    my ($self) = @_;
-    
-    $self->timer->Stop if $self->timer;
-    $self->sender->disconnect if $self->sender;
-    Slic3r::GUI::enable_screensaver();
-}
-
-package Slic3r::GUI::Projector::Screen;
-use Wx qw(:dialog :id :misc :sizer :colour :pen :brush :font wxBG_STYLE_CUSTOM);
-use Wx::Event qw(EVT_PAINT EVT_SIZE);
-use base qw(Wx::Dialog Class::Accessor);
-
-use List::Util qw(min);
-use Slic3r::Geometry qw(X Y unscale scale);
-use Slic3r::Geometry::Clipper qw(intersection_pl);
-
-__PACKAGE__->mk_accessors(qw(config config2 scaling_factor bed_origin layers));
-
-sub new {
-    my ($class, $parent, $config, $config2) = @_;
-    my $self = $class->SUPER::new($parent, -1, "Projector", wxDefaultPosition, wxDefaultSize, 0);
-    
-    $self->config($config);
-    $self->config2($config2);
-    $self->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
-    EVT_SIZE($self, \&_resize);
-    EVT_PAINT($self, \&_repaint);
-    $self->_resize;
-    
-    return $self;
-}
-
-sub reposition {
-    my ($self) = @_;
-    
-    my $display = Wx::Display->new($self->config2->{display});
-    my $area = $display->GetGeometry;
-    $self->Move($area->GetPosition);
-    # ShowFullScreen doesn't use the right screen
-    #$self->ShowFullScreen($self->config2->{fullscreen});
-    $self->SetSize($area->GetSize);
-    $self->_resize;
-    $self->Refresh;
-}
-
-sub _resize {
-    my ($self) = @_;
-    
-    return if !$self->config;
-    my ($cw, $ch) = $self->GetSizeWH;
-    
-    # get bed shape polygon
-    my $bed_polygon = Slic3r::Polygon->new_scale(@{$self->config->bed_shape});
-    my $bb = $bed_polygon->bounding_box;
-    my $size = $bb->size;
-    my $center = $bb->center;
-
-    # calculate the scaling factor needed for constraining print bed area inside preview
-    # scaling_factor is expressed in pixel / mm
-    $self->scaling_factor(min($cw / unscale($size->x), $ch / unscale($size->y))); #)
-    
-    # apply zoom to scaling factor
-    if ($self->config2->{zoom} != 0) {
-        # TODO: make sure min and max in the option config are enforced
-        $self->scaling_factor($self->scaling_factor * ($self->config2->{zoom}/100));
-    }
-    
-    # calculate the displacement needed for centering bed on screen
-    $self->bed_origin([
-        $cw/2 - (unscale($center->x) - $self->config2->{offset}->[X]) * $self->scaling_factor,
-        $ch/2 - (unscale($center->y) - $self->config2->{offset}->[Y]) * $self->scaling_factor,  #))
-    ]);
-    
-    $self->Refresh;
-}
-
-sub project_layers {
-    my ($self, $layers) = @_;
-    
-    $self->layers($layers);
-    $self->Refresh;
-}
-
-sub _repaint {
-    my ($self) = @_;
-    
-    my $dc = Wx::AutoBufferedPaintDC->new($self);
-    my ($cw, $ch) = $self->GetSizeWH;
-    return if $cw == 0;  # when canvas is not rendered yet, size is 0,0
-    
-    $dc->SetPen(Wx::Pen->new(wxBLACK, 1, wxSOLID));
-    $dc->SetBrush(Wx::Brush->new(wxBLACK, wxSOLID));
-    $dc->DrawRectangle(0, 0, $cw, $ch);
-    
-    return if !$self->config;
-    
-    # turn size into max visible coordinates
-    # TODO: or should we use ClientArea?
-    $cw--;
-    $ch--;
-    
-    # draw bed
-    if ($self->config2->{show_bed}) {
-        $dc->SetPen(Wx::Pen->new(wxRED, 2, wxSOLID));
-        $dc->SetBrush(Wx::Brush->new(wxWHITE, wxTRANSPARENT));
-        
-        # draw contour
-        my $bed_polygon = Slic3r::Polygon->new_scale(@{$self->config->bed_shape});
-        $dc->DrawPolygon($self->scaled_points_to_pixel($bed_polygon), 0, 0);
-        
-        # draw grid
-        $dc->SetPen(Wx::Pen->new(wxRED, 1, wxSOLID));
-        {
-            my $bb = $bed_polygon->bounding_box;
-            my $step = scale 10;  # 1cm grid
-            my @polylines = ();
-            for (my $x = $bb->x_min - ($bb->x_min % $step) + $step; $x < $bb->x_max; $x += $step) {
-                push @polylines, Slic3r::Polyline->new([$x, $bb->y_min], [$x, $bb->y_max]);
-            }
-            for (my $y = $bb->y_min - ($bb->y_min % $step) + $step; $y < $bb->y_max; $y += $step) {
-                push @polylines, Slic3r::Polyline->new([$bb->x_min, $y], [$bb->x_max, $y]);
-            }
-            $dc->DrawLine(map @$_, @$_)
-                for map $self->scaled_points_to_pixel([ @$_[0,-1] ]),
-                    @{intersection_pl(\@polylines, [$bed_polygon])};
-        }
-        
-        # draw axes orientation
-        $dc->SetPen(Wx::Pen->new(wxWHITE, 4, wxSOLID));
-        {
-            foreach my $endpoint ([10, 0], [0, 10]) {
-                $dc->DrawLine(
-                    map @{$self->unscaled_point_to_pixel($_)}, [0,0], $endpoint
-                );
-            }
-            
-            $dc->SetTextForeground(wxWHITE);
-            $dc->SetFont(Wx::Font->new(20, wxDEFAULT, wxNORMAL, wxNORMAL));
-            $dc->DrawText("X", @{$self->unscaled_point_to_pixel([10, -2])});
-            $dc->DrawText("Y", @{$self->unscaled_point_to_pixel([-2, 10])});
-        }
-    }
-    
-    return if !defined $self->layers;
-    
-    # get layers at this height
-    # draw layers
-    $dc->SetPen(Wx::Pen->new(wxWHITE, 1, wxSOLID));
-    foreach my $layer (@{$self->layers}) {
-        my @polygons = sort { $a->contains_point($b->first_point) ? -1 : 1 } map @$_, @{ $layer->slices };
-        foreach my $copy (@{$layer->object->_shifted_copies}) {
-            foreach my $polygon (@polygons) {
-                $polygon = $polygon->clone;
-                $polygon->translate(@$copy);
-                
-                if ($polygon->is_counter_clockwise) {
-                    $dc->SetBrush(Wx::Brush->new(wxWHITE, wxSOLID));
-                } else {
-                    $dc->SetBrush(Wx::Brush->new(wxBLACK, wxSOLID));
-                }
-                $dc->DrawPolygon($self->scaled_points_to_pixel($polygon->pp), 0, 0);
-            }
-        }
-    }
-}
-
-# convert a model coordinate into a pixel coordinate
-sub unscaled_point_to_pixel {
-    my ($self, $point) = @_;
-    
-    my $zero = $self->bed_origin;
-    my $p = [
-        $point->[X] * $self->scaling_factor + $zero->[X],
-        $point->[Y] * $self->scaling_factor + $zero->[Y],
-    ];
-    
-    if (!$self->config2->{invert_y}) {
-        my $ch = $self->GetSize->GetHeight;
-        $p->[Y] = $ch - $p->[Y];
-    }
-    
-    return $p;
-}
-
-sub scaled_points_to_pixel {
-    my ($self, $points) = @_;
-    
-    return [
-        map $self->unscaled_point_to_pixel($_),
-            map Slic3r::Pointf->new_unscale(@$_),
-            @$points
-    ];
-}
-
-1;

BIN
var/film.png