Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2018-09-14 11:25:20 +0300
committerbubnikv <bubnikv@gmail.com>2018-09-14 11:25:20 +0300
commit36faa090fcf57bdb7aceddfaa7148141165cb073 (patch)
tree7d06583b256d9003ab6c703acbf0b7a0d7fe2c6c /lib
parent9d9e4a0f7b2d9d3440c2a05bc65b2cab707d148a (diff)
Removed the Controller, Layer View, System Info, ObjectCutDialog,
removed unused Perl modules.
Diffstat (limited to 'lib')
-rw-r--r--lib/Slic3r/GUI.pm33
-rw-r--r--lib/Slic3r/GUI/2DBed.pm217
-rw-r--r--lib/Slic3r/GUI/Controller.pm190
-rw-r--r--lib/Slic3r/GUI/Controller/ManualControlDialog.pm190
-rw-r--r--lib/Slic3r/GUI/Controller/PrinterPanel.pm707
-rw-r--r--lib/Slic3r/GUI/MainFrame.pm3
-rw-r--r--lib/Slic3r/GUI/OptionsGroup.pm498
-rw-r--r--lib/Slic3r/GUI/OptionsGroup/Field.pm605
-rw-r--r--lib/Slic3r/GUI/Plater.pm70
-rw-r--r--lib/Slic3r/GUI/Plater/2D.pm372
-rw-r--r--lib/Slic3r/GUI/Plater/2DToolpaths.pm910
-rw-r--r--lib/Slic3r/GUI/Plater/LambdaObjectDialog.pm221
-rw-r--r--lib/Slic3r/GUI/Plater/ObjectCutDialog.pm284
-rw-r--r--lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm588
-rw-r--r--lib/Slic3r/GUI/Plater/ObjectSettingsDialog.pm224
-rw-r--r--lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm182
-rw-r--r--lib/Slic3r/GUI/SystemInfo.pm70
-rw-r--r--lib/Slic3r/Geometry.pm4
-rw-r--r--lib/Slic3r/Print.pm10
-rw-r--r--lib/Slic3r/SVG.pm142
20 files changed, 43 insertions, 5477 deletions
diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm
index 483fd36f9..d25f1a8af 100644
--- a/lib/Slic3r/GUI.pm
+++ b/lib/Slic3r/GUI.pm
@@ -6,25 +6,11 @@ use utf8;
use File::Basename qw(basename);
use FindBin;
use List::Util qw(first);
-use Slic3r::GUI::2DBed;
-use Slic3r::GUI::Controller;
-use Slic3r::GUI::Controller::ManualControlDialog;
-use Slic3r::GUI::Controller::PrinterPanel;
use Slic3r::GUI::MainFrame;
use Slic3r::GUI::Plater;
-use Slic3r::GUI::Plater::2D;
-use Slic3r::GUI::Plater::2DToolpaths;
use Slic3r::GUI::Plater::3D;
use Slic3r::GUI::Plater::3DPreview;
-use Slic3r::GUI::Plater::ObjectPartsPanel;
-use Slic3r::GUI::Plater::ObjectCutDialog;
-use Slic3r::GUI::Plater::ObjectSettingsDialog;
-use Slic3r::GUI::Plater::LambdaObjectDialog;
-use Slic3r::GUI::Plater::OverrideSettingsPanel;
use Slic3r::GUI::ProgressStatusBar;
-use Slic3r::GUI::OptionsGroup;
-use Slic3r::GUI::OptionsGroup::Field;
-use Slic3r::GUI::SystemInfo;
use Wx::Locale gettext => 'L';
@@ -226,16 +212,15 @@ sub system_info {
$opengl_info = Slic3r::GUI::_3DScene::get_gl_info(1, 1);
$opengl_info_txt = Slic3r::GUI::_3DScene::get_gl_info(0, 1);
}
- my $about = Slic3r::GUI::SystemInfo->new(
- parent => undef,
- slic3r_info => $slic3r_info,
-# copyright_info => $copyright_info,
- system_info => $system_info,
- opengl_info => $opengl_info,
- text_info => Slic3r::slic3r_info . Slic3r::system_info . $opengl_info_txt,
- );
- $about->ShowModal;
- $about->Destroy;
+# my $about = Slic3r::GUI::SystemInfo->new(
+# parent => undef,
+# slic3r_info => $slic3r_info,
+# system_info => $system_info,
+# opengl_info => $opengl_info,
+# text_info => Slic3r::slic3r_info . Slic3r::system_info . $opengl_info_txt,
+# );
+# $about->ShowModal;
+# $about->Destroy;
}
# static method accepting a wxWindow object as first parameter
diff --git a/lib/Slic3r/GUI/2DBed.pm b/lib/Slic3r/GUI/2DBed.pm
deleted file mode 100644
index 0891a4836..000000000
--- a/lib/Slic3r/GUI/2DBed.pm
+++ /dev/null
@@ -1,217 +0,0 @@
-# Bed shape dialog
-# still used by the Slic3r::GUI::Controller::ManualControlDialog Perl module.
-
-package Slic3r::GUI::2DBed;
-use strict;
-use warnings;
-
-use List::Util qw(min max);
-use Slic3r::Geometry qw(X Y unscale deg2rad);
-use Slic3r::Geometry::Clipper qw(intersection_pl);
-use Wx qw(:misc :pen :brush :font :systemsettings wxTAB_TRAVERSAL wxSOLID);
-use Wx::Event qw(EVT_PAINT EVT_ERASE_BACKGROUND EVT_MOUSE_EVENTS EVT_SIZE);
-use base qw(Wx::Panel Class::Accessor);
-
-__PACKAGE__->mk_accessors(qw(bed_shape interactive pos _scale_factor _shift on_move _painted));
-
-sub new {
- my ($class, $parent, $bed_shape) = @_;
-
- my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, [250,-1], wxTAB_TRAVERSAL);
- $self->{user_drawn_background} = $^O ne 'darwin';
- $self->bed_shape($bed_shape // []);
- EVT_PAINT($self, \&_repaint);
- EVT_ERASE_BACKGROUND($self, sub {}) if $self->{user_drawn_background};
- EVT_MOUSE_EVENTS($self, \&_mouse_event);
- EVT_SIZE($self, sub { $self->Refresh; });
- return $self;
-}
-
-sub _repaint {
- my ($self, $event) = @_;
-
- 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
-
- if ($self->{user_drawn_background}) {
- # On all systems the AutoBufferedPaintDC() achieves double buffering.
- # On MacOS the background is erased, on Windows the background is not erased
- # and on Linux/GTK the background is erased to gray color.
- # Fill DC with the background on Windows & Linux/GTK.
- my $color = Wx::SystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT);
- $dc->SetPen(Wx::Pen->new($color, 1, wxSOLID));
- $dc->SetBrush(Wx::Brush->new($color, wxSOLID));
- my $rect = $self->GetUpdateRegion()->GetBox();
- $dc->DrawRectangle($rect->GetLeft(), $rect->GetTop(), $rect->GetWidth(), $rect->GetHeight());
- }
-
- # turn $cw and $ch from sizes to max coordinates
- $cw--;
- $ch--;
-
- my $cbb = Slic3r::Geometry::BoundingBoxf->new_from_points([
- Slic3r::Pointf->new(0, 0),
- Slic3r::Pointf->new($cw, $ch),
- ]);
-
- # leave space for origin point
- $cbb->set_x_min($cbb->x_min + 4);
- $cbb->set_x_max($cbb->x_max - 4);
- $cbb->set_y_max($cbb->y_max - 4);
-
- # leave space for origin label
- $cbb->set_y_max($cbb->y_max - 13);
-
- # read new size
- ($cw, $ch) = @{$cbb->size};
- my $ccenter = $cbb->center;
-
- # get bounding box of bed shape in G-code coordinates
- my $bed_shape = $self->bed_shape;
- my $bed_polygon = Slic3r::Polygon->new_scale(@$bed_shape);
- my $bb = Slic3r::Geometry::BoundingBoxf->new_from_points($bed_shape);
- $bb->merge_point(Slic3r::Pointf->new(0,0)); # origin needs to be in the visible area
- my ($bw, $bh) = @{$bb->size};
- my $bcenter = $bb->center;
-
- # calculate the scaling factor for fitting bed shape in canvas area
- my $sfactor = min($cw/$bw, $ch/$bh);
- my $shift = Slic3r::Pointf->new(
- $ccenter->x - $bcenter->x * $sfactor,
- $ccenter->y - $bcenter->y * $sfactor, #-
- );
- $self->_scale_factor($sfactor);
- $self->_shift(Slic3r::Pointf->new(
- $shift->x + $cbb->x_min,
- $shift->y - ($cbb->y_max-$self->GetSize->GetHeight), #++
- ));
-
- # draw bed fill
- {
- $dc->SetPen(Wx::Pen->new(Wx::Colour->new(0,0,0), 1, wxSOLID));
- $dc->SetBrush(Wx::Brush->new(Wx::Colour->new(255,255,255), wxSOLID));
- $dc->DrawPolygon([ map $self->to_pixels($_), @$bed_shape ], 0, 0);
- }
-
- # draw grid
- {
- my $step = 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_scale([$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_scale([$bb->x_min, $y], [$bb->x_max, $y]);
- }
- @polylines = @{intersection_pl(\@polylines, [$bed_polygon])};
-
- $dc->SetPen(Wx::Pen->new(Wx::Colour->new(230,230,230), 1, wxSOLID));
- $dc->DrawLine(map @{$self->to_pixels([map unscale($_), @$_])}, @$_[0,-1]) for @polylines;
- }
-
- # draw bed contour
- {
- $dc->SetPen(Wx::Pen->new(Wx::Colour->new(0,0,0), 1, wxSOLID));
- $dc->SetBrush(Wx::Brush->new(Wx::Colour->new(255,255,255), wxTRANSPARENT));
- $dc->DrawPolygon([ map $self->to_pixels($_), @$bed_shape ], 0, 0);
- }
-
- my $origin_px = $self->to_pixels(Slic3r::Pointf->new(0,0));
-
- # draw axes
- {
- my $axes_len = 50;
- my $arrow_len = 6;
- my $arrow_angle = deg2rad(45);
- $dc->SetPen(Wx::Pen->new(Wx::Colour->new(255,0,0), 2, wxSOLID)); # red
- my $x_end = Slic3r::Pointf->new($origin_px->[X] + $axes_len, $origin_px->[Y]);
- $dc->DrawLine(@$origin_px, @$x_end);
- foreach my $angle (-$arrow_angle, +$arrow_angle) {
- my $end = $x_end->clone;
- $end->translate(-$arrow_len, 0);
- $end->rotate($angle, $x_end);
- $dc->DrawLine(@$x_end, @$end);
- }
-
- $dc->SetPen(Wx::Pen->new(Wx::Colour->new(0,255,0), 2, wxSOLID)); # green
- my $y_end = Slic3r::Pointf->new($origin_px->[X], $origin_px->[Y] - $axes_len);
- $dc->DrawLine(@$origin_px, @$y_end);
- foreach my $angle (-$arrow_angle, +$arrow_angle) {
- my $end = $y_end->clone;
- $end->translate(0, +$arrow_len);
- $end->rotate($angle, $y_end);
- $dc->DrawLine(@$y_end, @$end);
- }
- }
-
- # draw origin
- {
- $dc->SetPen(Wx::Pen->new(Wx::Colour->new(0,0,0), 1, wxSOLID));
- $dc->SetBrush(Wx::Brush->new(Wx::Colour->new(0,0,0), wxSOLID));
- $dc->DrawCircle(@$origin_px, 3);
-
- $dc->SetTextForeground(Wx::Colour->new(0,0,0));
- $dc->SetFont(Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL));
- $dc->DrawText("(0,0)", $origin_px->[X] + 1, $origin_px->[Y] + 2);
- }
-
- # draw current position
- if (defined $self->pos) {
- my $pos_px = $self->to_pixels($self->pos);
- $dc->SetPen(Wx::Pen->new(Wx::Colour->new(200,0,0), 2, wxSOLID));
- $dc->SetBrush(Wx::Brush->new(Wx::Colour->new(200,0,0), wxTRANSPARENT));
- $dc->DrawCircle(@$pos_px, 5);
-
- $dc->DrawLine($pos_px->[X]-15, $pos_px->[Y], $pos_px->[X]+15, $pos_px->[Y]);
- $dc->DrawLine($pos_px->[X], $pos_px->[Y]-15, $pos_px->[X], $pos_px->[Y]+15);
- }
-
- $self->_painted(1);
-}
-
-sub _mouse_event {
- my ($self, $event) = @_;
-
- return if !$self->interactive;
- return if !$self->_painted;
-
- my $pos = $event->GetPosition;
- my $point = $self->to_units([ $pos->x, $pos->y ]); #]]
- if ($event->LeftDown || $event->Dragging) {
- $self->on_move->($point) if $self->on_move;
- $self->Refresh;
- }
-}
-
-# convert G-code coordinates into pixels
-sub to_pixels {
- my ($self, $point) = @_;
-
- my $p = Slic3r::Pointf->new(@$point);
- $p->scale($self->_scale_factor);
- $p->translate(@{$self->_shift});
- return [$p->x, $self->GetSize->GetHeight - $p->y]; #]]
-}
-
-# convert pixels into G-code coordinates
-sub to_units {
- my ($self, $point) = @_;
-
- my $p = Slic3r::Pointf->new(
- $point->[X],
- $self->GetSize->GetHeight - $point->[Y],
- );
- $p->translate(@{$self->_shift->negative});
- $p->scale(1/$self->_scale_factor);
- return $p;
-}
-
-sub set_pos {
- my ($self, $pos) = @_;
-
- $self->pos($pos);
- $self->Refresh;
-}
-
-1;
diff --git a/lib/Slic3r/GUI/Controller.pm b/lib/Slic3r/GUI/Controller.pm
deleted file mode 100644
index f7d90c796..000000000
--- a/lib/Slic3r/GUI/Controller.pm
+++ /dev/null
@@ -1,190 +0,0 @@
-# The "Controller" tab to control the printer using serial / USB.
-# This feature is rarely used. Much more often, the firmware reads the G-codes from a SD card.
-# May there be multiple subtabs per each printer connected?
-
-package Slic3r::GUI::Controller;
-use strict;
-use warnings;
-use utf8;
-
-use Wx qw(wxTheApp :frame :id :misc :sizer :bitmap :button :icon :dialog wxBORDER_NONE);
-use Wx::Event qw(EVT_CLOSE EVT_LEFT_DOWN EVT_MENU);
-use base qw(Wx::ScrolledWindow Class::Accessor);
-use List::Util qw(first);
-
-__PACKAGE__->mk_accessors(qw(_selected_printer_preset));
-
-our @ConfigOptions = qw(bed_shape serial_port serial_speed);
-
-sub new {
- my ($class, $parent) = @_;
- my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, [600,350]);
-
- $self->SetScrollbars(0, 1, 0, 1);
- $self->{sizer} = my $sizer = Wx::BoxSizer->new(wxVERTICAL);
-
- # warning to show when there are no printers configured
- {
- $self->{text_no_printers} = Wx::StaticText->new($self, -1,
- "No printers were configured for USB/serial control.",
- wxDefaultPosition, wxDefaultSize);
- $self->{sizer}->Add($self->{text_no_printers}, 0, wxTOP | wxLEFT, 30);
- }
-
- # button for adding new printer panels
- {
- my $btn = $self->{btn_add} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new(Slic3r::var("add.png"), wxBITMAP_TYPE_PNG),
- wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
- $btn->SetToolTipString("Add printer…")
- if $btn->can('SetToolTipString');
-
- EVT_LEFT_DOWN($btn, sub {
- my $menu = Wx::Menu->new;
- my @panels = $self->print_panels;
- # remove printers that already exist
- # update configs of currently loaded print panels
- foreach my $preset (@{wxTheApp->{preset_bundle}->printer}) {
- my $preset_name = $preset->name;
- next if ! $preset->config->serial_port ||
- defined first { defined $_ && $_->printer_name eq $preset_name } @panels;
- my $myconfig = $preset->config->clone_only(\@ConfigOptions);
- my $id = &Wx::NewId();
- $menu->Append($id, $preset_name);
- EVT_MENU($menu, $id, sub {
- $self->add_printer($preset_name, $myconfig);
- });
- }
- $self->PopupMenu($menu, $btn->GetPosition);
- $menu->Destroy;
- });
- $self->{sizer}->Add($btn, 0, wxTOP | wxLEFT, 10);
- }
-
- $self->SetSizer($sizer);
- $self->SetMinSize($self->GetSize);
- #$sizer->SetSizeHints($self);
-
- EVT_CLOSE($self, sub {
- my (undef, $event) = @_;
-
- if ($event->CanVeto) {
- foreach my $panel ($self->print_panels) {
- if ($panel->printing) {
- my $confirm = Wx::MessageDialog->new(
- $self, "Printer '" . $panel->printer_name . "' is printing.\n\nDo you want to stop printing?",
- 'Unfinished Print', wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION,
- );
- if ($confirm->ShowModal == wxID_NO) {
- $event->Veto;
- return;
- }
- }
- }
- }
- foreach my $panel ($self->print_panels) {
- $panel->disconnect;
- }
-
- $event->Skip;
- });
-
- $self->Layout;
-
- return $self;
-}
-
-sub OnActivate {
- my ($self) = @_;
-
- # get all available presets
- my %presets = map { $_->name => $_->config->clone_only(\@ConfigOptions) }
- grep { $_->config->serial_port } @{wxTheApp->{preset_bundle}->printer};
-
- # decide which ones we want to keep
- my %active = ();
-
- # keep the ones that are currently connected or have jobs in queue
- $active{$_} = 1 for map $_->printer_name,
- grep { $_->is_connected || @{$_->jobs} > 0 }
- $self->print_panels;
-
- if (%presets) {
- # if there are no active panels, use sensible defaults
- if (!%active && keys %presets <= 2) {
- # if only one or two presets exist, load them
- $active{$_} = 1 for keys %presets;
- }
- if (!%active) {
- # enable printers whose port is available
- my %ports = map { $_ => 1 } Slic3r::GUI::scan_serial_ports;
- $active{$_} = 1
- for grep exists $ports{$presets{$_}->serial_port}, keys %presets;
- }
- if (!%active && $self->_selected_printer_preset) {
- # enable currently selected printer if it is configured
- $active{$self->_selected_printer_preset} = 1
- if $presets{$self->_selected_printer_preset};
- }
- }
-
- # apply changes
- for my $panel ($self->print_panels) {
- next if $active{$panel->printer_name};
-
- $self->{sizer}->DetachWindow($panel);
- $panel->Destroy;
- }
- $self->add_printer($_, $presets{$_}) for sort keys %active;
-
- # show/hide the warning about no printers
- $self->{text_no_printers}->Show(!%presets);
-
- # show/hide the Add button
- $self->{btn_add}->Show(keys %presets != keys %active);
-
- $self->Layout;
-
- # we need this in order to trigger the OnSize event of wxScrolledWindow which
- # recalculates the virtual size
- Wx::GetTopLevelParent($self)->SendSizeEvent;
-}
-
-sub add_printer {
- my ($self, $printer_name, $config) = @_;
-
- # check that printer doesn't exist already
- foreach my $panel ($self->print_panels) {
- if ($panel->printer_name eq $printer_name) {
- return $panel;
- }
- }
-
- my $printer_panel = Slic3r::GUI::Controller::PrinterPanel->new($self, $printer_name, $config);
- $self->{sizer}->Prepend($printer_panel, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 10);
- $self->Layout;
-
- return $printer_panel;
-}
-
-sub print_panels {
- my ($self) = @_;
- return grep $_->isa('Slic3r::GUI::Controller::PrinterPanel'),
- map $_->GetWindow, $self->{sizer}->GetChildren;
-}
-
-# Called by Slic3r::GUI::Tab::Printer::_on_presets_changed
-# when the presets are loaded or the user selects another preset.
-sub update_presets {
- my ($self, $presets) = @_;
- # update configs of currently loaded print panels
- my @presets = @$presets;
- foreach my $panel ($self->print_panels) {
- my $preset = $presets->find_preset($panel->printer_name, 0);
- $panel->config($preset->config->clone_only(\@ConfigOptions))
- if defined $preset;
- }
-
- $self->_selected_printer_preset($presets->get_selected_preset->name);
-}
-
-1;
diff --git a/lib/Slic3r/GUI/Controller/ManualControlDialog.pm b/lib/Slic3r/GUI/Controller/ManualControlDialog.pm
deleted file mode 100644
index de0565255..000000000
--- a/lib/Slic3r/GUI/Controller/ManualControlDialog.pm
+++ /dev/null
@@ -1,190 +0,0 @@
-# A printer "Controller" -> "ManualControlDialog" subtab, opened per 3D printer connected?
-
-package Slic3r::GUI::Controller::ManualControlDialog;
-use strict;
-use warnings;
-use utf8;
-
-use Wx qw(:dialog :id :misc :sizer :choicebook :button :bitmap
- wxBORDER_NONE wxTAB_TRAVERSAL);
-use Wx::Event qw(EVT_CLOSE EVT_BUTTON);
-use base qw(Wx::Dialog Class::Accessor);
-
-__PACKAGE__->mk_accessors(qw(sender config2 x_homed y_homed));
-
-sub new {
- my ($class, $parent, $config, $sender) = @_;
-
- my $self = $class->SUPER::new($parent, -1, "Manual Control", wxDefaultPosition,
- [500,380], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
- $self->sender($sender);
-
- $self->config2({
- xy_travel_speed => 130,
- z_travel_speed => 10,
- });
-
- my $bed_sizer = Wx::FlexGridSizer->new(2, 3, 1, 1);
- $bed_sizer->AddGrowableCol(1, 1);
- $bed_sizer->AddGrowableRow(0, 1);
-
- my $move_button = sub {
- my ($sizer, $label, $icon, $bold, $pos, $handler) = @_;
-
- my $btn = Wx::Button->new($self, -1, $label, wxDefaultPosition, wxDefaultSize,
- wxBU_LEFT | wxBU_EXACTFIT);
- $btn->SetFont($bold ? $Slic3r::GUI::small_bold_font : $Slic3r::GUI::small_font);
- $btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("$icon.png"), wxBITMAP_TYPE_PNG));
- $btn->SetBitmapPosition($pos);
- EVT_BUTTON($self, $btn, $handler);
- $sizer->Add($btn, 1, wxEXPAND | wxALL, 0);
- };
-
- # Y buttons
- {
- my $sizer = Wx::BoxSizer->new(wxVERTICAL);
- for my $d (qw(+10 +1 +0.1)) {
- $move_button->($sizer, $d, 'arrow_up', 0, wxLEFT, sub { $self->rel_move('Y', $d) });
- }
- $move_button->($sizer, 'Y', 'house', 1, wxLEFT, sub { $self->home('Y') });
- for my $d (qw(-0.1 -1 -10)) {
- $move_button->($sizer, $d, 'arrow_down', 0, wxLEFT, sub { $self->rel_move('Y', $d) });
- };
- $bed_sizer->Add($sizer, 1, wxEXPAND, 0);
- }
-
- # Bed canvas
- {
- my $bed_shape = $config->bed_shape;
- $self->{canvas} = my $canvas = Slic3r::GUI::2DBed->new($self, $bed_shape);
- $canvas->interactive(1);
- $canvas->on_move(sub {
- my ($pos) = @_;
-
- if (!($self->x_homed && $self->y_homed)) {
- Slic3r::GUI::show_error($self, "Please home both X and Y before moving.");
- return ;
- }
-
- # delete any pending commands to get a smoother movement
- $self->sender->purge_queue(1);
- $self->abs_xy_move($pos);
- });
- $bed_sizer->Add($canvas, 0, wxEXPAND | wxRIGHT, 3);
- }
-
- # Z buttons
- {
- my $sizer = Wx::BoxSizer->new(wxVERTICAL);
- for my $d (qw(+10 +1 +0.1)) {
- $move_button->($sizer, $d, 'arrow_up', 0, wxLEFT, sub { $self->rel_move('Z', $d) });
- }
- $move_button->($sizer, 'Z', 'house', 1, wxLEFT, sub { $self->home('Z') });
- for my $d (qw(-0.1 -1 -10)) {
- $move_button->($sizer, $d, 'arrow_down', 0, wxLEFT, sub { $self->rel_move('Z', $d) });
- };
- $bed_sizer->Add($sizer, 1, wxEXPAND, 0);
- }
-
- # XYZ home button
- $move_button->($bed_sizer, 'XYZ', 'house', 1, wxTOP, sub { $self->home(undef) });
-
- # X buttons
- {
- my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
- for my $d (qw(-10 -1 -0.1)) {
- $move_button->($sizer, $d, 'arrow_left', 0, wxTOP, sub { $self->rel_move('X', $d) });
- }
- $move_button->($sizer, 'X', 'house', 1, wxTOP, sub { $self->home('X') });
- for my $d (qw(+0.1 +1 +10)) {
- $move_button->($sizer, $d, 'arrow_right', 0, wxTOP, sub { $self->rel_move('X', $d) });
- }
- $bed_sizer->Add($sizer, 1, wxEXPAND, 0);
- }
-
- my $optgroup = Slic3r::GUI::OptionsGroup->new(
- parent => $self,
- title => 'Settings',
- on_change => sub {
- my ($opt_id, $value) = @_;
- $self->config2->{$opt_id} = $value;
- },
- );
- {
- my $line = Slic3r::GUI::OptionsGroup::Line->new(
- label => 'Speed (mm/s)',
- );
- $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 'xy_travel_speed',
- type => 'f',
- label => 'X/Y',
- tooltip => '',
- default => $self->config2->{xy_travel_speed},
- ));
- $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 'z_travel_speed',
- type => 'f',
- label => 'Z',
- tooltip => '',
- default => $self->config2->{z_travel_speed},
- ));
- $optgroup->append_line($line);
- }
-
- my $main_sizer = Wx::BoxSizer->new(wxVERTICAL);
- $main_sizer->Add($bed_sizer, 1, wxEXPAND | wxALL, 10);
- $main_sizer->Add($optgroup->sizer, 0, wxEXPAND | wxALL, 10);
- #$main_sizer->Add($self->CreateButtonSizer(wxCLOSE), 0, wxEXPAND);
- #EVT_BUTTON($self, wxID_CLOSE, sub { $self->Close });
-
- $self->SetSizer($main_sizer);
- $self->SetMinSize($self->GetSize);
- #$main_sizer->SetSizeHints($self);
- $self->Layout;
-
- # needed to actually free memory
- EVT_CLOSE($self, sub {
- $self->EndModal(wxID_OK);
- $self->Destroy;
- });
-
- return $self;
-}
-
-sub abs_xy_move {
- my ($self, $pos) = @_;
-
- $self->sender->send("G90", 1); # set absolute positioning
- $self->sender->send(sprintf("G1 X%.1f Y%.1f F%d", @$pos, $self->config2->{xy_travel_speed}*60), 1);
- $self->{canvas}->set_pos($pos);
-}
-
-sub rel_move {
- my ($self, $axis, $distance) = @_;
-
- my $speed = ($axis eq 'Z') ? $self->config2->{z_travel_speed} : $self->config2->{xy_travel_speed};
- $self->sender->send("G91", 1); # set relative positioning
- $self->sender->send(sprintf("G1 %s%.1f F%d", $axis, $distance, $speed*60), 1);
- $self->sender->send("G90", 1); # set absolute positioning
-
- if (my $pos = $self->{canvas}->pos) {
- if ($axis eq 'X') {
- $pos->translate($distance, 0);
- } elsif ($axis eq 'Y') {
- $pos->translate(0, $distance);
- }
- $self->{canvas}->set_pos($pos);
- }
-}
-
-sub home {
- my ($self, $axis) = @_;
-
- $axis //= '';
- $self->sender->send(sprintf("G28 %s", $axis), 1);
- $self->{canvas}->set_pos(undef);
- $self->x_homed(1) if $axis eq 'X';
- $self->y_homed(1) if $axis eq 'Y';
-}
-
-1;
diff --git a/lib/Slic3r/GUI/Controller/PrinterPanel.pm b/lib/Slic3r/GUI/Controller/PrinterPanel.pm
deleted file mode 100644
index 794ea4e4e..000000000
--- a/lib/Slic3r/GUI/Controller/PrinterPanel.pm
+++ /dev/null
@@ -1,707 +0,0 @@
-package Slic3r::GUI::Controller::PrinterPanel;
-use strict;
-use warnings;
-use utf8;
-
-use Wx qw(wxTheApp :panel :id :misc :sizer :button :bitmap :window :gauge :timer
- :textctrl :font :systemsettings);
-use Wx::Event qw(EVT_BUTTON EVT_MOUSEWHEEL EVT_TIMER EVT_SCROLLWIN);
-use base qw(Wx::Panel Class::Accessor);
-
-__PACKAGE__->mk_accessors(qw(printer_name config sender jobs
- printing status_timer temp_timer));
-
-use constant CONNECTION_TIMEOUT => 3; # seconds
-use constant STATUS_TIMER_INTERVAL => 1000; # milliseconds
-use constant TEMP_TIMER_INTERVAL => 5000; # milliseconds
-
-sub new {
- my ($class, $parent, $printer_name, $config) = @_;
- my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, [500, 250]);
-
- $self->printer_name($printer_name || 'Printer');
- $self->config($config);
- $self->jobs([]);
-
- # set up the timer that polls for updates
- {
- my $timer_id = &Wx::NewId();
- $self->status_timer(Wx::Timer->new($self, $timer_id));
- EVT_TIMER($self, $timer_id, sub {
- my ($self, $event) = @_;
-
- if ($self->printing) {
- my $queue_size = $self->sender->queue_size;
- $self->{gauge}->SetValue($self->{gauge}->GetRange - $queue_size);
- if ($queue_size == 0) {
- $self->print_completed;
- }
- }
- $self->{log_textctrl}->AppendText("$_\n") for @{$self->sender->purge_log};
- {
- my $temp = $self->sender->getT;
- if ($temp eq '') {
- $self->{temp_panel}->Hide;
- } else {
- if (!$self->{temp_panel}->IsShown) {
- $self->{temp_panel}->Show;
- $self->Layout;
- }
- $self->{temp_text}->SetLabel($temp . "°C");
-
- $temp = $self->sender->getB;
- if ($temp eq '') {
- $self->{bed_temp_text}->SetLabel('n.a.');
- } else {
- $self->{bed_temp_text}->SetLabel($temp . "°C");
- }
- }
- }
- });
- }
-
- # set up the timer that sends temperature requests
- # (responses are handled by status_timer)
- {
- my $timer_id = &Wx::NewId();
- $self->temp_timer(Wx::Timer->new($self, $timer_id));
- EVT_TIMER($self, $timer_id, sub {
- my ($self, $event) = @_;
- $self->sender->send("M105", 1); # send it through priority queue
- });
- }
-
- my $box = Wx::StaticBox->new($self, -1, "");
- my $sizer = Wx::StaticBoxSizer->new($box, wxHORIZONTAL);
- my $left_sizer = Wx::BoxSizer->new(wxVERTICAL);
-
- # printer name
- {
- my $text = Wx::StaticText->new($box, -1, $self->printer_name, wxDefaultPosition, [220,-1]);
- my $font = $text->GetFont;
- $font->SetPointSize(20);
- $text->SetFont($font);
- $left_sizer->Add($text, 0, wxEXPAND, 0);
- }
-
- # connection info
- {
- my $conn_sizer = Wx::FlexGridSizer->new(2, 2, 1, 0);
- $conn_sizer->SetFlexibleDirection(wxHORIZONTAL);
- $conn_sizer->AddGrowableCol(1, 1);
- $left_sizer->Add($conn_sizer, 0, wxEXPAND | wxTOP, 5);
- {
- my $text = Wx::StaticText->new($box, -1, "Port:", wxDefaultPosition, wxDefaultSize);
- $text->SetFont($Slic3r::GUI::small_font);
- $conn_sizer->Add($text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
- }
- my $serial_port_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
- {
- $self->{serial_port_combobox} = Wx::ComboBox->new($box, -1, $config->serial_port, wxDefaultPosition, wxDefaultSize, []);
- $self->{serial_port_combobox}->SetFont($Slic3r::GUI::small_font);
- $self->update_serial_ports;
- $serial_port_sizer->Add($self->{serial_port_combobox}, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1);
- }
- {
- $self->{btn_rescan_serial} = my $btn = Wx::BitmapButton->new($box, -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');
- $serial_port_sizer->Add($btn, 0, wxALIGN_CENTER_VERTICAL, 0);
- EVT_BUTTON($self, $btn, sub { $self->update_serial_ports });
- }
- $conn_sizer->Add($serial_port_sizer, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
-
- {
- my $text = Wx::StaticText->new($box, -1, "Speed:", wxDefaultPosition, wxDefaultSize);
- $text->SetFont($Slic3r::GUI::small_font);
- $conn_sizer->Add($text, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
- }
- my $serial_speed_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
- {
- $self->{serial_speed_combobox} = Wx::ComboBox->new($box, -1, $config->serial_speed, wxDefaultPosition, wxDefaultSize,
- ["115200", "250000"]);
- $self->{serial_speed_combobox}->SetFont($Slic3r::GUI::small_font);
- $serial_speed_sizer->Add($self->{serial_speed_combobox}, 0, wxALIGN_CENTER_VERTICAL, 0);
- }
- {
- $self->{btn_disconnect} = my $btn = Wx::Button->new($box, -1, "Disconnect", wxDefaultPosition, wxDefaultSize);
- $btn->SetFont($Slic3r::GUI::small_font);
- $btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("delete.png"), wxBITMAP_TYPE_PNG));
- $serial_speed_sizer->Add($btn, 0, wxLEFT, 5);
- EVT_BUTTON($self, $btn, \&disconnect);
- }
- $conn_sizer->Add($serial_speed_sizer, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
- }
-
- # buttons
- {
- $self->{btn_connect} = my $btn = Wx::Button->new($box, -1, "Connect to printer", wxDefaultPosition, [-1, 40]);
- my $font = $btn->GetFont;
- $font->SetPointSize($font->GetPointSize + 2);
- $btn->SetFont($font);
- $btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("arrow_up.png"), wxBITMAP_TYPE_PNG));
- $left_sizer->Add($btn, 0, wxTOP, 15);
- EVT_BUTTON($self, $btn, \&connect);
- }
-
- # print progress bar
- {
- my $gauge = $self->{gauge} = Wx::Gauge->new($self, wxGA_HORIZONTAL, 100, wxDefaultPosition, wxDefaultSize);
- $left_sizer->Add($self->{gauge}, 0, wxEXPAND | wxTOP, 15);
- $gauge->Hide;
- }
-
- # status
- $self->{status_text} = Wx::StaticText->new($box, -1, "", wxDefaultPosition, [200,-1]);
- $left_sizer->Add($self->{status_text}, 1, wxEXPAND | wxTOP, 15);
-
- # manual control
- {
- $self->{btn_manual_control} = my $btn = Wx::Button->new($box, -1, "Manual control", wxDefaultPosition, wxDefaultSize);
- $btn->SetFont($Slic3r::GUI::small_font);
- $btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("cog.png"), wxBITMAP_TYPE_PNG));
- $btn->Hide;
- $left_sizer->Add($btn, 0, wxTOP, 15);
- EVT_BUTTON($self, $btn, sub {
- my $dlg = Slic3r::GUI::Controller::ManualControlDialog->new
- ($self, $self->config, $self->sender);
- $dlg->ShowModal;
- });
- }
-
- # temperature
- {
- my $temp_panel = $self->{temp_panel} = Wx::Panel->new($box, -1);
- my $temp_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
-
- my $temp_font = Wx::Font->new($Slic3r::GUI::small_font);
- $temp_font->SetWeight(wxFONTWEIGHT_BOLD);
- {
- my $text = Wx::StaticText->new($temp_panel, -1, "Temperature:", wxDefaultPosition, wxDefaultSize);
- $text->SetFont($Slic3r::GUI::small_font);
- $temp_sizer->Add($text, 0, wxALIGN_CENTER_VERTICAL);
-
- $self->{temp_text} = Wx::StaticText->new($temp_panel, -1, "", wxDefaultPosition, wxDefaultSize);
- $self->{temp_text}->SetFont($temp_font);
- $self->{temp_text}->SetForegroundColour(Wx::wxRED);
- $temp_sizer->Add($self->{temp_text}, 1, wxALIGN_CENTER_VERTICAL);
- }
- {
- my $text = Wx::StaticText->new($temp_panel, -1, "Bed:", wxDefaultPosition, wxDefaultSize);
- $text->SetFont($Slic3r::GUI::small_font);
- $temp_sizer->Add($text, 0, wxALIGN_CENTER_VERTICAL);
-
- $self->{bed_temp_text} = Wx::StaticText->new($temp_panel, -1, "", wxDefaultPosition, wxDefaultSize);
- $self->{bed_temp_text}->SetFont($temp_font);
- $self->{bed_temp_text}->SetForegroundColour(Wx::wxRED);
- $temp_sizer->Add($self->{bed_temp_text}, 1, wxALIGN_CENTER_VERTICAL);
- }
- $temp_panel->SetSizer($temp_sizer);
- $temp_panel->Hide;
- $left_sizer->Add($temp_panel, 0, wxEXPAND | wxTOP | wxBOTTOM, 4);
- }
-
- # print jobs panel
- $self->{print_jobs_sizer} = my $print_jobs_sizer = Wx::BoxSizer->new(wxVERTICAL);
- {
- my $text = Wx::StaticText->new($box, -1, "Queue:", wxDefaultPosition, wxDefaultSize);
- $text->SetFont($Slic3r::GUI::small_font);
- $print_jobs_sizer->Add($text, 0, wxEXPAND, 0);
-
- $self->{jobs_panel} = Wx::ScrolledWindow->new($box, -1, wxDefaultPosition, wxDefaultSize,
- wxVSCROLL | wxBORDER_NONE);
- $self->{jobs_panel}->SetScrollbars(0, 1, 0, 1);
- $self->{jobs_panel_sizer} = Wx::BoxSizer->new(wxVERTICAL);
- $self->{jobs_panel}->SetSizer($self->{jobs_panel_sizer});
- $print_jobs_sizer->Add($self->{jobs_panel}, 1, wxEXPAND, 0);
-
- # TODO: fix this. We're trying to pass the scroll event to the parent but it
- # doesn't work.
- EVT_SCROLLWIN($self->{jobs_panel}, sub {
- my ($panel, $event) = @_;
-
- my $controller = $self->GetParent;
- my $new_event = Wx::ScrollWinEvent->new(
- $event->GetEventType,
- $event->GetPosition,
- $event->GetOrientation,
- );
- $controller->ProcessEvent($new_event);
- }) if 0;
- }
-
- my $log_sizer = Wx::BoxSizer->new(wxVERTICAL);
- {
- my $text = Wx::StaticText->new($box, -1, "Log:", wxDefaultPosition, wxDefaultSize);
- $text->SetFont($Slic3r::GUI::small_font);
- $log_sizer->Add($text, 0, wxEXPAND, 0);
-
- my $log = $self->{log_textctrl} = Wx::TextCtrl->new($box, -1, "", wxDefaultPosition, wxDefaultSize,
- wxTE_MULTILINE | wxBORDER_NONE);
- $log->SetBackgroundColour($box->GetBackgroundColour);
- $log->SetFont($Slic3r::GUI::small_font);
- $log->SetEditable(0);
- $log_sizer->Add($self->{log_textctrl}, 1, wxEXPAND, 0);
- }
-
- $sizer->Add($left_sizer, 0, wxEXPAND | wxALL, 0);
- $sizer->Add($print_jobs_sizer, 2, wxEXPAND | wxALL, 0);
- $sizer->Add($log_sizer, 1, wxEXPAND | wxLEFT, 15);
-
- $self->SetSizer($sizer);
- $self->SetMinSize($self->GetSize);
-
- $self->_update_connection_controls;
-
- return $self;
-}
-
-sub is_connected {
- my ($self) = @_;
- return $self->sender && $self->sender->is_connected;
-}
-
-sub _update_connection_controls {
- my ($self) = @_;
-
- $self->{btn_connect}->Show;
- $self->{btn_disconnect}->Hide;
- $self->{serial_port_combobox}->Enable;
- $self->{serial_speed_combobox}->Enable;
- $self->{btn_rescan_serial}->Enable;
- $self->{btn_manual_control}->Hide;
- $self->{btn_manual_control}->Disable;
-
- if ($self->is_connected) {
- $self->{btn_connect}->Hide;
- $self->{btn_manual_control}->Show;
- if (!$self->printing || $self->printing->paused) {
- $self->{btn_disconnect}->Show;
- $self->{btn_manual_control}->Enable;
- }
- $self->{serial_port_combobox}->Disable;
- $self->{serial_speed_combobox}->Disable;
- $self->{btn_rescan_serial}->Disable;
- }
-
- $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 connect {
- my ($self) = @_;
-
- return if $self->is_connected;
-
- $self->set_status("Connecting...");
- $self->sender(Slic3r::GCode::Sender->new);
- my $res = $self->sender->connect(
- $self->{serial_port_combobox}->GetValue,
- $self->{serial_speed_combobox}->GetValue,
- );
- if (!$res) {
- $self->set_status("Connection failed. Check serial port and speed.");
- } else {
- if ($self->sender->wait_connected) {
- $self->set_status("Printer is online. You can now start printing from the queue on the right.");
- $self->status_timer->Start(STATUS_TIMER_INTERVAL, wxTIMER_CONTINUOUS);
- $self->temp_timer->Start(TEMP_TIMER_INTERVAL, wxTIMER_CONTINUOUS);
-
- # request temperature now, without waiting for the timer
- $self->sender->send("M105", 1);
- } else {
- $self->set_status("Connection failed. Check serial port and speed.");
- }
- }
- $self->_update_connection_controls;
- $self->reload_jobs;
-}
-
-sub disconnect {
- my ($self) = @_;
-
- $self->status_timer->Stop;
- $self->temp_timer->Stop;
- return if !$self->is_connected;
-
- $self->printing->printing(0) if $self->printing;
- $self->printing(undef);
- $self->{gauge}->Hide;
- $self->{temp_panel}->Hide;
- $self->sender->disconnect;
- $self->set_status("");
- $self->_update_connection_controls;
- $self->reload_jobs;
-}
-
-sub update_serial_ports {
- my ($self) = @_;
-
- my $cb = $self->{serial_port_combobox};
- my $current = $cb->GetValue;
- $cb->Clear;
- $cb->Append($_) for Slic3r::GUI::scan_serial_ports;
- $cb->SetValue($current);
-}
-
-sub load_print_job {
- my ($self, $gcode_file, $filament_stats) = @_;
-
- push @{$self->jobs}, my $job = Slic3r::GUI::Controller::PrinterPanel::PrintJob->new(
- id => time() . $gcode_file . rand(1000),
- gcode_file => $gcode_file,
- filament_stats => $filament_stats,
- );
- $self->reload_jobs;
- return $job;
-}
-
-sub delete_job {
- my ($self, $job) = @_;
-
- $self->jobs([ grep $_->id ne $job->id, @{$self->jobs} ]);
- $self->reload_jobs;
-}
-
-sub print_job {
- my ($self, $job) = @_;
-
- $self->printing($job);
- $job->printing(1);
- $self->reload_jobs;
-
- open my $fh, '<', $job->gcode_file;
- my $line_count = 0;
- while (my $row = <$fh>) {
- $self->sender->send($row);
- $line_count++;
- }
- close $fh;
-
- $self->_update_connection_controls;
- $self->{gauge}->SetRange($line_count);
- $self->{gauge}->SetValue(0);
- $self->{gauge}->Enable;
- $self->{gauge}->Show;
- $self->Layout;
-
- $self->set_status('Printing...');
- $self->{log_textctrl}->AppendText(sprintf "=====\n");
- $self->{log_textctrl}->AppendText(sprintf "Printing %s\n", $job->name);
- $self->{log_textctrl}->AppendText(sprintf "Print started at %s\n", $self->_timestamp);
-}
-
-sub print_completed {
- my ($self) = @_;
-
- my $job = $self->printing;
- $self->printing(undef);
- $job->printing(0);
- $job->printed(1);
- $self->_update_connection_controls;
- $self->{gauge}->Hide;
- $self->Layout;
-
- $self->set_status('Print completed.');
- $self->{log_textctrl}->AppendText(sprintf "Print completed at %s\n", $self->_timestamp);
-
- $self->reload_jobs;
-}
-
-sub reload_jobs {
- my ($self) = @_;
-
- # reorder jobs
- @{$self->jobs} = sort { ($a->printed <=> $b->printed) || ($a->timestamp <=> $b->timestamp) }
- @{$self->jobs};
-
- # remove all panels
- foreach my $child ($self->{jobs_panel_sizer}->GetChildren) {
- my $window = $child->GetWindow;
- $self->{jobs_panel_sizer}->Detach($window);
- # now $child does not exist anymore
- $window->Destroy;
- }
-
- # re-add all panels
- foreach my $job (@{$self->jobs}) {
- my $panel = Slic3r::GUI::Controller::PrinterPanel::PrintJobPanel->new($self->{jobs_panel}, $job);
- $self->{jobs_panel_sizer}->Add($panel, 0, wxEXPAND | wxBOTTOM, 5);
-
- $panel->on_delete_job(sub {
- my ($job) = @_;
- $self->delete_job($job);
- });
- $panel->on_print_job(sub {
- my ($job) = @_;
- $self->print_job($job);
- });
- $panel->on_pause_print(sub {
- my ($job) = @_;
- $self->sender->pause_queue;
- $job->paused(1);
- $self->reload_jobs;
- $self->_update_connection_controls;
- $self->{gauge}->Disable;
- $self->set_status('Print is paused. Click on Resume to continue.');
- });
- $panel->on_abort_print(sub {
- my ($job) = @_;
- $self->sender->purge_queue;
- $self->printing(undef);
- $job->printing(0);
- $job->paused(0);
- $self->reload_jobs;
- $self->_update_connection_controls;
- $self->{gauge}->Disable;
- $self->{gauge}->Hide;
- $self->set_status('Print was aborted.');
- $self->{log_textctrl}->AppendText(sprintf "Print aborted at %s\n", $self->_timestamp);
- });
- $panel->on_resume_print(sub {
- my ($job) = @_;
- $self->sender->resume_queue;
- $job->paused(0);
- $self->reload_jobs;
- $self->_update_connection_controls;
- $self->{gauge}->Enable;
- $self->set_status('Printing...');
- });
- $panel->enable_print if $self->is_connected && !$self->printing;
-
- EVT_MOUSEWHEEL($panel, sub {
- my (undef, $event) = @_;
- Wx::PostEvent($self->{jobs_panel}, $event);
- $event->Skip;
- });
- }
-
- $self->{jobs_panel}->Layout;
- $self->{print_jobs_sizer}->Layout;
-}
-
-sub _timestamp {
- my ($self) = @_;
-
- my @time = localtime(time);
- return sprintf '%02d:%02d:%02d', @time[2,1,0];
-}
-
-package Slic3r::GUI::Controller::PrinterPanel::PrintJob;
-use Moo;
-
-use File::Basename qw(basename);
-
-has 'id' => (is => 'ro', required => 1);
-has 'timestamp' => (is => 'ro', default => sub { time });
-has 'gcode_file' => (is => 'ro', required => 1);
-has 'filament_stats' => (is => 'rw');
-has 'printing' => (is => 'rw', default => sub { 0 });
-has 'paused' => (is => 'rw', default => sub { 0 });
-has 'printed' => (is => 'rw', default => sub { 0 });
-
-sub name {
- my ($self) = @_;
- return basename($self->gcode_file);
-}
-
-package Slic3r::GUI::Controller::PrinterPanel::PrintJobPanel;
-use strict;
-use warnings;
-use utf8;
-
-use Wx qw(wxTheApp :panel :id :misc :sizer :button :bitmap :font :dialog :icon :timer
- :colour :brush :pen);
-use Wx::Event qw(EVT_BUTTON EVT_TIMER EVT_ERASE_BACKGROUND);
-use base qw(Wx::Panel Class::Accessor);
-
-__PACKAGE__->mk_accessors(qw(job on_delete_job on_print_job on_pause_print on_resume_print
- on_abort_print blink_timer));
-
-sub new {
- my ($class, $parent, $job) = @_;
- my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize);
-
- $self->job($job);
- $self->SetBackgroundColour(wxWHITE);
-
- {
- my $white_brush = Wx::Brush->new(wxWHITE, wxSOLID);
- my $pen = Wx::Pen->new(Wx::Colour->new(200,200,200), 1, wxSOLID);
- EVT_ERASE_BACKGROUND($self, sub {
- my ($self, $event) = @_;
- my $dc = $event->GetDC;
- my $size = $self->GetSize;
- $dc->SetBrush($white_brush);
- $dc->SetPen($pen);
- $dc->DrawRoundedRectangle(0, 0, $size->GetWidth,$size->GetHeight, 6);
- });
- }
-
- my $left_sizer = Wx::BoxSizer->new(wxVERTICAL);
- {
- $self->{job_name_textctrl} = my $text = Wx::StaticText->new($self, -1, $job->name, wxDefaultPosition, wxDefaultSize);
- my $font = $text->GetFont;
- $font->SetWeight(wxFONTWEIGHT_BOLD);
- $text->SetFont($font);
- if ($job->printed) {
- $text->SetForegroundColour($Slic3r::GUI::grey);
- }
- $left_sizer->Add($text, 0, wxEXPAND, 0);
- }
- {
- my $filament_stats = join "\n",
- map "$_ (" . sprintf("%.2f", $job->filament_stats->{$_}/1000) . "m)",
- sort keys %{$job->filament_stats};
- my $text = Wx::StaticText->new($self, -1, $filament_stats, wxDefaultPosition, wxDefaultSize);
- $text->SetFont($Slic3r::GUI::small_font);
- if ($job->printed && !$job->printing) {
- $text->SetForegroundColour($Slic3r::GUI::grey);
- }
- $left_sizer->Add($text, 0, wxEXPAND | wxTOP, 6);
- }
-
- my $buttons_sizer = Wx::BoxSizer->new(wxVERTICAL);
- my $button_style = Wx::wxBORDER_NONE | wxBU_EXACTFIT;
- {
- my $btn = $self->{btn_delete} = Wx::Button->new($self, -1, 'Delete',
- wxDefaultPosition, wxDefaultSize, $button_style);
- $btn->SetToolTipString("Delete this job from print queue")
- if $btn->can('SetToolTipString');
- $btn->SetFont($Slic3r::GUI::small_font);
- $btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("delete.png"), wxBITMAP_TYPE_PNG));
- if ($job->printing) {
- $btn->Hide;
- }
- $buttons_sizer->Add($btn, 0, wxBOTTOM, 2);
-
- EVT_BUTTON($self, $btn, sub {
- my $res = Wx::MessageDialog->new($self, "Are you sure you want to delete this print job?", 'Delete Job', wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION)->ShowModal;
- return unless $res == wxID_YES;
-
- wxTheApp->CallAfter(sub {
- $self->on_delete_job->($job);
- });
- });
- }
- {
- my $label = $job->printed ? 'Print Again' : 'Print This';
- my $btn = $self->{btn_print} = Wx::Button->new($self, -1, $label, wxDefaultPosition, wxDefaultSize,
- $button_style);
- $btn->SetFont($Slic3r::GUI::small_bold_font);
- $btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("control_play.png"), wxBITMAP_TYPE_PNG));
- $btn->SetBitmapCurrent(Wx::Bitmap->new(Slic3r::var("control_play_blue.png"), wxBITMAP_TYPE_PNG));
- #$btn->SetBitmapPosition(wxRIGHT);
- $btn->Hide;
- $buttons_sizer->Add($btn, 0, wxBOTTOM, 2);
-
- EVT_BUTTON($self, $btn, sub {
- wxTheApp->CallAfter(sub {
- $self->on_print_job->($job);
- });
- });
- }
- {
- my $btn = $self->{btn_pause} = Wx::Button->new($self, -1, "Pause", wxDefaultPosition, wxDefaultSize,
- $button_style);
- $btn->SetFont($Slic3r::GUI::small_font);
- if (!$job->printing || $job->paused) {
- $btn->Hide;
- }
- $btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("control_pause.png"), wxBITMAP_TYPE_PNG));
- $btn->SetBitmapCurrent(Wx::Bitmap->new(Slic3r::var("control_pause_blue.png"), wxBITMAP_TYPE_PNG));
- $buttons_sizer->Add($btn, 0, wxBOTTOM, 2);
-
- EVT_BUTTON($self, $btn, sub {
- wxTheApp->CallAfter(sub {
- $self->on_pause_print->($job);
- });
- });
- }
- {
- my $btn = $self->{btn_resume} = Wx::Button->new($self, -1, "Resume", wxDefaultPosition, wxDefaultSize,
- $button_style);
- $btn->SetFont($Slic3r::GUI::small_font);
- if (!$job->printing || !$job->paused) {
- $btn->Hide;
- }
- $btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("control_play.png"), wxBITMAP_TYPE_PNG));
- $btn->SetBitmapCurrent(Wx::Bitmap->new(Slic3r::var("control_play_blue.png"), wxBITMAP_TYPE_PNG));
- $buttons_sizer->Add($btn, 0, wxBOTTOM, 2);
-
- EVT_BUTTON($self, $btn, sub {
- wxTheApp->CallAfter(sub {
- $self->on_resume_print->($job);
- });
- });
- }
- {
- my $btn = $self->{btn_abort} = Wx::Button->new($self, -1, "Abort", wxDefaultPosition, wxDefaultSize,
- $button_style);
- $btn->SetFont($Slic3r::GUI::small_font);
- if (!$job->printing) {
- $btn->Hide;
- }
- $btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("control_stop.png"), wxBITMAP_TYPE_PNG));
- $btn->SetBitmapCurrent(Wx::Bitmap->new(Slic3r::var("control_stop_blue.png"), wxBITMAP_TYPE_PNG));
- $buttons_sizer->Add($btn, 0, wxBOTTOM, 2);
-
- EVT_BUTTON($self, $btn, sub {
- wxTheApp->CallAfter(sub {
- $self->on_abort_print->($job);
- });
- });
- }
-
- my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
- $sizer->Add($left_sizer, 1, wxEXPAND | wxALL, 6);
- $sizer->Add($buttons_sizer, 0, wxEXPAND | wxALL, 6);
- $self->SetSizer($sizer);
-
- # set-up the timer that changes the job name color while printing
- if ($self->job->printing && !$self->job->paused) {
- my $timer_id = &Wx::NewId();
- $self->blink_timer(Wx::Timer->new($self, $timer_id));
- my $blink = 0; # closure
- my $colour = Wx::Colour->new(0, 190, 0);
- EVT_TIMER($self, $timer_id, sub {
- my ($self, $event) = @_;
-
- $self->{job_name_textctrl}->SetForegroundColour($blink ? Wx::wxBLACK : $colour);
- $blink = !$blink;
- });
- $self->blink_timer->Start(1000, wxTIMER_CONTINUOUS);
- }
-
- return $self;
-}
-
-sub enable_print {
- my ($self) = @_;
-
- if (!$self->job->printing) {
- $self->{btn_print}->Show;
- }
- $self->Layout;
-}
-
-sub Destroy {
- my ($self) = @_;
-
- # There's a gap between the time Perl destroys the wxPanel object and
- # the blink_timer member, so the wxTimer might still fire an event which
- # isn't handled properly, causing a crash. So we ensure that blink_timer
- # is stopped before we destroy the wxPanel.
- $self->blink_timer->Stop if $self->blink_timer;
- return $self->SUPER::Destroy;
-}
-
-1;
diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm
index 59c39dc8b..e2a25a7ab 100644
--- a/lib/Slic3r/GUI/MainFrame.pm
+++ b/lib/Slic3r/GUI/MainFrame.pm
@@ -150,9 +150,6 @@ sub _init_tabpanel {
event_remove_object => $OBJECT_REMOVE_EVENT,
event_update_scene => $UPDATE_SCENE_EVENT,
), L("Plater"));
- if (!$self->{no_controller}) {
- $panel->AddPage($self->{controller} = Slic3r::GUI::Controller->new($panel), L("Controller"));
- }
}
#TODO this is an example of a Slic3r XS interface call to add a new preset editor page to the main view.
diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm
deleted file mode 100644
index 962e6ffc0..000000000
--- a/lib/Slic3r/GUI/OptionsGroup.pm
+++ /dev/null
@@ -1,498 +0,0 @@
-# A dialog group object. Used by the Tab, Preferences dialog, ManualControlDialog etc.
-
-package Slic3r::GUI::OptionsGroup;
-use Moo;
-
-use List::Util qw(first);
-use Wx qw(:combobox :font :misc :sizer :systemsettings :textctrl wxTheApp);
-use Wx::Event qw(EVT_CHECKBOX EVT_COMBOBOX EVT_SPINCTRL EVT_TEXT EVT_KILL_FOCUS EVT_SLIDER);
-
-has 'parent' => (is => 'ro', required => 1);
-has 'title' => (is => 'ro', required => 1);
-has 'on_change' => (is => 'rw', default => sub { sub {} });
-has 'staticbox' => (is => 'ro', default => sub { 1 });
-has 'label_width' => (is => 'rw', default => sub { 180 });
-has 'extra_column' => (is => 'rw', default => sub { undef });
-has 'label_font' => (is => 'rw');
-has 'sidetext_font' => (is => 'rw', default => sub { Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) });
-has 'sizer' => (is => 'rw');
-has '_disabled' => (is => 'rw', default => sub { 0 });
-has '_grid_sizer' => (is => 'rw');
-has '_options' => (is => 'ro', default => sub { {} });
-has '_fields' => (is => 'ro', default => sub { {} });
-
-sub BUILD {
- my $self = shift;
-
- if ($self->staticbox) {
- my $box = Wx::StaticBox->new($self->parent, -1, $self->title);
- $self->sizer(Wx::StaticBoxSizer->new($box, wxVERTICAL));
- } else {
- $self->sizer(Wx::BoxSizer->new(wxVERTICAL));
- }
-
- my $num_columns = 1;
- ++$num_columns if $self->label_width != 0;
- ++$num_columns if $self->extra_column;
- $self->_grid_sizer(Wx::FlexGridSizer->new(0, $num_columns, 0, 0));
- $self->_grid_sizer->SetFlexibleDirection(wxHORIZONTAL);
- $self->_grid_sizer->AddGrowableCol($self->label_width != 0);
-
- # TODO: border size may be related to wxWidgets 2.8.x vs. 2.9.x instead of wxMAC specific
- $self->sizer->Add($self->_grid_sizer, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 5);
-}
-
-# this method accepts a Slic3r::GUI::OptionsGroup::Line object
-sub append_line {
- my ($self, $line) = @_;
-
- if ($line->sizer || ($line->widget && $line->full_width)) {
- # full-width widgets are appended *after* the grid sizer, so after all the non-full-width lines
- my $sizer = $line->sizer // $line->widget->($self->parent);
- $self->sizer->Add($sizer, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 15);
- return;
- }
-
- my $grid_sizer = $self->_grid_sizer;
-
- # if we have an extra column, build it
- if ($self->extra_column) {
- if (defined (my $item = $self->extra_column->($line))) {
- $grid_sizer->Add($item, 0, wxALIGN_CENTER_VERTICAL, 0);
- } else {
- # if the callback provides no sizer for the extra cell, put a spacer
- $grid_sizer->AddSpacer(1);
- }
- }
-
- # build label if we have it
- my $label;
- if ($self->label_width != 0) {
- $label = Wx::StaticText->new($self->parent, -1, $line->label ? $line->label . ":" : "", wxDefaultPosition, [$self->label_width, -1]);
- $label->SetFont($self->label_font) if $self->label_font;
- $label->Wrap($self->label_width) ; # needed to avoid Linux/GTK bug
- $grid_sizer->Add($label, 0, wxALIGN_CENTER_VERTICAL, 0);
- $label->SetToolTipString($line->label_tooltip) if $line->label_tooltip;
- }
-
- # if we have a widget, add it to the sizer
- if ($line->widget) {
- my $widget_sizer = $line->widget->($self->parent);
- $grid_sizer->Add($widget_sizer, 0, wxEXPAND | wxALL, &Wx::wxMAC ? 0 : 15);
- return;
- }
-
- # if we have a single option with no sidetext just add it directly to the grid sizer
- my @options = @{$line->get_options};
- $self->_options->{$_->opt_id} = $_ for @options;
- if (@options == 1 && !$options[0]->sidetext && !$options[0]->side_widget && !@{$line->get_extra_widgets}) {
- my $option = $options[0];
- my $field = $self->_build_field($option);
- $grid_sizer->Add($field, 0, ($option->full_width ? wxEXPAND : 0) | wxALIGN_CENTER_VERTICAL, 0);
- return;
- }
-
- # if we're here, we have more than one option or a single option with sidetext
- # so we need a horizontal sizer to arrange these things
- my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
- $grid_sizer->Add($sizer, 0, 0, 0);
-
- foreach my $i (0..$#options) {
- my $option = $options[$i];
-
- # add label if any
- if ($option->label) {
- my $field_label = Wx::StaticText->new($self->parent, -1, $option->label . ":", wxDefaultPosition, wxDefaultSize);
- $field_label->SetFont($self->sidetext_font);
- $sizer->Add($field_label, 0, wxALIGN_CENTER_VERTICAL, 0);
- }
-
- # add field
- my $field = $self->_build_field($option);
- $sizer->Add($field, 0, wxALIGN_CENTER_VERTICAL, 0);
-
- # add sidetext if any
- if ($option->sidetext) {
- my $sidetext = Wx::StaticText->new($self->parent, -1, $option->sidetext, wxDefaultPosition, wxDefaultSize);
- $sidetext->SetFont($self->sidetext_font);
- $sizer->Add($sidetext, 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 4);
- }
-
- # add side widget if any
- if ($option->side_widget) {
- $sizer->Add($option->side_widget->($self->parent), 0, wxLEFT | wxALIGN_CENTER_VERTICAL, 1);
- }
-
- if ($option != $#options) {
- $sizer->AddSpacer(4);
- }
- }
-
- # add extra sizers if any
- foreach my $extra_widget (@{$line->get_extra_widgets}) {
- $sizer->Add($extra_widget->($self->parent), 0, wxLEFT | wxALIGN_CENTER_VERTICAL , 4);
- }
-}
-
-sub create_single_option_line {
- my ($self, $option) = @_;
-
- my $line = Slic3r::GUI::OptionsGroup::Line->new(
- label => $option->label,
- label_tooltip => $option->tooltip,
- );
- $option->label("");
- $line->append_option($option);
-
- return $line;
-}
-
-sub append_single_option_line {
- my ($self, $option) = @_;
- return $self->append_line($self->create_single_option_line($option));
-}
-
-sub _build_field {
- my $self = shift;
- my ($opt) = @_;
-
- my $opt_id = $opt->opt_id;
- my $on_change = sub {
- #! This function will be called from Field.
- my ($opt_id, $value) = @_;
- #! Call OptionGroup._on_change(...)
- $self->_on_change($opt_id, $value)
- unless $self->_disabled;
- };
- my $on_kill_focus = sub {
- my ($opt_id) = @_;
- $self->_on_kill_focus($opt_id);
- };
-
- my $type = $opt->{gui_type} || $opt->{type};
-
- my $field;
- if ($type eq 'bool') {
- $field = Slic3r::GUI::OptionsGroup::Field::Checkbox->new(
- parent => $self->parent,
- option => $opt,
- );
- } elsif ($type eq 'i') {
- $field = Slic3r::GUI::OptionsGroup::Field::SpinCtrl->new(
- parent => $self->parent,
- option => $opt,
- );
- } elsif ($type eq 'color') {
- $field = Slic3r::GUI::OptionsGroup::Field::ColourPicker->new(
- parent => $self->parent,
- option => $opt,
- );
- } elsif ($type =~ /^(f|s|s@|percent)$/) {
- $field = Slic3r::GUI::OptionsGroup::Field::TextCtrl->new(
- parent => $self->parent,
- option => $opt,
- );
- } elsif ($type eq 'select' || $type eq 'select_open') {
- $field = Slic3r::GUI::OptionsGroup::Field::Choice->new(
- parent => $self->parent,
- option => $opt,
- );
- } elsif ($type eq 'f_enum_open' || $type eq 'i_enum_open' || $type eq 'i_enum_closed') {
- $field = Slic3r::GUI::OptionsGroup::Field::NumericChoice->new(
- parent => $self->parent,
- option => $opt,
- );
- } elsif ($type eq 'point') {
- $field = Slic3r::GUI::OptionsGroup::Field::Point->new(
- parent => $self->parent,
- option => $opt,
- );
- } elsif ($type eq 'slider') {
- $field = Slic3r::GUI::OptionsGroup::Field::Slider->new(
- parent => $self->parent,
- option => $opt,
- );
- }
- return undef if !$field;
-
- #! setting up a function that will be triggered when the field changes
- #! think of it as $field->on_change = ($on_change)
- $field->on_change($on_change);
- $field->on_kill_focus($on_kill_focus);
- $self->_fields->{$opt_id} = $field;
-
- return $field->isa('Slic3r::GUI::OptionsGroup::Field::wxWindow')
- ? $field->wxWindow
- : $field->wxSizer;
-}
-
-sub get_option {
- my ($self, $opt_id) = @_;
- return undef if !exists $self->_options->{$opt_id};
- return $self->_options->{$opt_id};
-}
-
-sub get_field {
- my ($self, $opt_id) = @_;
- return undef if !exists $self->_fields->{$opt_id};
- return $self->_fields->{$opt_id};
-}
-
-sub get_value {
- my ($self, $opt_id) = @_;
-
- return if !exists $self->_fields->{$opt_id};
- return $self->_fields->{$opt_id}->get_value;
-}
-
-sub set_value {
- my ($self, $opt_id, $value) = @_;
-
- return if !exists $self->_fields->{$opt_id};
- $self->_fields->{$opt_id}->set_value($value);
-}
-
-sub _on_change {
- my ($self, $opt_id, $value) = @_;
- $self->on_change->($opt_id, $value);
-}
-
-sub enable {
- my ($self) = @_;
-
- $_->enable for values %{$self->_fields};
-}
-
-sub disable {
- my ($self) = @_;
-
- $_->disable for values %{$self->_fields};
-}
-
-sub _on_kill_focus {
- my ($self, $opt_id) = @_;
- # nothing
-}
-
-
-package Slic3r::GUI::OptionsGroup::Line;
-use Moo;
-
-has 'label' => (is => 'rw', default => sub { "" });
-has 'full_width' => (is => 'rw', default => sub { 0 });
-has 'label_tooltip' => (is => 'rw', default => sub { "" });
-has 'sizer' => (is => 'rw');
-has 'widget' => (is => 'rw');
-has '_options' => (is => 'ro', default => sub { [] });
-# Extra UI components after the label and the edit widget of the option.
-has '_extra_widgets' => (is => 'ro', default => sub { [] });
-
-# this method accepts a Slic3r::GUI::OptionsGroup::Option object
-sub append_option {
- my ($self, $option) = @_;
- push @{$self->_options}, $option;
-}
-
-sub append_widget {
- my ($self, $widget) = @_;
- push @{$self->_extra_widgets}, $widget;
-}
-
-sub get_options {
- my ($self) = @_;
- return [ @{$self->_options} ];
-}
-
-sub get_extra_widgets {
- my ($self) = @_;
- return [ @{$self->_extra_widgets} ];
-}
-
-
-# Configuration of an option.
-# This very much reflects the content of the C++ ConfigOptionDef class.
-package Slic3r::GUI::OptionsGroup::Option;
-use Moo;
-
-has 'opt_id' => (is => 'rw', required => 1);
-has 'type' => (is => 'rw', required => 1);
-has 'default' => (is => 'rw', required => 1);
-has 'gui_type' => (is => 'rw', default => sub { undef });
-has 'gui_flags' => (is => 'rw', default => sub { "" });
-has 'label' => (is => 'rw', default => sub { "" });
-has 'sidetext' => (is => 'rw', default => sub { "" });
-has 'tooltip' => (is => 'rw', default => sub { "" });
-has 'multiline' => (is => 'rw', default => sub { 0 });
-has 'full_width' => (is => 'rw', default => sub { 0 });
-has 'width' => (is => 'rw', default => sub { undef });
-has 'height' => (is => 'rw', default => sub { undef });
-has 'min' => (is => 'rw', default => sub { undef });
-has 'max' => (is => 'rw', default => sub { undef });
-has 'labels' => (is => 'rw', default => sub { [] });
-has 'values' => (is => 'rw', default => sub { [] });
-has 'readonly' => (is => 'rw', default => sub { 0 });
-has 'side_widget' => (is => 'rw', default => sub { undef });
-
-
-package Slic3r::GUI::ConfigOptionsGroup;
-use Moo;
-
-use List::Util qw(first);
-
-extends 'Slic3r::GUI::OptionsGroup';
-has 'config' => (is => 'ro', required => 1);
-has 'full_labels' => (is => 'ro', default => sub { 0 });
-has '_opt_map' => (is => 'ro', default => sub { {} });
-
-sub get_option {
- my ($self, $opt_key, $opt_index) = @_;
-
- $opt_index //= -1;
-
- if (!$self->config->has($opt_key)) {
- die "No $opt_key in ConfigOptionsGroup config";
- }
-
- my $opt_id = ($opt_index == -1 ? $opt_key : "${opt_key}#${opt_index}");
- $self->_opt_map->{$opt_id} = [ $opt_key, $opt_index ];
-
- # Slic3r::Config::Options is a C++ Slic3r::PrintConfigDef exported as a Perl hash of hashes.
- # The C++ counterpart is a constant singleton.
- my $optdef = $Slic3r::Config::Options->{$opt_key}; # we should access this from $self->config
- my $default_value = $self->_get_config_value($opt_key, $opt_index, $optdef->{gui_flags} =~ /\bserialized\b/);
-
- return Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => $opt_id,
- type => $optdef->{type},
- default => $default_value,
- gui_type => $optdef->{gui_type},
- gui_flags => $optdef->{gui_flags},
- label => ($self->full_labels && defined $optdef->{full_label}) ? $optdef->{full_label} : $optdef->{label},
- sidetext => $optdef->{sidetext},
- # calling serialize() ensures we get a stringified value
- tooltip => $optdef->{tooltip} . " (default: " . $self->config->serialize($opt_key) . ")",
- multiline => $optdef->{multiline},
- width => $optdef->{width},
- min => $optdef->{min},
- max => $optdef->{max},
- labels => $optdef->{labels},
- values => $optdef->{values},
- readonly => $optdef->{readonly},
- );
-}
-
-sub create_single_option_line {
- my ($self, $opt_key, $opt_index) = @_;
-
- my $option;
- if (ref($opt_key)) {
- $option = $opt_key;
- } else {
- $option = $self->get_option($opt_key, $opt_index);
- }
- return $self->SUPER::create_single_option_line($option);
-}
-
-sub append_single_option_line {
- my ($self, $option, $opt_index) = @_;
- return $self->append_line($self->create_single_option_line($option, $opt_index));
-}
-
-# Initialize UI components with the config values.
-sub reload_config {
- my ($self) = @_;
-
- foreach my $opt_id (keys %{ $self->_opt_map }) {
- my ($opt_key, $opt_index) = @{ $self->_opt_map->{$opt_id} };
- my $option = $self->_options->{$opt_id};
- $self->set_value($opt_id, $self->_get_config_value($opt_key, $opt_index, $option->gui_flags =~ /\bserialized\b/));
- }
-}
-
-sub get_fieldc {
- my ($self, $opt_key, $opt_index) = @_;
-
- $opt_index //= -1;
- my $opt_id = first { $self->_opt_map->{$_}[0] eq $opt_key && $self->_opt_map->{$_}[1] == $opt_index }
- keys %{$self->_opt_map};
- return defined($opt_id) ? $self->get_field($opt_id) : undef;
-}
-
-sub _get_config_value {
- my ($self, $opt_key, $opt_index, $deserialize) = @_;
-
- if ($deserialize) {
- # Want to edit a vector value (currently only multi-strings) in a single edit box.
- # Aggregate the strings the old way.
- # Currently used for the post_process config value only.
- die "Can't deserialize option indexed value" if $opt_index != -1;
- return join(';', @{$self->config->get($opt_key)});
- } else {
- return $opt_index == -1
- ? $self->config->get($opt_key)
- : $self->config->get_at($opt_key, $opt_index);
- }
-}
-
-sub _on_change {
- my ($self, $opt_id, $value) = @_;
-
- if (exists $self->_opt_map->{$opt_id}) {
- my ($opt_key, $opt_index) = @{ $self->_opt_map->{$opt_id} };
- my $option = $self->_options->{$opt_id};
-
- # get value
- my $field_value = $self->get_value($opt_id);
- if ($option->gui_flags =~ /\bserialized\b/) {
- die "Can't set serialized option indexed value" if $opt_index != -1;
- # Split a string to multiple strings by a semi-colon. This is the old way of storing multi-string values.
- # Currently used for the post_process config value only.
- my @values = split /;/, $field_value;
- $self->config->set($opt_key, \@values);
- } else {
- if ($opt_index == -1) {
- $self->config->set($opt_key, $field_value);
- } else {
- my $value = $self->config->get($opt_key);
- $value->[$opt_index] = $field_value;
- $self->config->set($opt_key, $value);
- }
- }
- }
-
- $self->SUPER::_on_change($opt_id, $value);
-}
-
-sub _on_kill_focus {
- my ($self, $opt_id) = @_;
-
- # when a field loses focus, reapply the config value to it
- # (thus discarding any invalid input and reverting to the last
- # accepted value)
- $self->reload_config;
-}
-
-# Static text shown among the options.
-# Currently used for the filament cooling legend only.
-package Slic3r::GUI::OptionsGroup::StaticText;
-use Wx qw(:misc :systemsettings);
-use base 'Wx::StaticText';
-
-sub new {
- my ($class, $parent) = @_;
-
- my $self = $class->SUPER::new($parent, -1, "", wxDefaultPosition, wxDefaultSize);
- my $font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
- $self->SetFont($font);
- return $self;
-}
-
-sub SetText {
- my ($self, $value) = @_;
-
- $self->SetLabel($value);
- $self->Wrap(400);
- $self->GetParent->Layout;
-}
-
-1;
diff --git a/lib/Slic3r/GUI/OptionsGroup/Field.pm b/lib/Slic3r/GUI/OptionsGroup/Field.pm
deleted file mode 100644
index 1a53daeb5..000000000
--- a/lib/Slic3r/GUI/OptionsGroup/Field.pm
+++ /dev/null
@@ -1,605 +0,0 @@
-# An input field class prototype.
-package Slic3r::GUI::OptionsGroup::Field;
-use Moo;
-
-# This is a base class for option fields.
-
-has 'parent' => (is => 'ro', required => 1);
-# Slic3r::GUI::OptionsGroup::Option
-has 'option' => (is => 'ro', required => 1);
-# On change callback
-has 'on_change' => (is => 'rw', default => sub { sub {} });
-has 'on_kill_focus' => (is => 'rw', default => sub { sub {} });
-# If set, the callback $self->on_change is not called.
-# This is used to avoid recursive invocation of the field change/update by wxWidgets.
-has 'disable_change_event' => (is => 'rw', default => sub { 0 });
-
-# This method should not fire the on_change event
-sub set_value {
- my ($self, $value) = @_;
- die "Method not implemented";
-}
-
-sub get_value {
- my ($self) = @_;
- die "Method not implemented";
-}
-
-sub set_tooltip {
- my ($self, $tooltip) = @_;
-
- $self->SetToolTipString($tooltip)
- if $tooltip && $self->can('SetToolTipString');
-}
-
-sub toggle {
- my ($self, $enable) = @_;
- $enable ? $self->enable : $self->disable;
-}
-
-sub _on_change {
- my ($self, $opt_id) = @_;
-
- $self->on_change->($opt_id, $self->get_value)
- unless $self->disable_change_event;
-}
-
-sub _on_kill_focus {
- my ($self, $opt_id, $s, $event) = @_;
-
- # Without this, there will be nasty focus bugs on Windows.
- # Also, docs for wxEvent::Skip() say "In general, it is recommended to skip all
- # non-command events to allow the default handling to take place."
- $event->Skip(1);
-
- $self->on_kill_focus->($opt_id);
-}
-
-
-package Slic3r::GUI::OptionsGroup::Field::wxWindow;
-use Moo;
-extends 'Slic3r::GUI::OptionsGroup::Field';
-
-has 'wxWindow' => (is => 'rw', trigger => 1); # wxWindow object
-
-sub _default_size {
- my ($self) = @_;
-
- # default width on Windows is too large
- return Wx::Size->new($self->option->width || 60, $self->option->height || -1);
-}
-
-sub _trigger_wxWindow {
- my ($self) = @_;
-
- $self->wxWindow->SetToolTipString($self->option->tooltip)
- if $self->option->tooltip && $self->wxWindow->can('SetToolTipString');
-}
-
-sub set_value {
- my ($self, $value) = @_;
-
- $self->disable_change_event(1);
- $self->wxWindow->SetValue($value);
- $self->disable_change_event(0);
-}
-
-sub get_value {
- my ($self) = @_;
- return $self->wxWindow->GetValue;
-}
-
-sub enable {
- my ($self) = @_;
-
- $self->wxWindow->Enable;
- $self->wxWindow->Refresh;
-}
-
-sub disable {
- my ($self) = @_;
-
- $self->wxWindow->Disable;
- $self->wxWindow->Refresh;
-}
-
-
-package Slic3r::GUI::OptionsGroup::Field::Checkbox;
-use Moo;
-extends 'Slic3r::GUI::OptionsGroup::Field::wxWindow';
-
-use Wx qw(:misc);
-use Wx::Event qw(EVT_CHECKBOX);
-
-sub BUILD {
- my ($self) = @_;
-
- my $field = Wx::CheckBox->new($self->parent, -1, "");
- $self->wxWindow($field);
- $field->SetValue($self->option->default);
- $field->Disable if $self->option->readonly;
-
- EVT_CHECKBOX($self->parent, $field, sub {
- $self->_on_change($self->option->opt_id);
- });
-}
-
-sub get_value {
- my ($self) = @_;
- return $self->wxWindow->GetValue ? 1 : 0;
-}
-
-package Slic3r::GUI::OptionsGroup::Field::SpinCtrl;
-use Moo;
-extends 'Slic3r::GUI::OptionsGroup::Field::wxWindow';
-
-use Wx qw(:misc);
-use Wx::Event qw(EVT_SPINCTRL EVT_TEXT EVT_KILL_FOCUS);
-
-has 'tmp_value' => (is => 'rw');
-
-sub BUILD {
- my ($self) = @_;
-
- my $field = Wx::SpinCtrl->new($self->parent, -1, $self->option->default, wxDefaultPosition, $self->_default_size,
- 0, $self->option->min || 0, $self->option->max || 2147483647, $self->option->default);
- $self->wxWindow($field);
-
- EVT_SPINCTRL($self->parent, $field, sub {
- $self->tmp_value(undef);
- $self->_on_change($self->option->opt_id);
- });
- EVT_TEXT($self->parent, $field, sub {
- my ($s, $event) = @_;
-
- # On OSX/Cocoa, wxSpinCtrl::GetValue() doesn't return the new value
- # when it was changed from the text control, so the on_change callback
- # gets the old one, and on_kill_focus resets the control to the old value.
- # As a workaround, we get the new value from $event->GetString and store
- # here temporarily so that we can return it from $self->get_value
- $self->tmp_value($event->GetString) if $event->GetString =~ /^\d+$/;
- $self->_on_change($self->option->opt_id);
- # We don't reset tmp_value here because _on_change might put callbacks
- # in the CallAfter queue, and we want the tmp value to be available from
- # them as well.
- });
- EVT_KILL_FOCUS($field, sub {
- $self->tmp_value(undef);
- $self->_on_kill_focus($self->option->opt_id, @_);
- });
-}
-
-sub get_value {
- my ($self) = @_;
- return $self->tmp_value // $self->wxWindow->GetValue;
-}
-
-
-package Slic3r::GUI::OptionsGroup::Field::TextCtrl;
-use Moo;
-extends 'Slic3r::GUI::OptionsGroup::Field::wxWindow';
-
-use Wx qw(:misc :textctrl);
-use Wx::Event qw(EVT_TEXT EVT_KILL_FOCUS);
-
-sub BUILD {
- my ($self) = @_;
-
- my $style = 0;
- $style = wxTE_MULTILINE if $self->option->multiline;
- my $field = Wx::TextCtrl->new($self->parent, -1, $self->option->default, wxDefaultPosition,
- $self->_default_size, $style);
- $self->wxWindow($field);
-
- # TODO: test loading a config that has empty string for multi-value options like 'wipe'
-
- EVT_TEXT($self->parent, $field, sub {
- $self->_on_change($self->option->opt_id);
- });
- EVT_KILL_FOCUS($field, sub {
- $self->_on_kill_focus($self->option->opt_id, @_);
- });
-}
-
-sub enable {
- my ($self) = @_;
-
- $self->wxWindow->Enable;
- $self->wxWindow->SetEditable(1);
-}
-
-sub disable {
- my ($self) = @_;
-
- $self->wxWindow->Disable;
- $self->wxWindow->SetEditable(0);
-}
-
-
-package Slic3r::GUI::OptionsGroup::Field::Choice;
-use Moo;
-extends 'Slic3r::GUI::OptionsGroup::Field::wxWindow';
-
-use List::Util qw(first);
-use Wx qw(:misc :combobox);
-use Wx::Event qw(EVT_COMBOBOX EVT_TEXT);
-
-sub BUILD {
- my ($self) = @_;
-
- my $style = 0;
- $style |= wxCB_READONLY if defined $self->option->gui_type && $self->option->gui_type ne 'select_open';
- my $field = Wx::ComboBox->new($self->parent, -1, "", wxDefaultPosition, $self->_default_size,
- $self->option->labels || $self->option->values || [], $style);
- $self->wxWindow($field);
-
- $self->set_value($self->option->default);
-
- EVT_COMBOBOX($self->parent, $field, sub {
- $self->_on_change($self->option->opt_id);
- });
- EVT_TEXT($self->parent, $field, sub {
- $self->_on_change($self->option->opt_id);
- });
-}
-
-sub set_value {
- my ($self, $value) = @_;
-
- $self->disable_change_event(1);
-
- my $idx;
- if ($self->option->values) {
- $idx = first { $self->option->values->[$_] eq $value } 0..$#{$self->option->values};
- # if value is not among indexes values we use SetValue()
- }
-
- if (defined $idx) {
- $self->wxWindow->SetSelection($idx);
- } else {
- $self->wxWindow->SetValue($value);
- }
-
- $self->disable_change_event(0);
-}
-
-sub set_values {
- my ($self, $values) = @_;
-
- $self->disable_change_event(1);
-
- # it looks that Clear() also clears the text field in recent wxWidgets versions,
- # but we want to preserve it
- my $ww = $self->wxWindow;
- my $value = $ww->GetValue;
- $ww->Clear;
- $ww->Append($_) for @$values;
- $ww->SetValue($value);
-
- $self->disable_change_event(0);
-}
-
-sub get_value {
- my ($self) = @_;
-
- if ($self->option->values) {
- my $idx = $self->wxWindow->GetSelection;
- if ($idx != &Wx::wxNOT_FOUND) {
- return $self->option->values->[$idx];
- }
- }
- return $self->wxWindow->GetValue;
-}
-
-package Slic3r::GUI::OptionsGroup::Field::NumericChoice;
-use Moo;
-extends 'Slic3r::GUI::OptionsGroup::Field::wxWindow';
-
-use List::Util qw(first);
-use Wx qw(wxTheApp :misc :combobox);
-use Wx::Event qw(EVT_COMBOBOX EVT_TEXT);
-
-# if option has no 'values', indices are values
-# if option has no 'labels', values are labels
-
-sub BUILD {
- my ($self) = @_;
-
- my $field = Wx::ComboBox->new($self->parent, -1, $self->option->default, wxDefaultPosition, $self->_default_size,
- $self->option->labels || $self->option->values);
- $self->wxWindow($field);
-
- $self->set_value($self->option->default);
-
- EVT_COMBOBOX($self->parent, $field, sub {
- my $disable_change_event = $self->disable_change_event;
- $self->disable_change_event(1);
-
- my $idx = $field->GetSelection; # get index of selected value
- my $label;
-
- if ($self->option->labels && $idx <= $#{$self->option->labels}) {
- $label = $self->option->labels->[$idx];
- } elsif ($self->option->values && $idx <= $#{$self->option->values}) {
- $label = $self->option->values->[$idx];
- } else {
- $label = $idx;
- }
-
- # The MSW implementation of wxComboBox will leave the field blank if we call
- # SetValue() in the EVT_COMBOBOX event handler, so we postpone the call.
- wxTheApp->CallAfter(sub {
- my $dce = $self->disable_change_event;
- $self->disable_change_event(1);
-
- # ChangeValue() is not exported in wxPerl
- $field->SetValue($label);
-
- $self->disable_change_event($dce);
- });
-
- $self->disable_change_event($disable_change_event);
- $self->_on_change($self->option->opt_id);
- });
- EVT_TEXT($self->parent, $field, sub {
- $self->_on_change($self->option->opt_id);
- });
-}
-
-sub set_value {
- my ($self, $value) = @_;
-
- $self->disable_change_event(1);
-
- my $field = $self->wxWindow;
- if ($self->option->gui_flags =~ /\bshow_value\b/) {
- $field->SetValue($value);
- } else {
- if ($self->option->values) {
- # check whether we have a value index
- my $value_idx = first { $self->option->values->[$_] eq $value } 0..$#{$self->option->values};
- if (defined $value_idx) {
- $field->SetSelection($value_idx);
- $self->disable_change_event(0);
- return;
- }
- } elsif ($self->option->labels && $value <= $#{$self->option->labels}) {
- # if we have no values, we expect value to be an index
- $field->SetValue($self->option->labels->[$value]);
- $self->disable_change_event(0);
- return;
- }
- $field->SetValue($value);
- }
-
- $self->disable_change_event(0);
-}
-
-sub get_value {
- my ($self) = @_;
-
- my $label = $self->wxWindow->GetValue;
- if ($self->option->labels) {
- my $value_idx = first { $self->option->labels->[$_] eq $label } 0..$#{$self->option->labels};
- if (defined $value_idx) {
- if ($self->option->values) {
- return $self->option->values->[$value_idx];
- }
- return $value_idx;
- }
- }
- return $label;
-}
-
-
-package Slic3r::GUI::OptionsGroup::Field::ColourPicker;
-use Moo;
-extends 'Slic3r::GUI::OptionsGroup::Field::wxWindow';
-
-use Wx qw(:misc :colour);
-use Wx::Event qw(EVT_COLOURPICKER_CHANGED);
-
-sub BUILD {
- my ($self) = @_;
-
- my $field = Wx::ColourPickerCtrl->new($self->parent, -1,
- $self->_string_to_colour($self->option->default), wxDefaultPosition,
- $self->_default_size);
- $self->wxWindow($field);
-
- EVT_COLOURPICKER_CHANGED($self->parent, $field, sub {
- $self->_on_change($self->option->opt_id);
- });
-}
-
-sub set_value {
- my ($self, $value) = @_;
-
- $self->disable_change_event(1);
- $self->wxWindow->SetColour($self->_string_to_colour($value));
- $self->disable_change_event(0);
-}
-
-sub get_value {
- my ($self) = @_;
- return $self->wxWindow->GetColour->GetAsString(wxC2S_HTML_SYNTAX);
-}
-
-sub _string_to_colour {
- my ($self, $string) = @_;
-
- $string =~ s/^#//;
- # If the color is in an invalid format, set it to white.
- $string = 'FFFFFF' if ($string !~ m/^[[:xdigit:]]{6}/);
- return Wx::Colour->new(unpack 'C*', pack 'H*', $string);
-}
-
-
-package Slic3r::GUI::OptionsGroup::Field::wxSizer;
-use Moo;
-extends 'Slic3r::GUI::OptionsGroup::Field';
-
-has 'wxSizer' => (is => 'rw'); # wxSizer object
-
-
-package Slic3r::GUI::OptionsGroup::Field::Point;
-use Moo;
-extends 'Slic3r::GUI::OptionsGroup::Field::wxSizer';
-
-has 'x_textctrl' => (is => 'rw');
-has 'y_textctrl' => (is => 'rw');
-
-use Slic3r::Geometry qw(X Y);
-use Wx qw(:misc :sizer);
-use Wx::Event qw(EVT_TEXT);
-
-sub BUILD {
- my ($self) = @_;
-
- my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
- $self->wxSizer($sizer);
-
- my $field_size = Wx::Size->new(40, -1);
-
- $self->x_textctrl(Wx::TextCtrl->new($self->parent, -1, $self->option->default->[X], wxDefaultPosition, $field_size));
- $self->y_textctrl(Wx::TextCtrl->new($self->parent, -1, $self->option->default->[Y], wxDefaultPosition, $field_size));
-
- my @items = (
- Wx::StaticText->new($self->parent, -1, "x:"),
- $self->x_textctrl,
- Wx::StaticText->new($self->parent, -1, " y:"),
- $self->y_textctrl,
- );
- $sizer->Add($_, 0, wxALIGN_CENTER_VERTICAL, 0) for @items;
-
- if ($self->option->tooltip) {
- foreach my $item (@items) {
- $item->SetToolTipString($self->option->tooltip)
- if $item->can('SetToolTipString');
- }
- }
-
- EVT_TEXT($self->parent, $_, sub {
- $self->_on_change($self->option->opt_id);
- }) for $self->x_textctrl, $self->y_textctrl;
-}
-
-sub set_value {
- my ($self, $value) = @_;
-
- $self->disable_change_event(1);
- $self->x_textctrl->SetValue($value->[X]);
- $self->y_textctrl->SetValue($value->[Y]);
- $self->disable_change_event(0);
-}
-
-sub get_value {
- my ($self) = @_;
-
- return [
- $self->x_textctrl->GetValue,
- $self->y_textctrl->GetValue,
- ];
-}
-
-sub enable {
- my ($self) = @_;
-
- $self->x_textctrl->Enable;
- $self->y_textctrl->Enable;
-}
-
-sub disable {
- my ($self) = @_;
-
- $self->x_textctrl->Disable;
- $self->y_textctrl->Disable;
-}
-
-
-package Slic3r::GUI::OptionsGroup::Field::Slider;
-use Moo;
-extends 'Slic3r::GUI::OptionsGroup::Field::wxSizer';
-
-has 'scale' => (is => 'rw', default => sub { 10 });
-has 'slider' => (is => 'rw');
-has 'textctrl' => (is => 'rw');
-
-use Wx qw(:misc :sizer);
-use Wx::Event qw(EVT_SLIDER EVT_TEXT EVT_KILL_FOCUS);
-
-sub BUILD {
- my ($self) = @_;
-
- my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
- $self->wxSizer($sizer);
-
- my $slider = Wx::Slider->new(
- $self->parent, -1,
- ($self->option->default // $self->option->min) * $self->scale,
- ($self->option->min // 0) * $self->scale,
- ($self->option->max // 100) * $self->scale,
- wxDefaultPosition,
- [ $self->option->width // -1, $self->option->height // -1 ],
- );
- $self->slider($slider);
-
- my $textctrl = Wx::TextCtrl->new($self->parent, -1, $slider->GetValue/$self->scale,
- wxDefaultPosition, [50,-1]);
- $self->textctrl($textctrl);
-
- $sizer->Add($slider, 1, wxALIGN_CENTER_VERTICAL, 0);
- $sizer->Add($textctrl, 0, wxALIGN_CENTER_VERTICAL, 0);
-
- EVT_SLIDER($self->parent, $slider, sub {
- if (! $self->disable_change_event) {
- # wxTextCtrl::SetLabel() does not work on Linux, use wxTextCtrl::SetValue() instead
- $self->textctrl->SetValue($self->get_value);
- $self->_on_change($self->option->opt_id);
- }
- });
- EVT_TEXT($self->parent, $textctrl, sub {
- my $value = $textctrl->GetValue;
- if ($value =~ /^-?\d+(\.\d*)?$/) {
- $self->disable_change_event(1);
- $self->slider->SetValue($value*$self->scale);
- $self->disable_change_event(0);
- $self->_on_change($self->option->opt_id);
- }
- });
- EVT_KILL_FOCUS($textctrl, sub {
- $self->_on_kill_focus($self->option->opt_id, @_);
- });
-}
-
-sub set_value {
- my ($self, $value) = @_;
-
- $self->disable_change_event(1);
- $self->slider->SetValue($value*$self->scale);
- $self->textctrl->SetLabel($self->get_value);
- $self->disable_change_event(0);
-}
-
-sub get_value {
- my ($self) = @_;
- return $self->slider->GetValue/$self->scale;
-}
-
-sub enable {
- my ($self) = @_;
-
- $self->slider->Enable;
- $self->textctrl->Enable;
- $self->textctrl->SetEditable(1);
-}
-
-sub disable {
- my ($self) = @_;
-
- $self->slider->Disable;
- $self->textctrl->Disable;
- $self->textctrl->SetEditable(0);
-}
-
-1;
diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm
index de2657894..d3cca7e53 100644
--- a/lib/Slic3r/GUI/Plater.pm
+++ b/lib/Slic3r/GUI/Plater.pm
@@ -296,14 +296,6 @@ sub new {
Slic3r::GUI::register_on_request_update_callback(sub { $self->schedule_background_process; });
-# # Initialize 2D preview canvas
-# $self->{canvas} = Slic3r::GUI::Plater::2D->new($self->{preview_notebook}, wxDefaultSize, $self->{objects}, $self->{model}, $self->{config});
-# $self->{preview_notebook}->AddPage($self->{canvas}, L('2D'));
-# $self->{canvas}->on_select_object($on_select_object);
-# $self->{canvas}->on_double_click($on_double_click);
-# $self->{canvas}->on_right_click(sub { $on_right_click->($self->{canvas}, @_); });
-# $self->{canvas}->on_instances_moved($on_instances_moved);
-
# Initialize 3D toolpaths preview
if ($Slic3r::GUI::have_OpenGL) {
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self->{preview_notebook}, $self->{print}, $self->{gcode_preview_data}, $self->{config});
@@ -314,12 +306,6 @@ sub new {
$self->{preview3D_page_idx} = $self->{preview_notebook}->GetPageCount-1;
}
- # Initialize toolpaths preview
- if ($Slic3r::GUI::have_OpenGL) {
- $self->{toolpaths2D} = Slic3r::GUI::Plater::2DToolpaths->new($self->{preview_notebook}, $self->{print});
- $self->{preview_notebook}->AddPage($self->{toolpaths2D}, L('Layers'));
- }
-
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{preview_notebook}, sub {
my $preview = $self->{preview_notebook}->GetCurrentPage;
if (($preview != $self->{preview3D}) && ($preview != $self->{canvas3D})) {
@@ -994,7 +980,6 @@ sub remove {
$self->stop_background_process;
# Prevent toolpaths preview from rendering while we modify the Print object
- $self->{toolpaths2D}->enabled(0) if $self->{toolpaths2D};
$self->{preview3D}->enabled(0) if $self->{preview3D};
# If no object index is supplied, remove the selected one.
@@ -1020,7 +1005,6 @@ sub reset {
$self->stop_background_process;
# Prevent toolpaths preview from rendering while we modify the Print object
- $self->{toolpaths2D}->enabled(0) if $self->{toolpaths2D};
$self->{preview3D}->enabled(0) if $self->{preview3D};
@{$self->{objects}} = ();
@@ -1382,7 +1366,6 @@ sub async_apply_config {
# Reset preview canvases. If the print has been invalidated, the preview canvases will be cleared.
# Otherwise they will be just refreshed.
$self->{gcode_preview_data}->reset;
- $self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
$self->{preview3D}->reload_print if $self->{preview3D};
# We also need to reload 3D scene because of the wipe tower preview box
if ($self->{config}->wipe_tower) {
@@ -1418,7 +1401,6 @@ sub start_background_process {
sub stop_background_process {
my ($self) = @_;
$self->{background_slicing_process}->stop();
- $self->{toolpaths2D}->reload_print if $self->{canvas3D};
$self->{preview3D}->reload_print if $self->{preview3D};
}
@@ -1525,7 +1507,6 @@ sub export_gcode {
# This message should be called by the background process synchronously.
sub on_update_print_preview {
my ($self) = @_;
- $self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
$self->{preview3D}->reload_print if $self->{preview3D};
# in case this was MM print, wipe tower bounding box on 3D tab might need redrawing with exact depth:
@@ -1607,7 +1588,6 @@ sub on_process_completed {
$self->object_list_changed;
# refresh preview
- $self->{toolpaths2D}->reload_print if $self->{toolpaths2D};
$self->{preview3D}->reload_print if $self->{preview3D};
}
@@ -2043,31 +2023,31 @@ sub filament_color_box_lmouse_down
}
}
-sub object_cut_dialog {
- my ($self, $obj_idx) = @_;
-
- if (!defined $obj_idx) {
- ($obj_idx, undef) = $self->selected_object;
- }
-
- if (!$Slic3r::GUI::have_OpenGL) {
- Slic3r::GUI::show_error($self, L("Please install the OpenGL modules to use this feature (see build instructions)."));
- return;
- }
-
- my $dlg = Slic3r::GUI::Plater::ObjectCutDialog->new($self,
- object => $self->{objects}[$obj_idx],
- model_object => $self->{model}->objects->[$obj_idx],
- );
- return unless $dlg->ShowModal == wxID_OK;
-
- if (my @new_objects = $dlg->NewModelObjects) {
- $self->remove($obj_idx);
- $self->load_model_objects(grep defined($_), @new_objects);
- $self->arrange;
- Slic3r::GUI::_3DScene::zoom_to_volumes($self->{canvas3D}) if $self->{canvas3D};
- }
-}
+#sub object_cut_dialog {
+# my ($self, $obj_idx) = @_;
+#
+# if (!defined $obj_idx) {
+# ($obj_idx, undef) = $self->selected_object;
+# }
+#
+# if (!$Slic3r::GUI::have_OpenGL) {
+# Slic3r::GUI::show_error($self, L("Please install the OpenGL modules to use this feature (see build instructions)."));
+# return;
+# }
+#
+# my $dlg = Slic3r::GUI::Plater::ObjectCutDialog->new($self,
+# object => $self->{objects}[$obj_idx],
+# model_object => $self->{model}->objects->[$obj_idx],
+# );
+# return unless $dlg->ShowModal == wxID_OK;
+#
+# if (my @new_objects = $dlg->NewModelObjects) {
+# $self->remove($obj_idx);
+# $self->load_model_objects(grep defined($_), @new_objects);
+# $self->arrange;
+# Slic3r::GUI::_3DScene::zoom_to_volumes($self->{canvas3D}) if $self->{canvas3D};
+# }
+#}
sub object_settings_dialog {
my ($self, $obj_idx) = @_;
diff --git a/lib/Slic3r/GUI/Plater/2D.pm b/lib/Slic3r/GUI/Plater/2D.pm
deleted file mode 100644
index 88a05c292..000000000
--- a/lib/Slic3r/GUI/Plater/2D.pm
+++ /dev/null
@@ -1,372 +0,0 @@
-# 2D preview on the platter.
-# 3D objects are visualized by their convex hulls.
-
-package Slic3r::GUI::Plater::2D;
-use strict;
-use warnings;
-use utf8;
-
-use List::Util qw(min max first);
-use Slic3r::Geometry qw(X Y scale unscale convex_hull);
-use Slic3r::Geometry::Clipper qw(offset JT_ROUND intersection_pl);
-use Wx qw(wxTheApp :misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL);
-use Wx::Event qw(EVT_MOUSE_EVENTS EVT_PAINT EVT_ERASE_BACKGROUND EVT_SIZE);
-use base 'Wx::Panel';
-
-use Wx::Locale gettext => 'L';
-
-sub new {
- my $class = shift;
- my ($parent, $size, $objects, $model, $config) = @_;
-
- my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, $size, wxTAB_TRAVERSAL);
- # This has only effect on MacOS. On Windows and Linux/GTK, the background is painted by $self->repaint().
- $self->SetBackgroundColour(Wx::wxWHITE);
-
- $self->{objects} = $objects;
- $self->{model} = $model;
- $self->{config} = $config;
- $self->{on_select_object} = sub {};
- $self->{on_double_click} = sub {};
- $self->{on_right_click} = sub {};
- $self->{on_instances_moved} = sub {};
-
- $self->{objects_brush} = Wx::Brush->new(Wx::Colour->new(210,210,210), wxSOLID);
- $self->{selected_brush} = Wx::Brush->new(Wx::Colour->new(255,128,128), wxSOLID);
- $self->{dragged_brush} = Wx::Brush->new(Wx::Colour->new(128,128,255), wxSOLID);
- $self->{transparent_brush} = Wx::Brush->new(Wx::Colour->new(0,0,0), wxTRANSPARENT);
- $self->{grid_pen} = Wx::Pen->new(Wx::Colour->new(230,230,230), 1, wxSOLID);
- $self->{print_center_pen} = Wx::Pen->new(Wx::Colour->new(200,200,200), 1, wxSOLID);
- $self->{clearance_pen} = Wx::Pen->new(Wx::Colour->new(0,0,200), 1, wxSOLID);
- $self->{skirt_pen} = Wx::Pen->new(Wx::Colour->new(150,150,150), 1, wxSOLID);
-
- $self->{user_drawn_background} = $^O ne 'darwin';
-
- EVT_PAINT($self, \&repaint);
- EVT_ERASE_BACKGROUND($self, sub {}) if $self->{user_drawn_background};
- EVT_MOUSE_EVENTS($self, \&mouse_event);
- EVT_SIZE($self, sub {
- $self->update_bed_size;
- $self->Refresh;
- });
-
- return $self;
-}
-
-sub on_select_object {
- my ($self, $cb) = @_;
- $self->{on_select_object} = $cb;
-}
-
-sub on_double_click {
- my ($self, $cb) = @_;
- $self->{on_double_click} = $cb;
-}
-
-sub on_right_click {
- my ($self, $cb) = @_;
- $self->{on_right_click} = $cb;
-}
-
-sub on_instances_moved {
- my ($self, $cb) = @_;
- $self->{on_instances_moved} = $cb;
-}
-
-sub repaint {
- my ($self, $event) = @_;
-
- my $dc = Wx::AutoBufferedPaintDC->new($self);
- my $size = $self->GetSize;
- my @size = ($size->GetWidth, $size->GetHeight);
-
- if ($self->{user_drawn_background}) {
- # On all systems the AutoBufferedPaintDC() achieves double buffering.
- # On MacOS the background is erased, on Windows the background is not erased
- # and on Linux/GTK the background is erased to gray color.
- # Fill DC with the background on Windows & Linux/GTK.
- my $brush_background = Wx::Brush->new(Wx::wxWHITE, wxSOLID);
- $dc->SetPen(wxWHITE_PEN);
- $dc->SetBrush($brush_background);
- my $rect = $self->GetUpdateRegion()->GetBox();
- $dc->DrawRectangle($rect->GetLeft(), $rect->GetTop(), $rect->GetWidth(), $rect->GetHeight());
- }
-
- # draw grid
- $dc->SetPen($self->{grid_pen});
- $dc->DrawLine(map @$_, @$_) for @{$self->{grid}};
-
- # draw bed
- {
- $dc->SetPen($self->{print_center_pen});
- $dc->SetBrush($self->{transparent_brush});
- $dc->DrawPolygon($self->scaled_points_to_pixel($self->{bed_polygon}, 1), 0, 0);
- }
-
- # draw print center
- if (@{$self->{objects}} && wxTheApp->{app_config}->get("autocenter")) {
- my $center = $self->unscaled_point_to_pixel($self->{print_center});
- $dc->SetPen($self->{print_center_pen});
- $dc->DrawLine($center->[X], 0, $center->[X], $size[Y]);
- $dc->DrawLine(0, $center->[Y], $size[X], $center->[Y]);
- $dc->SetTextForeground(Wx::Colour->new(0,0,0));
- $dc->SetFont(Wx::Font->new(10, wxDEFAULT, wxNORMAL, wxNORMAL));
- $dc->DrawLabel("X = " . sprintf('%.0f', $self->{print_center}->[X]), Wx::Rect->new(0, 0, $center->[X]*2, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM);
- $dc->DrawRotatedText("Y = " . sprintf('%.0f', $self->{print_center}->[Y]), 0, $center->[Y]+15, 90);
- }
-
- # draw frame
- if (0) {
- $dc->SetPen(wxBLACK_PEN);
- $dc->SetBrush($self->{transparent_brush});
- $dc->DrawRectangle(0, 0, @size);
- }
-
- # draw text if plate is empty
- if (!@{$self->{objects}}) {
- $dc->SetTextForeground(Wx::Colour->new(150,50,50));
- $dc->SetFont(Wx::Font->new(14, wxDEFAULT, wxNORMAL, wxNORMAL));
- $dc->DrawLabel(
- join('-', +(localtime)[3,4]) eq '13-8'
- ? L('What do you want to print today? ™') # Sept. 13, 2006. The first part ever printed by a RepRap to make another RepRap.
- : L('Drag your objects here'),
- Wx::Rect->new(0, 0, $self->GetSize->GetWidth, $self->GetSize->GetHeight), wxALIGN_CENTER_HORIZONTAL | wxALIGN_CENTER_VERTICAL);
- }
-
- # draw thumbnails
- $dc->SetPen(wxBLACK_PEN);
- $self->clean_instance_thumbnails;
- for my $obj_idx (0 .. $#{$self->{objects}}) {
- my $object = $self->{objects}[$obj_idx];
- my $model_object = $self->{model}->objects->[$obj_idx];
- next unless defined $object->thumbnail;
- for my $instance_idx (0 .. $#{$model_object->instances}) {
- my $instance = $model_object->instances->[$instance_idx];
- next if !defined $object->transformed_thumbnail;
-
- my $thumbnail = $object->transformed_thumbnail->clone; # in scaled model coordinates
- $thumbnail->translate(map scale($_), @{$instance->offset});
-
- $object->instance_thumbnails->[$instance_idx] = $thumbnail;
-
- if (defined $self->{drag_object} && $self->{drag_object}[0] == $obj_idx && $self->{drag_object}[1] == $instance_idx) {
- $dc->SetBrush($self->{dragged_brush});
- } elsif ($object->selected) {
- $dc->SetBrush($self->{selected_brush});
- } else {
- $dc->SetBrush($self->{objects_brush});
- }
- foreach my $expolygon (@$thumbnail) {
- foreach my $points (@{$expolygon->pp}) {
- $dc->DrawPolygon($self->scaled_points_to_pixel($points, 1), 0, 0);
- }
- }
-
- if (0) {
- # draw bounding box for debugging purposes
- my $bb = $model_object->instance_bounding_box($instance_idx);
- $bb->scale($self->{scaling_factor});
- # no need to translate by instance offset because instance_bounding_box() does that
- my $points = $bb->polygon->pp;
- $dc->SetPen($self->{clearance_pen});
- $dc->SetBrush($self->{transparent_brush});
- $dc->DrawPolygon($self->_y($points), 0, 0);
- }
-
- # if sequential printing is enabled and we have more than one object, draw clearance area
- if ($self->{config}->complete_objects && (map @{$_->instances}, @{$self->{model}->objects}) > 1) {
- my ($clearance) = @{offset([$thumbnail->convex_hull], (scale($self->{config}->extruder_clearance_radius) / 2), JT_ROUND, scale(0.1))};
- $dc->SetPen($self->{clearance_pen});
- $dc->SetBrush($self->{transparent_brush});
- $dc->DrawPolygon($self->scaled_points_to_pixel($clearance, 1), 0, 0);
- }
- }
- }
-
- # draw skirt
- if (@{$self->{objects}} && $self->{config}->skirts) {
- my @points = map @{$_->contour}, map @$_, map @{$_->instance_thumbnails}, @{$self->{objects}};
- if (@points >= 3) {
- my ($convex_hull) = @{offset([convex_hull(\@points)], scale max($self->{config}->brim_width + $self->{config}->skirt_distance), JT_ROUND, scale(0.1))};
- $dc->SetPen($self->{skirt_pen});
- $dc->SetBrush($self->{transparent_brush});
- $dc->DrawPolygon($self->scaled_points_to_pixel($convex_hull, 1), 0, 0);
- }
- }
-
- $event->Skip;
-}
-
-sub mouse_event {
- my ($self, $event) = @_;
- my $pos = $event->GetPosition;
- my $point = $self->point_to_model_units([ $pos->x, $pos->y ]); #]]
- if ($event->ButtonDown) {
- $self->{on_select_object}->(undef);
- # traverse objects and instances in reverse order, so that if they're overlapping
- # we get the one that gets drawn last, thus on top (as user expects that to move)
- OBJECTS: for my $obj_idx (reverse 0 .. $#{$self->{objects}}) {
- my $object = $self->{objects}->[$obj_idx];
- for my $instance_idx (reverse 0 .. $#{ $object->instance_thumbnails }) {
- my $thumbnail = $object->instance_thumbnails->[$instance_idx];
- if (defined first { $_->contour->contains_point($point) } @$thumbnail) {
- $self->{on_select_object}->($obj_idx);
-
- if ($event->LeftDown) {
- # start dragging
- my $instance = $self->{model}->objects->[$obj_idx]->instances->[$instance_idx];
- my $instance_origin = [ map scale($_), @{$instance->offset} ];
- $self->{drag_start_pos} = [ # displacement between the click and the instance origin in scaled model units
- $point->x - $instance_origin->[X],
- $point->y - $instance_origin->[Y], #-
- ];
- $self->{drag_object} = [ $obj_idx, $instance_idx ];
- } elsif ($event->RightDown) {
- $self->{on_right_click}->($pos->x, $pos->y);
- }
-
- last OBJECTS;
- }
- }
- }
- $self->Refresh;
- } elsif ($event->LeftUp) {
- if ($self->{drag_object}) {
- $self->{on_instances_moved}->();
- }
- $self->{drag_start_pos} = undef;
- $self->{drag_object} = undef;
- $self->SetCursor(wxSTANDARD_CURSOR);
- } elsif ($event->LeftDClick) {
- $self->{on_double_click}->();
- } elsif ($event->Dragging) {
- return if !$self->{drag_start_pos}; # concurrency problems
- my ($obj_idx, $instance_idx) = @{ $self->{drag_object} };
- my $model_object = $self->{model}->objects->[$obj_idx];
- $model_object->instances->[$instance_idx]->set_offset(
- Slic3r::Pointf->new(
- unscale($point->[X] - $self->{drag_start_pos}[X]),
- unscale($point->[Y] - $self->{drag_start_pos}[Y]),
- ));
- $self->Refresh;
- } elsif ($event->Moving) {
- my $cursor = wxSTANDARD_CURSOR;
- if (defined first { $_->contour->contains_point($point) } map @$_, map @{$_->instance_thumbnails}, @{ $self->{objects} }) {
- $cursor = Wx::Cursor->new(wxCURSOR_HAND);
- }
- $self->SetCursor($cursor);
- }
-}
-
-sub update_bed_size {
- my ($self) = @_;
-
- # when the canvas is not rendered yet, its GetSize() method returns 0,0
- my $canvas_size = $self->GetSize;
- my ($canvas_w, $canvas_h) = ($canvas_size->GetWidth, $canvas_size->GetHeight);
- return if $canvas_w == 0;
-
- # get bed shape polygon
- $self->{bed_polygon} = my $polygon = Slic3r::Polygon->new_scale(@{$self->{config}->bed_shape});
- my $bb = $polygon->bounding_box;
- my $size = $bb->size;
-
- # calculate the scaling factor needed for constraining print bed area inside preview
- # scaling_factor is expressed in pixel / mm
- $self->{scaling_factor} = min($canvas_w / unscale($size->x), $canvas_h / unscale($size->y)); #)
-
- # calculate the displacement needed to center bed
- $self->{bed_origin} = [
- $canvas_w/2 - (unscale($bb->x_max + $bb->x_min)/2 * $self->{scaling_factor}),
- $canvas_h - ($canvas_h/2 - (unscale($bb->y_max + $bb->y_min)/2 * $self->{scaling_factor})),
- ];
-
- # calculate print center
- my $center = $bb->center;
- $self->{print_center} = [ unscale($center->x), unscale($center->y) ]; #))
-
- # cache bed contours and grid
- {
- 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]);
- }
- @polylines = @{intersection_pl(\@polylines, [$polygon])};
- $self->{grid} = [ map $self->scaled_points_to_pixel([ @$_[0,-1] ], 1), @polylines ];
- }
-}
-
-sub clean_instance_thumbnails {
- my ($self) = @_;
-
- foreach my $object (@{ $self->{objects} }) {
- @{ $object->instance_thumbnails } = ();
- }
-}
-
-# convert a model coordinate into a pixel coordinate
-sub unscaled_point_to_pixel {
- my ($self, $point) = @_;
-
- my $canvas_height = $self->GetSize->GetHeight;
- my $zero = $self->{bed_origin};
- return [
- $point->[X] * $self->{scaling_factor} + $zero->[X],
- $canvas_height - $point->[Y] * $self->{scaling_factor} + ($zero->[Y] - $canvas_height),
- ];
-}
-
-sub scaled_points_to_pixel {
- my ($self, $points, $unscale) = @_;
-
- my $result = [];
- foreach my $point (@$points) {
- $point = [ map unscale($_), @$point ] if $unscale;
- push @$result, $self->unscaled_point_to_pixel($point);
- }
- return $result;
-}
-
-sub point_to_model_units {
- my ($self, $point) = @_;
-
- my $zero = $self->{bed_origin};
- return Slic3r::Point->new(
- scale ($point->[X] - $zero->[X]) / $self->{scaling_factor},
- scale ($zero->[Y] - $point->[Y]) / $self->{scaling_factor},
- );
-}
-
-sub reload_scene {
- my ($self, $force) = @_;
-
- if (! $self->IsShown && ! $force) {
- $self->{reload_delayed} = 1;
- return;
- }
-
- $self->{reload_delayed} = 0;
-
- foreach my $obj_idx (0..$#{$self->{model}->objects}) {
- my $plater_object = $self->{objects}[$obj_idx];
- next if $plater_object->thumbnail;
- # The thumbnail is not valid, update it with a convex hull of an object.
- $plater_object->thumbnail(Slic3r::ExPolygon::Collection->new);
- $plater_object->make_thumbnail($self->{model}, $obj_idx);
- $plater_object->transform_thumbnail($self->{model}, $obj_idx);
- }
-
- $self->Refresh;
-}
-
-# Called by the Platter wxNotebook when this page is activated.
-sub OnActivate {
- my ($self) = @_;
- $self->reload_scene(1) if ($self->{reload_delayed});
-}
-
-1;
diff --git a/lib/Slic3r/GUI/Plater/2DToolpaths.pm b/lib/Slic3r/GUI/Plater/2DToolpaths.pm
deleted file mode 100644
index bcd1aeed4..000000000
--- a/lib/Slic3r/GUI/Plater/2DToolpaths.pm
+++ /dev/null
@@ -1,910 +0,0 @@
-# 2D preview of the tool paths of a single layer, using a thin line.
-# OpenGL is used to render the paths.
-# Vojtech also added a 2D simulation of under/over extrusion in a single layer.
-
-package Slic3r::GUI::Plater::2DToolpaths;
-use strict;
-use warnings;
-use utf8;
-
-use Slic3r::Print::State ':steps';
-use Wx qw(:misc :sizer :slider :statictext :keycode wxWHITE wxWANTS_CHARS);
-use Wx::Event qw(EVT_SLIDER EVT_KEY_DOWN);
-use base qw(Wx::Panel Class::Accessor);
-
-__PACKAGE__->mk_accessors(qw(print enabled));
-
-sub new {
- my $class = shift;
- my ($parent, $print) = @_;
-
- my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS);
- $self->SetBackgroundColour(wxWHITE);
-
- # init GUI elements
- my $canvas = $self->{canvas} = Slic3r::GUI::Plater::2DToolpaths::Canvas->new($self, $print);
- my $slider = $self->{slider} = Wx::Slider->new(
- $self, -1,
- 0, # default
- 0, # min
- # we set max to a bogus non-zero value because the MSW implementation of wxSlider
- # will skip drawing the slider if max <= min:
- 1, # max
- wxDefaultPosition,
- wxDefaultSize,
- wxVERTICAL | wxSL_INVERSE,
- );
- my $z_label = $self->{z_label} = Wx::StaticText->new($self, -1, "", wxDefaultPosition,
- [40,-1], wxALIGN_CENTRE_HORIZONTAL);
- $z_label->SetFont($Slic3r::GUI::small_font);
-
- my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
- $vsizer->Add($slider, 1, wxALL | wxEXPAND | wxALIGN_CENTER, 3);
- $vsizer->Add($z_label, 0, wxALL | wxEXPAND | wxALIGN_CENTER, 3);
-
- my $sizer = Wx::BoxSizer->new(wxHORIZONTAL);
- $sizer->Add($canvas, 1, wxALL | wxEXPAND, 0);
- $sizer->Add($vsizer, 0, wxTOP | wxBOTTOM | wxEXPAND, 5);
-
- EVT_SLIDER($self, $slider, sub {
- $self->set_z($self->{layers_z}[$slider->GetValue])
- if $self->enabled;
- });
- EVT_KEY_DOWN($canvas, sub {
- my ($s, $event) = @_;
- if ($event->HasModifiers) {
- $event->Skip;
- } else {
- my $key = $event->GetKeyCode;
- if ($key == ord('D') || $key == WXK_LEFT) {
- # Keys: 'D' or WXK_LEFT
- $slider->SetValue($slider->GetValue - 1);
- $self->set_z($self->{layers_z}[$slider->GetValue]);
- } elsif ($key == ord('U') || $key == WXK_RIGHT) {
- # Keys: 'U' or WXK_RIGHT
- $slider->SetValue($slider->GetValue + 1);
- $self->set_z($self->{layers_z}[$slider->GetValue]);
- } elsif ($key >= ord('1') && $key <= ord('3')) {
- # Keys: '1' to '3'
- $canvas->set_simulation_mode($key - ord('1'));
- } else {
- $event->Skip;
- }
- }
- });
-
- $self->SetSizer($sizer);
- $self->SetMinSize($self->GetSize);
- $sizer->SetSizeHints($self);
-
- # init print
- $self->{print} = $print;
- $self->reload_print;
-
- return $self;
-}
-
-sub reload_print {
- my ($self) = @_;
-
- # we require that there's at least one object and the posSlice step
- # is performed on all of them (this ensures that _shifted_copies was
- # populated and we know the number of layers)
- if (!$self->print->object_step_done(STEP_SLICE)) {
- $self->enabled(0);
- $self->{slider}->Hide;
- $self->{canvas}->Refresh; # clears canvas
- return;
- }
-
- $self->{canvas}->bb($self->print->total_bounding_box);
- $self->{canvas}->_dirty(1);
-
- my %z = (); # z => 1
- foreach my $object (@{$self->{print}->objects}) {
- foreach my $layer (@{$object->layers}, @{$object->support_layers}) {
- $z{$layer->print_z} = 1;
- }
- }
- $self->enabled(1);
- $self->{layers_z} = [ sort { $a <=> $b } keys %z ];
- $self->{slider}->SetRange(0, scalar(@{$self->{layers_z}})-1);
- if ((my $z_idx = $self->{slider}->GetValue) <= $#{$self->{layers_z}}) {
- $self->set_z($self->{layers_z}[$z_idx]);
- } else {
- $self->{slider}->SetValue(0);
- $self->set_z($self->{layers_z}[0]) if @{$self->{layers_z}};
- }
- $self->{slider}->Show;
- $self->Layout;
-}
-
-sub set_z {
- my ($self, $z) = @_;
-
- return if !$self->enabled;
- $self->{z_label}->SetLabel(sprintf '%.2f', $z);
- $self->{canvas}->set_z($z);
-}
-
-
-package Slic3r::GUI::Plater::2DToolpaths::Canvas;
-
-use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_IDLE EVT_MOUSEWHEEL EVT_MOUSE_EVENTS);
-use OpenGL qw(:glconstants :glfunctions :glufunctions :gluconstants);
-use base qw(Wx::GLCanvas Class::Accessor);
-use Wx::GLCanvas qw(:all);
-use List::Util qw(min max first);
-use Slic3r::Geometry qw(scale epsilon X Y);
-use Slic3r::Print::State ':steps';
-
-__PACKAGE__->mk_accessors(qw(
- print z layers color init
- bb
- _camera_bb
- _dirty
- _zoom
- _camera_target
- _drag_start_xy
- _texture_name
- _texture_size
- _extrusion_simulator
- _simulation_mode
-));
-
-sub new {
- my ($class, $parent, $print) = @_;
-
- my $self = (Wx::wxVERSION >= 3.000003) ?
- # The wxWidgets 3.0.3-beta have a bug, they crash with NULL attribute list.
- $class->SUPER::new($parent, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize, 0, "",
- [WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, 0]) :
- $class->SUPER::new($parent);
- # Immediatelly force creation of the OpenGL context to consume the static variable s_wglContextAttribs.
- $self->GetContext();
- $self->print($print);
- $self->_zoom(1);
-
- # 2D point in model space
- $self->_camera_target(Slic3r::Pointf->new(0,0));
-
- # Texture for the extrusion simulator. The texture will be allocated / reallocated on Resize.
- $self->_texture_name(0);
- $self->_texture_size(Slic3r::Point->new(0,0));
- $self->_extrusion_simulator(Slic3r::ExtrusionSimulator->new());
- $self->_simulation_mode(0);
-
- EVT_PAINT($self, sub {
- my $dc = Wx::PaintDC->new($self);
- $self->Render($dc);
- });
- EVT_SIZE($self, sub { $self->_dirty(1) });
- EVT_IDLE($self, sub {
- return unless $self->_dirty;
- return if !$self->IsShownOnScreen;
- $self->Resize;
- $self->Refresh;
- });
- EVT_MOUSEWHEEL($self, sub {
- my ($self, $e) = @_;
-
- return if !$self->GetParent->enabled;
-
- my $old_zoom = $self->_zoom;
-
- # Calculate the zoom delta and apply it to the current zoom factor
- my $zoom = -$e->GetWheelRotation() / $e->GetWheelDelta();
- $zoom = max(min($zoom, 4), -4);
- $zoom /= 10;
- $self->_zoom($self->_zoom / (1-$zoom));
- $self->_zoom(1.25) if $self->_zoom > 1.25; # prevent from zooming out too much
-
- {
- # In order to zoom around the mouse point we need to translate
- # the camera target. This math is almost there but not perfect yet...
- my $camera_bb_size = $self->_camera_bb->size;
- my $size = Slic3r::Pointf->new($self->GetSizeWH);
- my $pos = Slic3r::Pointf->new($e->GetPositionXY);
-
- # calculate the zooming center in pixel coordinates relative to the viewport center
- my $vec = Slic3r::Pointf->new($pos->x - $size->x/2, $pos->y - $size->y/2); #-
-
- # calculate where this point will end up after applying the new zoom
- my $vec2 = $vec->clone;
- $vec2->scale($old_zoom / $self->_zoom);
-
- # move the camera target by the difference of the two positions
- $self->_camera_target->translate(
- -($vec->x - $vec2->x) * $camera_bb_size->x / $size->x,
- ($vec->y - $vec2->y) * $camera_bb_size->y / $size->y, #//
- );
- }
-
- $self->_dirty(1);
- });
- EVT_MOUSE_EVENTS($self, \&mouse_event);
-
- return $self;
-}
-
-sub Destroy {
- my ($self) = @_;
-
- # Deallocate the OpenGL resources.
- my $context = $self->GetContext;
- if ($context and $self->texture_id) {
- $self->SetCurrent($context);
- glDeleteTextures(1, ($self->texture_id));
- $self->SetCurrent(0);
- $self->texture_id(0);
- $self->texture_size(new Slic3r::Point(0, 0));
- }
- return $self->SUPER::Destroy;
-}
-
-sub mouse_event {
- my ($self, $e) = @_;
-
- return if !$self->GetParent->enabled;
-
- my $pos = Slic3r::Pointf->new($e->GetPositionXY);
- if ($e->Entering && (&Wx::wxMSW || $^O eq 'linux')) {
- # wxMSW and Linux needs focus in order to catch key events
- $self->SetFocus;
- } elsif ($e->Dragging) {
- if ($e->LeftIsDown || $e->MiddleIsDown || $e->RightIsDown) {
- # if dragging, translate view
-
- if (defined $self->_drag_start_xy) {
- my $move = $self->_drag_start_xy->vector_to($pos); # in pixels
-
- # get viewport and camera size in order to convert pixel to model units
- my ($x, $y) = $self->GetSizeWH;
- my $camera_bb_size = $self->_camera_bb->size;
-
- # compute translation in model units
- $self->_camera_target->translate(
- -$move->x * $camera_bb_size->x / $x,
- $move->y * $camera_bb_size->y / $y, # /**
- );
-
- $self->_dirty(1);
- }
- $self->_drag_start_xy($pos);
- }
- } elsif ($e->LeftUp || $e->MiddleUp || $e->RightUp) {
- $self->_drag_start_xy(undef);
- } else {
- $e->Skip();
- }
-}
-
-sub set_z {
- my ($self, $z) = @_;
-
- my $print = $self->print;
-
- # can we have interlaced layers?
- my $interlaced = (defined first { $_->config->support_material } @{$print->objects})
- || (defined first { $_->config->infill_every_layers > 1 } @{$print->regions});
-
- my $max_layer_height = $print->max_allowed_layer_height;
-
- my @layers = ();
- foreach my $object (@{$print->objects}) {
- foreach my $layer (@{$object->layers}, @{$object->support_layers}) {
- if ($interlaced) {
- push @layers, $layer
- if $z > ($layer->print_z - $max_layer_height - epsilon)
- && $z <= $layer->print_z + epsilon;
- } else {
- push @layers, $layer if abs($layer->print_z - $z) < epsilon;
- }
- }
- }
-
- # reverse layers so that we draw the lowermost (i.e. current) on top
- $self->z($z);
- $self->layers([ reverse @layers ]);
- $self->Refresh;
-}
-
-sub set_simulation_mode
-{
- my ($self, $mode) = @_;
- $self->_simulation_mode($mode);
- $self->_dirty(1);
- $self->Refresh;
-}
-
-sub Render {
- my ($self, $dc) = @_;
-
- # prevent calling SetCurrent() when window is not shown yet
- return unless $self->IsShownOnScreen;
- return unless my $context = $self->GetContext;
- $self->SetCurrent($context);
- $self->InitGL;
-
- glClearColor(1, 1, 1, 0);
- glClear(GL_COLOR_BUFFER_BIT);
-
- if (!$self->GetParent->enabled || !$self->layers) {
- $self->SwapBuffers;
- return;
- }
-
- glDisable(GL_DEPTH_TEST);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- if ($self->_simulation_mode and $self->_texture_name and $self->_texture_size->x() > 0 and $self->_texture_size->y() > 0) {
- $self->_simulate_extrusion();
- my ($x, $y) = $self->GetSizeWH;
- glEnable(GL_TEXTURE_2D);
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_REPLACE);
- glBindTexture(GL_TEXTURE_2D, $self->_texture_name);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexImage2D_c(GL_TEXTURE_2D,
- 0, # level (0 normal, heighr is form mip-mapping)
- GL_RGBA, # internal format
- $self->_texture_size->x(), $self->_texture_size->y(),
- 0, # border
- GL_RGBA, # format RGBA color data
- GL_UNSIGNED_BYTE, # unsigned byte data
- $self->_extrusion_simulator->image_ptr()); # ptr to texture data
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glOrtho(0, 1, 0, 1, 0, 1);
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0);
- glVertex2f(0, 0);
- glTexCoord2f($x/$self->_texture_size->x(), 0);
- glVertex2f(1, 0);
- glTexCoord2f($x/$self->_texture_size->x(), $y/$self->_texture_size->y());
- glVertex2f(1, 1);
- glTexCoord2f(0, $y/$self->_texture_size->y());
- glVertex2f(0, 1);
- glEnd();
- glPopMatrix();
- glBindTexture(GL_TEXTURE_2D, 0);
- }
-
- # anti-alias
- if (0) {
- glEnable(GL_LINE_SMOOTH);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
- glHint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
- }
-
- # Tesselator triangulates polygons with holes on the fly for the rendering purposes only.
- my $tess;
- if ($self->_simulation_mode() == 0 and !(&Wx::wxMSW && $OpenGL::VERSION < 0.6704)) {
- # We can't use the GLU tesselator on MSW with older OpenGL versions
- # because of an upstream bug:
- # http://sourceforge.net/p/pogl/bugs/16/
- $tess = gluNewTess();
- gluTessCallback($tess, GLU_TESS_BEGIN, 'DEFAULT');
- gluTessCallback($tess, GLU_TESS_END, 'DEFAULT');
- gluTessCallback($tess, GLU_TESS_VERTEX, 'DEFAULT');
- gluTessCallback($tess, GLU_TESS_COMBINE, 'DEFAULT');
- gluTessCallback($tess, GLU_TESS_ERROR, 'DEFAULT');
- gluTessCallback($tess, GLU_TESS_EDGE_FLAG, 'DEFAULT');
- }
-
- foreach my $layer (@{$self->layers}) {
- my $object = $layer->object;
-
- # only draw the slice for the current layer
- next unless abs($layer->print_z - $self->z) < epsilon;
-
- # draw slice contour
- glLineWidth(1);
- foreach my $copy (@{ $object->_shifted_copies }) {
- glPushMatrix();
- glTranslatef(@$copy, 0);
-
- foreach my $slice (@{$layer->slices}) {
- glColor3f(0.95, 0.95, 0.95);
-
- if ($tess) {
- gluTessBeginPolygon($tess);
- foreach my $polygon (@$slice) {
- gluTessBeginContour($tess);
- gluTessVertex_p($tess, @$_, 0) for @$polygon;
- gluTessEndContour($tess);
- }
- gluTessEndPolygon($tess);
- }
-
- glColor3f(0.9, 0.9, 0.9);
- foreach my $polygon (@$slice) {
- foreach my $line (@{$polygon->lines}) {
- glBegin(GL_LINES);
- glVertex2f(@{$line->a});
- glVertex2f(@{$line->b});
- glEnd();
- }
- }
- }
- glPopMatrix();
- }
- }
-
- my $skirt_drawn = 0;
- my $brim_drawn = 0;
- foreach my $layer (@{$self->layers}) {
- my $object = $layer->object;
- my $print_z = $layer->print_z;
-
- # draw brim
- if ($self->print->step_done(STEP_BRIM) && $layer->id == 0 && !$brim_drawn) {
- $self->color([0, 0, 0]);
- $self->_draw(undef, $print_z, $_) for @{$self->print->brim};
- $brim_drawn = 1;
- }
- if ($self->print->step_done(STEP_SKIRT)
- && ($self->print->has_infinite_skirt() || $self->print->config->skirt_height > $layer->id)
- && !$skirt_drawn) {
- $self->color([0, 0, 0]);
- $self->_draw(undef, $print_z, $_) for @{$self->print->skirt};
- $skirt_drawn = 1;
- }
-
- foreach my $layerm (@{$layer->regions}) {
- if ($object->step_done(STEP_PERIMETERS)) {
- $self->color([0.7, 0, 0]);
- $self->_draw($object, $print_z, $_) for map @$_, @{$layerm->perimeters};
- }
-
- if ($object->step_done(STEP_INFILL)) {
- $self->color([0, 0, 0.7]);
- $self->_draw($object, $print_z, $_) for map @$_, @{$layerm->fills};
- }
- }
-
- if ($object->step_done(STEP_SUPPORTMATERIAL)) {
- if ($layer->isa('Slic3r::Layer::Support')) {
- $self->color([0, 0, 0]);
- $self->_draw($object, $print_z, $_) for @{$layer->support_fills};
- }
- }
- }
-
- gluDeleteTess($tess) if $tess;
- $self->SwapBuffers;
-}
-
-sub _draw {
- my ($self, $object, $print_z, $path) = @_;
-
- my @paths = ($path->isa('Slic3r::ExtrusionLoop') || $path->isa('Slic3r::ExtrusionMultiPath'))
- ? @$path
- : ($path);
-
- $self->_draw_path($object, $print_z, $_) for @paths;
-}
-
-sub _draw_path {
- my ($self, $object, $print_z, $path) = @_;
-
- return if $print_z - $path->height > $self->z - epsilon;
-
- if (abs($print_z - $self->z) < epsilon) {
- glColor3f(@{$self->color});
- } else {
- glColor3f(0.8, 0.8, 0.8);
- }
-
- glLineWidth(1);
-
- if (defined $object) {
- foreach my $copy (@{ $object->_shifted_copies }) {
- glPushMatrix();
- glTranslatef(@$copy, 0);
- foreach my $line (@{$path->polyline->lines}) {
- glBegin(GL_LINES);
- glVertex2f(@{$line->a});
- glVertex2f(@{$line->b});
- glEnd();
- }
- glPopMatrix();
- }
- } else {
- foreach my $line (@{$path->polyline->lines}) {
- glBegin(GL_LINES);
- glVertex2f(@{$line->a});
- glVertex2f(@{$line->b});
- glEnd();
- }
- }
-}
-
-sub _simulate_extrusion {
- my ($self) = @_;
- $self->_extrusion_simulator->reset_accumulator();
- foreach my $layer (@{$self->layers}) {
- if (abs($layer->print_z - $self->z) < epsilon) {
- my $object = $layer->object;
- my @shifts = (defined $object) ? @{$object->_shifted_copies} : (Slic3r::Point->new(0, 0));
- foreach my $layerm (@{$layer->regions}) {
- my @extrusions = ();
- if ($object->step_done(STEP_PERIMETERS)) {
- push @extrusions, @$_ for @{$layerm->perimeters};
- }
- if ($object->step_done(STEP_INFILL)) {
- push @extrusions, @$_ for @{$layerm->fills};
- }
- foreach my $extrusion_entity (@extrusions) {
- my @paths = ($extrusion_entity->isa('Slic3r::ExtrusionLoop') || $extrusion_entity->isa('Slic3r::ExtrusionMultiPath'))
- ? @$extrusion_entity
- : ($extrusion_entity);
- foreach my $path (@paths) {
- print "width: ", $path->width,
- " height: ", $path->height,
- " mm3_per_mm: ", $path->mm3_per_mm,
- " height2: ", $path->mm3_per_mm / $path->height,
- "\n";
- $self->_extrusion_simulator->extrude_to_accumulator($path, $_, $self->_simulation_mode()) for @shifts;
- }
- }
- }
- }
- }
- $self->_extrusion_simulator->evaluate_accumulator($self->_simulation_mode());
-}
-
-sub InitGL {
- my $self = shift;
-
- return if $self->init;
- return unless $self->GetContext;
-
- my $texture_id = 0;
- ($texture_id) = glGenTextures_p(1);
- $self->_texture_name($texture_id);
- $self->init(1);
-}
-
-sub GetContext {
- my ($self) = @_;
- return $self->{context} ||= Wx::GLContext->new($self);
-}
-
-sub SetCurrent {
- my ($self, $context) = @_;
- return $self->SUPER::SetCurrent($context);
-}
-
-sub Resize {
- my ($self) = @_;
-
- return unless $self->GetContext;
- return unless $self->bb;
- $self->_dirty(0);
-
- $self->SetCurrent($self->GetContext);
- my ($x, $y) = $self->GetSizeWH;
-
- if ($self->_texture_size->x() < $x or $self->_texture_size->y() < $y) {
- # Allocate a large enough OpenGL texture with power of 2 dimensions.
- $self->_texture_size->set_x(1) if ($self->_texture_size->x() == 0);
- $self->_texture_size->set_y(1) if ($self->_texture_size->y() == 0);
- $self->_texture_size->set_x($self->_texture_size->x() * 2) while ($self->_texture_size->x() < $x);
- $self->_texture_size->set_y($self->_texture_size->y() * 2) while ($self->_texture_size->y() < $y);
- #print "screen size ", $x, "x", $y;
- #print "texture size ", $self->_texture_size->x(), "x", $self->_texture_size->y();
- # Initialize an empty texture.
- glBindTexture(GL_TEXTURE_2D, $self->_texture_name);
- if (1) {
- glTexImage2D_c(GL_TEXTURE_2D,
- 0, # level (0 normal, heighr is form mip-mapping)
- GL_RGBA, # internal format
- $self->_texture_size->x(), $self->_texture_size->y(),
- 0, # border
- GL_RGBA, # format RGBA color data
- GL_UNSIGNED_BYTE, # unsigned byte data
- 0); # ptr to texture data
- }
- glBindTexture(GL_TEXTURE_2D, 0);
- $self->_extrusion_simulator->set_image_size($self->_texture_size);
- }
- $self->_extrusion_simulator->set_viewport(Slic3r::Geometry::BoundingBox->new_from_points(
- [Slic3r::Point->new(0, 0), Slic3r::Point->new($x, $y)]));
-
- glViewport(0, 0, $x, $y);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- my $bb = $self->bb->clone;
-
- # rescale in dependence of window aspect ratio
- my $bb_size = $bb->size;
- my $ratio_x = ($x != 0.0) ? $bb_size->x / $x : 1.0;
- my $ratio_y = ($y != 0.0) ? $bb_size->y / $y : 1.0;
-
- if ($ratio_y < $ratio_x) {
- if ($ratio_y != 0.0) {
- my $new_size_y = $bb_size->y * $ratio_x / $ratio_y;
- my $half_delta_size_y = 0.5 * ($new_size_y - $bb_size->y);
- $bb->set_y_min($bb->y_min - $half_delta_size_y);
- $bb->set_y_max($bb->y_max + $half_delta_size_y);
- }
- } elsif ($ratio_x < $ratio_y) {
- if ($ratio_x != 0.0) {
- my $new_size_x = $bb_size->x * $ratio_y / $ratio_x;
- my $half_delta_size_x = 0.5 * ($new_size_x - $bb_size->x);
- $bb->set_x_min($bb->x_min - $half_delta_size_x);
- $bb->set_x_max($bb->x_max + $half_delta_size_x);
- }
- }
-
- # center bounding box around origin before scaling it
- my $bb_center = $bb->center;
- $bb->translate(@{$bb_center->negative});
-
- # scale bounding box according to zoom factor
- $bb->scale($self->_zoom);
-
- # reposition bounding box around original center
- $bb->translate(@{$bb_center});
-
- # translate camera
- $bb->translate(@{$self->_camera_target});
-
-# # keep camera_bb within total bb
-# # (i.e. prevent user from panning outside the bounding box)
-# {
-# my @translate = (0,0);
-# if ($bb->x_min < $self->bb->x_min) {
-# $translate[X] += $self->bb->x_min - $bb->x_min;
-# }
-# if ($bb->y_min < $self->bb->y_min) {
-# $translate[Y] += $self->bb->y_min - $bb->y_min;
-# }
-# if ($bb->x_max > $self->bb->x_max) {
-# $translate[X] -= $bb->x_max - $self->bb->x_max;
-# }
-# if ($bb->y_max > $self->bb->y_max) {
-# $translate[Y] -= $bb->y_max - $self->bb->y_max;
-# }
-# $self->_camera_target->translate(@translate);
-# $bb->translate(@translate);
-# }
-
- # save camera
- $self->_camera_bb($bb);
-
- my ($x1, $y1, $x2, $y2) = ($bb->x_min, $bb->y_min, $bb->x_max, $bb->y_max);
- if (($x2 - $x1)/($y2 - $y1) > $x/$y) {
- # adjust Y
- my $new_y = $y * ($x2 - $x1) / $x;
- $y1 = ($y2 + $y1)/2 - $new_y/2;
- $y2 = $y1 + $new_y;
- } else {
- my $new_x = $x * ($y2 - $y1) / $y;
- $x1 = ($x2 + $x1)/2 - $new_x/2;
- $x2 = $x1 + $new_x;
- }
- glOrtho($x1, $x2, $y1, $y2, 0, 1);
-
- # Set the adjusted bounding box at the extrusion simulator.
- #print "Scene bbox ", $bb->x_min, ",", $bb->y_min, " ", $bb->x_max, ",", $bb->y_max, "\n";
- #print "Setting simulator bbox ", $x1, ",", $y1, " ", $x2, ",", $y2, "\n";
- $self->_extrusion_simulator->set_bounding_box(
- Slic3r::Geometry::BoundingBox->new_from_points(
- [Slic3r::Point->new($x1, $y1), Slic3r::Point->new($x2, $y2)]));
-
- glMatrixMode(GL_MODELVIEW);
-}
-
-# Thick line drawing is not used anywhere. Probably not tested?
-sub line {
- my (
- $x1, $y1, $x2, $y2, # coordinates of the line
- $w, # width/thickness of the line in pixel
- $Cr, $Cg, $Cb, # RGB color components
- $Br, $Bg, $Bb, # color of background when alphablend=false
- # Br=alpha of color when alphablend=true
- $alphablend, # use alpha blend or not
- ) = @_;
-
- my $t;
- my $R;
- my $f = $w - int($w);
- my $A;
-
- if ($alphablend) {
- $A = $Br;
- } else {
- $A = 1;
- }
-
- # determine parameters t,R
- if ($w >= 0 && $w < 1) {
- $t = 0.05; $R = 0.48 + 0.32 * $f;
- if (!$alphablend) {
- $Cr += 0.88 * (1-$f);
- $Cg += 0.88 * (1-$f);
- $Cb += 0.88 * (1-$f);
- $Cr = 1.0 if ($Cr > 1.0);
- $Cg = 1.0 if ($Cg > 1.0);
- $Cb = 1.0 if ($Cb > 1.0);
- } else {
- $A *= $f;
- }
- } elsif ($w >= 1.0 && $w < 2.0) {
- $t = 0.05 + $f*0.33; $R = 0.768 + 0.312*$f;
- } elsif ($w >= 2.0 && $w < 3.0) {
- $t = 0.38 + $f*0.58; $R = 1.08;
- } elsif ($w >= 3.0 && $w < 4.0) {
- $t = 0.96 + $f*0.48; $R = 1.08;
- } elsif ($w >= 4.0 && $w < 5.0) {
- $t= 1.44 + $f*0.46; $R = 1.08;
- } elsif ($w >= 5.0 && $w < 6.0) {
- $t= 1.9 + $f*0.6; $R = 1.08;
- } elsif ($w >= 6.0) {
- my $ff = $w - 6.0;
- $t = 2.5 + $ff*0.50; $R = 1.08;
- }
- #printf( "w=%f, f=%f, C=%.4f\n", $w, $f, $C);
-
- # determine angle of the line to horizontal
- my $tx = 0; my $ty = 0; # core thinkness of a line
- my $Rx = 0; my $Ry = 0; # fading edge of a line
- my $cx = 0; my $cy = 0; # cap of a line
- my $ALW = 0.01;
- my $dx = $x2 - $x1;
- my $dy = $y2 - $y1;
- if (abs($dx) < $ALW) {
- # vertical
- $tx = $t; $ty = 0;
- $Rx = $R; $Ry = 0;
- if ($w > 0.0 && $w < 1.0) {
- $tx *= 8;
- } elsif ($w == 1.0) {
- $tx *= 10;
- }
- } elsif (abs($dy) < $ALW) {
- #horizontal
- $tx = 0; $ty = $t;
- $Rx = 0; $Ry = $R;
- if ($w > 0.0 && $w < 1.0) {
- $ty *= 8;
- } elsif ($w == 1.0) {
- $ty *= 10;
- }
- } else {
- if ($w < 3) { # approximate to make things even faster
- my $m = $dy/$dx;
- # and calculate tx,ty,Rx,Ry
- if ($m > -0.4142 && $m <= 0.4142) {
- # -22.5 < $angle <= 22.5, approximate to 0 (degree)
- $tx = $t * 0.1; $ty = $t;
- $Rx = $R * 0.6; $Ry = $R;
- } elsif ($m > 0.4142 && $m <= 2.4142) {
- # 22.5 < $angle <= 67.5, approximate to 45 (degree)
- $tx = $t * -0.7071; $ty = $t * 0.7071;
- $Rx = $R * -0.7071; $Ry = $R * 0.7071;
- } elsif ($m > 2.4142 || $m <= -2.4142) {
- # 67.5 < $angle <= 112.5, approximate to 90 (degree)
- $tx = $t; $ty = $t*0.1;
- $Rx = $R; $Ry = $R*0.6;
- } elsif ($m > -2.4142 && $m < -0.4142) {
- # 112.5 < angle < 157.5, approximate to 135 (degree)
- $tx = $t * 0.7071; $ty = $t * 0.7071;
- $Rx = $R * 0.7071; $Ry = $R * 0.7071;
- } else {
- # error in determining angle
- printf("error in determining angle: m=%.4f\n", $m);
- }
- } else { # calculate to exact
- $dx= $y1 - $y2;
- $dy= $x2 - $x1;
- my $L = sqrt($dx*$dx + $dy*$dy);
- $dx /= $L;
- $dy /= $L;
- $cx = -0.6*$dy; $cy=0.6*$dx;
- $tx = $t*$dx; $ty = $t*$dy;
- $Rx = $R*$dx; $Ry = $R*$dy;
- }
- }
-
- # draw the line by triangle strip
- glBegin(GL_TRIANGLE_STRIP);
- if (!$alphablend) {
- glColor3f($Br, $Bg, $Bb);
- } else {
- glColor4f($Cr, $Cg, $Cb, 0);
- }
- glVertex2f($x1 - $tx - $Rx, $y1 - $ty - $Ry); # fading edge
- glVertex2f($x2 - $tx - $Rx, $y2 - $ty - $Ry);
-
- if (!$alphablend) {
- glColor3f($Cr, $Cg, $Cb);
- } else {
- glColor4f($Cr, $Cg, $Cb, $A);
- }
- glVertex2f($x1 - $tx, $y1 - $ty); # core
- glVertex2f($x2 - $tx, $y2 - $ty);
- glVertex2f($x1 + $tx, $y1 + $ty);
- glVertex2f($x2 + $tx, $y2 + $ty);
-
- if ((abs($dx) < $ALW || abs($dy) < $ALW) && $w <= 1.0) {
- # printf("skipped one fading edge\n");
- } else {
- if (!$alphablend) {
- glColor3f($Br, $Bg, $Bb);
- } else {
- glColor4f($Cr, $Cg, $Cb, 0);
- }
- glVertex2f($x1 + $tx+ $Rx, $y1 + $ty + $Ry); # fading edge
- glVertex2f($x2 + $tx+ $Rx, $y2 + $ty + $Ry);
- }
- glEnd();
-
- # cap
- if ($w < 3) {
- # do not draw cap
- } else {
- # draw cap
- glBegin(GL_TRIANGLE_STRIP);
- if (!$alphablend) {
- glColor3f($Br, $Bg, $Bb);
- } else {
- glColor4f($Cr, $Cg, $Cb, 0);
- }
- glVertex2f($x1 - $Rx + $cx, $y1 - $Ry + $cy);
- glVertex2f($x1 + $Rx + $cx, $y1 + $Ry + $cy);
- glColor3f($Cr, $Cg, $Cb);
- glVertex2f($x1 - $tx - $Rx, $y1 - $ty - $Ry);
- glVertex2f($x1 + $tx + $Rx, $y1 + $ty + $Ry);
- glEnd();
- glBegin(GL_TRIANGLE_STRIP);
- if (!$alphablend) {
- glColor3f($Br, $Bg, $Bb);
- } else {
- glColor4f($Cr, $Cg, $Cb, 0);
- }
- glVertex2f($x2 - $Rx - $cx, $y2 - $Ry - $cy);
- glVertex2f($x2 + $Rx - $cx, $y2 + $Ry - $cy);
- glColor3f($Cr, $Cg, $Cb);
- glVertex2f($x2 - $tx - $Rx, $y2 - $ty - $Ry);
- glVertex2f($x2 + $tx + $Rx, $y2 + $ty + $Ry);
- glEnd();
- }
-}
-
-
-package Slic3r::GUI::Plater::2DToolpaths::Dialog;
-
-use Wx qw(:dialog :id :misc :sizer);
-use Wx::Event qw(EVT_CLOSE);
-use base 'Wx::Dialog';
-
-sub new {
- my $class = shift;
- my ($parent, $print) = @_;
- my $self = $class->SUPER::new($parent, -1, "Toolpaths", wxDefaultPosition, [500,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
-
- my $sizer = Wx::BoxSizer->new(wxVERTICAL);
- $sizer->Add(Slic3r::GUI::Plater::2DToolpaths->new($self, $print), 1, wxEXPAND, 0);
- $self->SetSizer($sizer);
- $self->SetMinSize($self->GetSize);
-
- # needed to actually free memory
- EVT_CLOSE($self, sub {
- $self->EndModal(wxID_OK);
- $self->Destroy;
- });
-
- return $self;
-}
-
-1;
diff --git a/lib/Slic3r/GUI/Plater/LambdaObjectDialog.pm b/lib/Slic3r/GUI/Plater/LambdaObjectDialog.pm
deleted file mode 100644
index 0685b4100..000000000
--- a/lib/Slic3r/GUI/Plater/LambdaObjectDialog.pm
+++ /dev/null
@@ -1,221 +0,0 @@
-# Generate an anonymous or "lambda" 3D object. This gets used with the Add Generic option in Settings.
-#
-
-package Slic3r::GUI::Plater::LambdaObjectDialog;
-use strict;
-use warnings;
-use utf8;
-
-use Wx qw(wxTheApp :dialog :id :misc :sizer wxTAB_TRAVERSAL wxCB_READONLY wxTE_PROCESS_TAB);
-use Wx::Event qw(EVT_CLOSE EVT_BUTTON EVT_COMBOBOX EVT_TEXT);
-use Scalar::Util qw(looks_like_number);
-use base 'Wx::Dialog';
-
-sub new {
- my $class = shift;
- my ($parent, %params) = @_;
- my $self = $class->SUPER::new($parent, -1, "Lambda Object", wxDefaultPosition, [500,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
- # Note whether the window was already closed, so a pending update is not executed.
- $self->{already_closed} = 0;
- $self->{object_parameters} = {
- type => "box",
- dim => [1, 1, 1],
- cyl_r => 1,
- cyl_h => 1,
- sph_rho => 1.0,
- slab_h => 1.0,
- slab_z => 0.0,
- };
-
- $self->{sizer} = Wx::BoxSizer->new(wxVERTICAL);
- my $button_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
- my $button_ok = $self->CreateStdDialogButtonSizer(wxOK);
- my $button_cancel = $self->CreateStdDialogButtonSizer(wxCANCEL);
- $button_sizer->Add($button_ok);
- $button_sizer->Add($button_cancel);
- EVT_BUTTON($self, wxID_OK, sub {
- # validate user input
- return if !$self->CanClose;
-
- $self->EndModal(wxID_OK);
- $self->Destroy;
- });
- EVT_BUTTON($self, wxID_CANCEL, sub {
- # validate user input
- return if !$self->CanClose;
-
- $self->EndModal(wxID_CANCEL);
- $self->Destroy;
- });
-
- my $optgroup_box;
- $optgroup_box = $self->{optgroup_box} = Slic3r::GUI::OptionsGroup->new(
- parent => $self,
- title => 'Add Cube...',
- on_change => sub {
- # Do validation
- my ($opt_id) = @_;
- if ($opt_id == 0 || $opt_id == 1 || $opt_id == 2) {
- if (!looks_like_number($optgroup_box->get_value($opt_id))) {
- return 0;
- }
- }
- $self->{object_parameters}->{dim}[$opt_id] = $optgroup_box->get_value($opt_id);
- },
- label_width => 100,
- );
- my @options = ("box", "slab", "cylinder", "sphere");
- $self->{type} = Wx::ComboBox->new($self, 1, "box", wxDefaultPosition, wxDefaultSize, \@options, wxCB_READONLY);
-
- $optgroup_box->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 0,
- label => 'L',
- type => 'f',
- default => '1',
- ));
- $optgroup_box->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 1,
- label => 'W',
- type => 'f',
- default => '1',
- ));
- $optgroup_box->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 2,
- label => 'H',
- type => 'f',
- default => '1',
- ));
-
- my $optgroup_cylinder;
- $optgroup_cylinder = $self->{optgroup_cylinder} = Slic3r::GUI::OptionsGroup->new(
- parent => $self,
- title => 'Add Cylinder...',
- on_change => sub {
- # Do validation
- my ($opt_id) = @_;
- if ($opt_id eq 'cyl_r' || $opt_id eq 'cyl_h') {
- if (!looks_like_number($optgroup_cylinder->get_value($opt_id))) {
- return 0;
- }
- }
- $self->{object_parameters}->{$opt_id} = $optgroup_cylinder->get_value($opt_id);
- },
- label_width => 100,
- );
-
- $optgroup_cylinder->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => "cyl_r",
- label => 'Radius',
- type => 'f',
- default => '1',
- ));
- $optgroup_cylinder->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => "cyl_h",
- label => 'Height',
- type => 'f',
- default => '1',
- ));
-
- my $optgroup_sphere;
- $optgroup_sphere = $self->{optgroup_sphere} = Slic3r::GUI::OptionsGroup->new(
- parent => $self,
- title => 'Add Sphere...',
- on_change => sub {
- # Do validation
- my ($opt_id) = @_;
- if ($opt_id eq 'sph_rho') {
- if (!looks_like_number($optgroup_sphere->get_value($opt_id))) {
- return 0;
- }
- }
- $self->{object_parameters}->{$opt_id} = $optgroup_sphere->get_value($opt_id);
- },
- label_width => 100,
- );
-
- $optgroup_sphere->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => "sph_rho",
- label => 'Rho',
- type => 'f',
- default => '1',
- ));
-
- my $optgroup_slab;
- $optgroup_slab = $self->{optgroup_slab} = Slic3r::GUI::OptionsGroup->new(
- parent => $self,
- title => 'Add Slab...',
- on_change => sub {
- # Do validation
- my ($opt_id) = @_;
- if ($opt_id eq 'slab_z' || $opt_id eq 'slab_h') {
- if (!looks_like_number($optgroup_slab->get_value($opt_id))) {
- return 0;
- }
- }
- $self->{object_parameters}->{$opt_id} = $optgroup_slab->get_value($opt_id);
- },
- label_width => 100,
- );
- $optgroup_slab->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => "slab_h",
- label => 'H',
- type => 'f',
- default => '1',
- ));
- $optgroup_slab->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => "slab_z",
- label => 'Initial Z',
- type => 'f',
- default => '0',
- ));
-
-
- EVT_COMBOBOX($self, 1, sub{
- $self->{object_parameters}->{type} = $self->{type}->GetValue();
- $self->_update_ui;
- });
-
-
- $self->{sizer}->Add($self->{type}, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
- $self->{sizer}->Add($optgroup_box->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
- $self->{sizer}->Add($optgroup_cylinder->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
- $self->{sizer}->Add($optgroup_sphere->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
- $self->{sizer}->Add($optgroup_slab->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
- $self->{sizer}->Add($button_sizer,0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
- $self->_update_ui;
-
- $self->SetSizer($self->{sizer});
- $self->{sizer}->Fit($self);
- $self->{sizer}->SetSizeHints($self);
-
-
- return $self;
-}
-sub CanClose {
- return 1;
-}
-sub ObjectParameter {
- my ($self) = @_;
- return $self->{object_parameters};
-}
-
-sub _update_ui {
- my ($self) = @_;
- $self->{sizer}->Hide($self->{optgroup_cylinder}->sizer);
- $self->{sizer}->Hide($self->{optgroup_slab}->sizer);
- $self->{sizer}->Hide($self->{optgroup_box}->sizer);
- $self->{sizer}->Hide($self->{optgroup_sphere}->sizer);
- if ($self->{type}->GetValue eq "box") {
- $self->{sizer}->Show($self->{optgroup_box}->sizer);
- } elsif ($self->{type}->GetValue eq "cylinder") {
- $self->{sizer}->Show($self->{optgroup_cylinder}->sizer);
- } elsif ($self->{type}->GetValue eq "slab") {
- $self->{sizer}->Show($self->{optgroup_slab}->sizer);
- } elsif ($self->{type}->GetValue eq "sphere") {
- $self->{sizer}->Show($self->{optgroup_sphere}->sizer);
- }
- $self->{sizer}->Fit($self);
- $self->{sizer}->SetSizeHints($self);
-
-}
-1;
diff --git a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm
deleted file mode 100644
index 26a6fdec3..000000000
--- a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm
+++ /dev/null
@@ -1,284 +0,0 @@
-# Cut an object at a Z position, keep either the top or the bottom of the object.
-# This dialog gets opened with the "Cut..." button above the platter.
-
-package Slic3r::GUI::Plater::ObjectCutDialog;
-use strict;
-use warnings;
-use utf8;
-
-use Slic3r::Geometry qw(PI X);
-use Wx qw(wxTheApp :dialog :id :misc :sizer wxTAB_TRAVERSAL);
-use Wx::Event qw(EVT_CLOSE EVT_BUTTON);
-use List::Util qw(max);
-use base 'Wx::Dialog';
-
-sub new {
- my ($class, $parent, %params) = @_;
- my $self = $class->SUPER::new($parent, -1, $params{object}->name, wxDefaultPosition, [500,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
- $self->{model_object} = $params{model_object};
- $self->{new_model_objects} = [];
- # Mark whether the mesh cut is valid.
- # If not, it needs to be recalculated by _update() on wxTheApp->CallAfter() or on exit of the dialog.
- $self->{mesh_cut_valid} = 0;
- # Note whether the window was already closed, so a pending update is not executed.
- $self->{already_closed} = 0;
-
- # cut options
- $self->{cut_options} = {
- z => 0,
- keep_upper => 1,
- keep_lower => 1,
- rotate_lower => 1,
-# preview => 1,
-# Disabled live preview by default as it is not stable and/or the calculation takes too long for interactive usage.
- preview => 0,
- };
-
- my $optgroup;
- $optgroup = $self->{optgroup} = Slic3r::GUI::OptionsGroup->new(
- parent => $self,
- title => 'Cut',
- on_change => sub {
- my ($opt_id) = @_;
- # There seems to be an issue with wxWidgets 3.0.2/3.0.3, where the slider
- # genates tens of events for a single value change.
- # Only trigger the recalculation if the value changes
- # or a live preview was activated and the mesh cut is not valid yet.
- if ($self->{cut_options}{$opt_id} != $optgroup->get_value($opt_id) ||
- ! $self->{mesh_cut_valid} && $self->_life_preview_active()) {
- $self->{cut_options}{$opt_id} = $optgroup->get_value($opt_id);
- $self->{mesh_cut_valid} = 0;
- wxTheApp->CallAfter(sub {
- $self->_update;
- });
- }
- },
- label_width => 120,
- );
- $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 'z',
- type => 'slider',
- label => 'Z',
- default => $self->{cut_options}{z},
- min => 0,
- max => $self->{model_object}->bounding_box->size->z,
- full_width => 1,
- ));
- {
- my $line = Slic3r::GUI::OptionsGroup::Line->new(
- label => 'Keep',
- );
- $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 'keep_upper',
- type => 'bool',
- label => 'Upper part',
- default => $self->{cut_options}{keep_upper},
- ));
- $line->append_option(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 'keep_lower',
- type => 'bool',
- label => 'Lower part',
- default => $self->{cut_options}{keep_lower},
- ));
- $optgroup->append_line($line);
- }
- $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 'rotate_lower',
- label => 'Rotate lower part upwards',
- type => 'bool',
- tooltip => 'If enabled, the lower part will be rotated by 180° so that the flat cut surface lies on the print bed.',
- default => $self->{cut_options}{rotate_lower},
- ));
- $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 'preview',
- label => 'Show preview',
- type => 'bool',
- tooltip => 'If enabled, object will be cut in real time.',
- default => $self->{cut_options}{preview},
- ));
- {
- my $cut_button_sizer = Wx::BoxSizer->new(wxVERTICAL);
- $self->{btn_cut} = Wx::Button->new($self, -1, "Perform cut", wxDefaultPosition, wxDefaultSize);
- $cut_button_sizer->Add($self->{btn_cut}, 0, wxALIGN_RIGHT | wxALL, 10);
- $optgroup->append_line(Slic3r::GUI::OptionsGroup::Line->new(
- sizer => $cut_button_sizer,
- ));
- }
-
- # left pane with tree
- my $left_sizer = Wx::BoxSizer->new(wxVERTICAL);
- $left_sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
-
- # right pane with preview canvas
- my $canvas;
- if ($Slic3r::GUI::have_OpenGL) {
- $canvas = $self->{canvas} = Slic3r::GUI::3DScene->new($self);
- Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $self->{model_object}, 0, [0]);
- Slic3r::GUI::_3DScene::set_auto_bed_shape($canvas);
- Slic3r::GUI::_3DScene::set_axes_length($canvas, 2.0 * max(@{ Slic3r::GUI::_3DScene::get_volumes_bounding_box($canvas)->size }));
- $canvas->SetSize([500,500]);
- $canvas->SetMinSize($canvas->GetSize);
- Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->{config});
- Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($canvas, 1);
- }
-
- $self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
- $self->{sizer}->Add($left_sizer, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
- $self->{sizer}->Add($canvas, 1, wxEXPAND | wxALL, 0) if $canvas;
-
- $self->SetSizer($self->{sizer});
- $self->SetMinSize($self->GetSize);
- $self->{sizer}->SetSizeHints($self);
-
- EVT_BUTTON($self, $self->{btn_cut}, sub {
- # Recalculate the cut if the preview was not active.
- $self->_perform_cut() unless $self->{mesh_cut_valid};
-
- # Adjust position / orientation of the split object halves.
- if ($self->{new_model_objects}{lower}) {
- if ($self->{cut_options}{rotate_lower}) {
- $self->{new_model_objects}{lower}->rotate(PI, Slic3r::Pointf3->new(1,0,0));
- $self->{new_model_objects}{lower}->center_around_origin; # align to Z = 0
- }
- }
- if ($self->{new_model_objects}{upper}) {
- $self->{new_model_objects}{upper}->center_around_origin; # align to Z = 0
- }
-
- # Note that the window was already closed, so a pending update will not be executed.
- $self->{already_closed} = 1;
- $self->EndModal(wxID_OK);
- $self->{canvas}->Destroy;
- $self->Destroy();
- });
-
- EVT_CLOSE($self, sub {
- # Note that the window was already closed, so a pending update will not be executed.
- $self->{already_closed} = 1;
- $self->EndModal(wxID_CANCEL);
- $self->{canvas}->Destroy;
- $self->Destroy();
- });
-
- $self->_update;
-
- return $self;
-}
-
-# scale Z down to original size since we're using the transformed mesh for 3D preview
-# and cut dialog but ModelObject::cut() needs Z without any instance transformation
-sub _mesh_slice_z_pos
-{
- my ($self) = @_;
- return $self->{cut_options}{z} / $self->{model_object}->instances->[0]->scaling_factor;
-}
-
-# Only perform live preview if just a single part of the object shall survive.
-sub _life_preview_active
-{
- my ($self) = @_;
- return $self->{cut_options}{preview} && ($self->{cut_options}{keep_upper} != $self->{cut_options}{keep_lower});
-}
-
-# Slice the mesh, keep the top / bottom part.
-sub _perform_cut
-{
- my ($self) = @_;
-
- # Early exit. If the cut is valid, don't recalculate it.
- return if $self->{mesh_cut_valid};
-
- my $z = $self->_mesh_slice_z_pos();
-
- my ($new_model) = $self->{model_object}->cut($z);
- my ($upper_object, $lower_object) = @{$new_model->objects};
- $self->{new_model} = $new_model;
- $self->{new_model_objects} = {};
- if ($self->{cut_options}{keep_upper} && $upper_object->volumes_count > 0) {
- $self->{new_model_objects}{upper} = $upper_object;
- }
- if ($self->{cut_options}{keep_lower} && $lower_object->volumes_count > 0) {
- $self->{new_model_objects}{lower} = $lower_object;
- }
-
- $self->{mesh_cut_valid} = 1;
-}
-
-sub _update {
- my ($self) = @_;
-
- # Don't update if the window was already closed.
- # We are not sure whether the action planned by wxTheApp->CallAfter() may be triggered after the window is closed.
- # Probably not, but better be safe than sorry, which is espetially true on multiple platforms.
- return if $self->{already_closed};
-
- # Only recalculate the cut, if the live cut preview is active.
- my $life_preview_active = $self->_life_preview_active();
- $self->_perform_cut() if $life_preview_active;
-
- {
- # scale Z down to original size since we're using the transformed mesh for 3D preview
- # and cut dialog but ModelObject::cut() needs Z without any instance transformation
- my $z = $self->_mesh_slice_z_pos();
-
-
- # update canvas
- if ($self->{canvas}) {
- # get volumes to render
- my @objects = ();
- if ($life_preview_active) {
- push @objects, values %{$self->{new_model_objects}};
- } else {
- push @objects, $self->{model_object};
- }
-
- my $z_cut = $z + $self->{model_object}->bounding_box->z_min;
-
- # get section contour
- my @expolygons = ();
- foreach my $volume (@{$self->{model_object}->volumes}) {
- next if !$volume->mesh;
- next if $volume->modifier;
- my $expp = $volume->mesh->slice([ $z_cut ])->[0];
- push @expolygons, @$expp;
- }
- foreach my $expolygon (@expolygons) {
- $self->{model_object}->instances->[0]->transform_polygon($_)
- for @$expolygon;
- $expolygon->translate(map Slic3r::Geometry::scale($_), @{ $self->{model_object}->instances->[0]->offset });
- }
-
- Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
- Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $_, 0, [0]) for @objects;
- Slic3r::GUI::_3DScene::set_cutting_plane($self->{canvas}, $self->{cut_options}{z}, [@expolygons]);
- Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
- Slic3r::GUI::_3DScene::render($self->{canvas});
- }
- }
-
- # update controls
- {
- my $z = $self->{cut_options}{z};
- my $optgroup = $self->{optgroup};
- $optgroup->get_field('keep_upper')->toggle(my $have_upper = abs($z - $optgroup->get_option('z')->max) > 0.1);
- $optgroup->get_field('keep_lower')->toggle(my $have_lower = $z > 0.1);
- $optgroup->get_field('rotate_lower')->toggle($z > 0 && $self->{cut_options}{keep_lower});
-# Disabled live preview by default as it is not stable and/or the calculation takes too long for interactive usage.
-# $optgroup->get_field('preview')->toggle($self->{cut_options}{keep_upper} != $self->{cut_options}{keep_lower});
-
- # update cut button
- if (($self->{cut_options}{keep_upper} && $have_upper)
- || ($self->{cut_options}{keep_lower} && $have_lower)) {
- $self->{btn_cut}->Enable;
- } else {
- $self->{btn_cut}->Disable;
- }
- }
-}
-
-sub NewModelObjects {
- my ($self) = @_;
- return values %{ $self->{new_model_objects} };
-}
-
-1;
diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm
deleted file mode 100644
index 783c1a9f5..000000000
--- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm
+++ /dev/null
@@ -1,588 +0,0 @@
-# Configuration of mesh modifiers and their parameters.
-# This panel is inserted into ObjectSettingsDialog.
-
-package Slic3r::GUI::Plater::ObjectPartsPanel;
-use strict;
-use warnings;
-use utf8;
-
-use File::Basename qw(basename);
-use Wx qw(:misc :sizer :treectrl :button :keycode wxTAB_TRAVERSAL wxSUNKEN_BORDER wxBITMAP_TYPE_PNG wxID_CANCEL wxMOD_CONTROL
- wxTheApp);
-use Wx::Event qw(EVT_BUTTON EVT_TREE_ITEM_COLLAPSING EVT_TREE_SEL_CHANGED EVT_TREE_KEY_DOWN EVT_KEY_DOWN);
-use List::Util qw(max);
-use base 'Wx::Panel';
-
-use constant ICON_OBJECT => 0;
-use constant ICON_SOLIDMESH => 1;
-use constant ICON_MODIFIERMESH => 2;
-
-sub new {
- my ($class, $parent, %params) = @_;
- my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
-
- # C++ type Slic3r::ModelObject
- my $object = $self->{model_object} = $params{model_object};
-
- # Save state for sliders.
- $self->{move_options} = {
- x => 0,
- y => 0,
- z => 0,
- };
- $self->{last_coords} = {
- x => 0,
- y => 0,
- z => 0,
- };
-
- # create TreeCtrl
- my $tree = $self->{tree} = Wx::TreeCtrl->new($self, -1, wxDefaultPosition, [300, 100],
- wxTR_NO_BUTTONS | wxSUNKEN_BORDER | wxTR_HAS_VARIABLE_ROW_HEIGHT
- | wxTR_SINGLE);
- {
- $self->{tree_icons} = Wx::ImageList->new(16, 16, 1);
- $tree->AssignImageList($self->{tree_icons});
- $self->{tree_icons}->Add(Wx::Bitmap->new(Slic3r::var("brick.png"), wxBITMAP_TYPE_PNG)); # ICON_OBJECT
- $self->{tree_icons}->Add(Wx::Bitmap->new(Slic3r::var("package.png"), wxBITMAP_TYPE_PNG)); # ICON_SOLIDMESH
- $self->{tree_icons}->Add(Wx::Bitmap->new(Slic3r::var("plugin.png"), wxBITMAP_TYPE_PNG)); # ICON_MODIFIERMESH
-
- my $rootId = $tree->AddRoot("Object", ICON_OBJECT);
- $tree->SetPlData($rootId, { type => 'object' });
- }
-
- # buttons
- $self->{btn_load_part} = Wx::Button->new($self, -1, "Load part…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
- $self->{btn_load_modifier} = Wx::Button->new($self, -1, "Load modifier…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
- $self->{btn_load_lambda_modifier} = Wx::Button->new($self, -1, "Load generic…", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
- $self->{btn_delete} = Wx::Button->new($self, -1, "Delete part", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
- $self->{btn_split} = Wx::Button->new($self, -1, "Split part", wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
- $self->{btn_move_up} = Wx::Button->new($self, -1, "", wxDefaultPosition, [40, -1], wxBU_LEFT);
- $self->{btn_move_down} = Wx::Button->new($self, -1, "", wxDefaultPosition, [40, -1], wxBU_LEFT);
- $self->{btn_load_part}->SetBitmap(Wx::Bitmap->new(Slic3r::var("brick_add.png"), wxBITMAP_TYPE_PNG));
- $self->{btn_load_modifier}->SetBitmap(Wx::Bitmap->new(Slic3r::var("brick_add.png"), wxBITMAP_TYPE_PNG));
- $self->{btn_load_lambda_modifier}->SetBitmap(Wx::Bitmap->new(Slic3r::var("brick_add.png"), wxBITMAP_TYPE_PNG));
- $self->{btn_delete}->SetBitmap(Wx::Bitmap->new(Slic3r::var("brick_delete.png"), wxBITMAP_TYPE_PNG));
- $self->{btn_split}->SetBitmap(Wx::Bitmap->new(Slic3r::var("shape_ungroup.png"), wxBITMAP_TYPE_PNG));
- $self->{btn_move_up}->SetBitmap(Wx::Bitmap->new(Slic3r::var("bullet_arrow_up.png"), wxBITMAP_TYPE_PNG));
- $self->{btn_move_down}->SetBitmap(Wx::Bitmap->new(Slic3r::var("bullet_arrow_down.png"), wxBITMAP_TYPE_PNG));
-
- # buttons sizer
- my $buttons_sizer = Wx::GridSizer->new(2, 3);
- $buttons_sizer->Add($self->{btn_load_part}, 0, wxEXPAND | wxBOTTOM | wxRIGHT, 5);
- $buttons_sizer->Add($self->{btn_load_modifier}, 0, wxEXPAND | wxBOTTOM | wxRIGHT, 5);
- $buttons_sizer->Add($self->{btn_load_lambda_modifier}, 0, wxEXPAND | wxBOTTOM, 5);
- $buttons_sizer->Add($self->{btn_delete}, 0, wxEXPAND | wxRIGHT, 5);
- $buttons_sizer->Add($self->{btn_split}, 0, wxEXPAND | wxRIGHT, 5);
- {
- my $up_down_sizer = Wx::GridSizer->new(1, 2);
- $up_down_sizer->Add($self->{btn_move_up}, 0, wxEXPAND | wxRIGHT, 5);
- $up_down_sizer->Add($self->{btn_move_down}, 0, wxEXPAND, 5);
- $buttons_sizer->Add($up_down_sizer, 0, wxEXPAND, 5);
- }
- $self->{btn_load_part}->SetFont($Slic3r::GUI::small_font);
- $self->{btn_load_modifier}->SetFont($Slic3r::GUI::small_font);
- $self->{btn_load_lambda_modifier}->SetFont($Slic3r::GUI::small_font);
- $self->{btn_delete}->SetFont($Slic3r::GUI::small_font);
- $self->{btn_split}->SetFont($Slic3r::GUI::small_font);
- $self->{btn_move_up}->SetFont($Slic3r::GUI::small_font);
- $self->{btn_move_down}->SetFont($Slic3r::GUI::small_font);
-
- # part settings panel
- $self->{settings_panel} = Slic3r::GUI::Plater::OverrideSettingsPanel->new($self, on_change => sub { $self->{part_settings_changed} = 1; $self->_update_canvas; });
- my $settings_sizer = Wx::StaticBoxSizer->new($self->{staticbox} = Wx::StaticBox->new($self, -1, "Part Settings"), wxVERTICAL);
- $settings_sizer->Add($self->{settings_panel}, 1, wxEXPAND | wxALL, 0);
-
- my $optgroup_movers;
- $optgroup_movers = $self->{optgroup_movers} = Slic3r::GUI::OptionsGroup->new(
- parent => $self,
- title => 'Move',
- on_change => sub {
- my ($opt_id) = @_;
- # There seems to be an issue with wxWidgets 3.0.2/3.0.3, where the slider
- # genates tens of events for a single value change.
- # Only trigger the recalculation if the value changes
- # or a live preview was activated and the mesh cut is not valid yet.
- if ($self->{move_options}{$opt_id} != $optgroup_movers->get_value($opt_id)) {
- $self->{move_options}{$opt_id} = $optgroup_movers->get_value($opt_id);
- wxTheApp->CallAfter(sub {
- $self->_update;
- });
- }
- },
- label_width => 20,
- );
- $optgroup_movers->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 'x',
- type => 'slider',
- label => 'X',
- default => 0,
- min => -($self->{model_object}->bounding_box->size->x)*4,
- max => $self->{model_object}->bounding_box->size->x*4,
- full_width => 1,
- ));
- $optgroup_movers->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 'y',
- type => 'slider',
- label => 'Y',
- default => 0,
- min => -($self->{model_object}->bounding_box->size->y)*4,
- max => $self->{model_object}->bounding_box->size->y*4,
- full_width => 1,
- ));
- $optgroup_movers->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
- opt_id => 'z',
- type => 'slider',
- label => 'Z',
- default => 0,
- min => -($self->{model_object}->bounding_box->size->z)*4,
- max => $self->{model_object}->bounding_box->size->z*4,
- full_width => 1,
- ));
-
- # left pane with tree
- my $left_sizer = Wx::BoxSizer->new(wxVERTICAL);
- $left_sizer->Add($tree, 3, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 10);
- $left_sizer->Add($buttons_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 10);
- $left_sizer->Add($settings_sizer, 5, wxEXPAND | wxALL, 0);
- $left_sizer->Add($optgroup_movers->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
-
- # right pane with preview canvas
- my $canvas;
- if ($Slic3r::GUI::have_OpenGL) {
- $canvas = $self->{canvas} = Slic3r::GUI::3DScene->new($self);
- Slic3r::GUI::_3DScene::enable_picking($canvas, 1);
- Slic3r::GUI::_3DScene::set_select_by($canvas, 'volume');
- Slic3r::GUI::_3DScene::register_on_select_object_callback($canvas, sub {
- my ($volume_idx) = @_;
- $self->reload_tree($volume_idx);
- });
- Slic3r::GUI::_3DScene::load_model_object($canvas, $self->{model_object}, 0, [0]);
- Slic3r::GUI::_3DScene::set_auto_bed_shape($canvas);
- Slic3r::GUI::_3DScene::set_axes_length($canvas, 2.0 * max(@{ Slic3r::GUI::_3DScene::get_volumes_bounding_box($canvas)->size }));
- $canvas->SetSize([500,700]);
- Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->GetParent->GetParent->{config});
- Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($canvas);
- Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($canvas, 1);
- }
-
- $self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL);
- $self->{sizer}->Add($left_sizer, 0, wxEXPAND | wxALL, 0);
- $self->{sizer}->Add($canvas, 1, wxEXPAND | wxALL, 0) if $canvas;
-
- $self->SetSizer($self->{sizer});
- $self->{sizer}->SetSizeHints($self);
-
- # attach events
- EVT_TREE_ITEM_COLLAPSING($self, $tree, sub {
- my ($self, $event) = @_;
- $event->Veto;
- });
- EVT_TREE_SEL_CHANGED($self, $tree, sub {
- my ($self, $event) = @_;
- return if $self->{disable_tree_sel_changed_event};
- $self->selection_changed;
- });
- EVT_TREE_KEY_DOWN($self, $tree, \&on_tree_key_down);
- EVT_BUTTON($self, $self->{btn_load_part}, sub { $self->on_btn_load(0) });
- EVT_BUTTON($self, $self->{btn_load_modifier}, sub { $self->on_btn_load(1) });
- EVT_BUTTON($self, $self->{btn_load_lambda_modifier}, sub { $self->on_btn_lambda(1) });
- EVT_BUTTON($self, $self->{btn_delete}, \&on_btn_delete);
- EVT_BUTTON($self, $self->{btn_split}, \&on_btn_split);
- EVT_BUTTON($self, $self->{btn_move_up}, \&on_btn_move_up);
- EVT_BUTTON($self, $self->{btn_move_down}, \&on_btn_move_down);
- EVT_KEY_DOWN($canvas, sub {
- my ($canvas, $event) = @_;
- if ($event->GetKeyCode == WXK_DELETE) {
- $canvas->GetParent->on_btn_delete;
- } else {
- $event->Skip;
- }
- });
-
- $self->reload_tree;
-
- return $self;
-}
-
-sub reload_tree {
- my ($self, $selected_volume_idx) = @_;
-
- $selected_volume_idx //= -1;
- my $object = $self->{model_object};
- my $tree = $self->{tree};
- my $rootId = $tree->GetRootItem;
-
- # despite wxWidgets states that DeleteChildren "will not generate any events unlike Delete() method",
- # the MSW implementation of DeleteChildren actually calls Delete() for each item, so
- # EVT_TREE_SEL_CHANGED is being called, with bad effects (the event handler is called; this
- # subroutine is never continued; an invisible EndModal is called on the dialog causing Plater
- # to continue its logic and rescheduling the background process etc. GH #2774)
- $self->{disable_tree_sel_changed_event} = 1;
- $tree->DeleteChildren($rootId);
- $self->{disable_tree_sel_changed_event} = 0;
-
- my $selectedId = $rootId;
- foreach my $volume_id (0..$#{$object->volumes}) {
- my $volume = $object->volumes->[$volume_id];
-
- my $icon = $volume->modifier ? ICON_MODIFIERMESH : ICON_SOLIDMESH;
- my $itemId = $tree->AppendItem($rootId, $volume->name || $volume_id, $icon);
- if ($volume_id == $selected_volume_idx) {
- $selectedId = $itemId;
- }
- $tree->SetPlData($itemId, {
- type => 'volume',
- volume_id => $volume_id,
- });
- }
- $tree->ExpandAll;
-
- Slic3r::GUI->CallAfter(sub {
- $self->{tree}->SelectItem($selectedId);
-
- # SelectItem() should trigger EVT_TREE_SEL_CHANGED as per wxWidgets docs,
- # but in fact it doesn't if the given item is already selected (this happens
- # on first load)
- $self->selection_changed;
- });
-}
-
-sub get_selection {
- my ($self) = @_;
-
- my $nodeId = $self->{tree}->GetSelection;
- if ($nodeId->IsOk) {
- return $self->{tree}->GetPlData($nodeId);
- }
- return undef;
-}
-
-sub selection_changed {
- my ($self) = @_;
-
- # deselect all meshes
- if ($self->{canvas}) {
- Slic3r::GUI::_3DScene::deselect_volumes($self->{canvas});
- }
-
- # disable things as if nothing is selected
- $self->{'btn_' . $_}->Disable for (qw(delete move_up move_down split));
- $self->{settings_panel}->disable;
- $self->{settings_panel}->set_config(undef);
-
- # reset move sliders
- $self->{optgroup_movers}->set_value("x", 0);
- $self->{optgroup_movers}->set_value("y", 0);
- $self->{optgroup_movers}->set_value("z", 0);
- $self->{move_options} = {
- x => 0,
- y => 0,
- z => 0,
- };
- $self->{last_coords} = {
- x => 0,
- y => 0,
- z => 0,
- };
-
- if (my $itemData = $self->get_selection) {
- my ($config, @opt_keys);
- if ($itemData->{type} eq 'volume') {
- # select volume in 3D preview
- if ($self->{canvas}) {
- Slic3r::GUI::_3DScene::select_volume($self->{canvas}, $itemData->{volume_id});
- }
- $self->{btn_delete}->Enable;
- $self->{btn_split}->Enable;
- $self->{btn_move_up}->Enable if $itemData->{volume_id} > 0;
- $self->{btn_move_down}->Enable if $itemData->{volume_id} + 1 < $self->{model_object}->volumes_count;
-
- # attach volume config to settings panel
- my $volume = $self->{model_object}->volumes->[ $itemData->{volume_id} ];
-
- if ($volume->modifier) {
- $self->{optgroup_movers}->enable;
- } else {
- $self->{optgroup_movers}->disable;
- }
- $config = $volume->config;
- $self->{staticbox}->SetLabel('Part Settings');
-
- # get default values
- @opt_keys = @{Slic3r::Config::PrintRegion->new->get_keys};
- } elsif ($itemData->{type} eq 'object') {
- # select nothing in 3D preview
-
- # attach object config to settings panel
- $self->{optgroup_movers}->disable;
- $self->{staticbox}->SetLabel('Object Settings');
- @opt_keys = (map @{$_->get_keys}, Slic3r::Config::PrintObject->new, Slic3r::Config::PrintRegion->new);
- $config = $self->{model_object}->config;
- }
- # get default values
- my $default_config = Slic3r::Config::new_from_defaults_keys(\@opt_keys);
-
- # decide which settings will be shown by default
- if ($itemData->{type} eq 'object') {
- $config->set_ifndef('wipe_into_objects', 0);
- $config->set_ifndef('wipe_into_infill', 0);
- }
-
- # append default extruder
- push @opt_keys, 'extruder';
- $default_config->set('extruder', 0);
- $config->set_ifndef('extruder', 0);
- $self->{settings_panel}->set_default_config($default_config);
- $self->{settings_panel}->set_config($config);
- $self->{settings_panel}->set_opt_keys(\@opt_keys);
-
- # disable minus icon to remove the settings
- if ($itemData->{type} eq 'object') {
- $self->{settings_panel}->set_fixed_options([qw(extruder), qw(wipe_into_infill), qw(wipe_into_objects)]);
- } else {
- $self->{settings_panel}->set_fixed_options([qw(extruder)]);
- }
-
- $self->{settings_panel}->enable;
- }
-
- Slic3r::GUI::_3DScene::render($self->{canvas}) if $self->{canvas};
-}
-
-sub on_btn_load {
- my ($self, $is_modifier) = @_;
-
- my @input_files = wxTheApp->open_model($self);
- foreach my $input_file (@input_files) {
- my $model = eval { Slic3r::Model->read_from_file($input_file) };
- if ($@) {
- Slic3r::GUI::show_error($self, $@);
- next;
- }
-
- foreach my $object (@{$model->objects}) {
- foreach my $volume (@{$object->volumes}) {
- my $new_volume = $self->{model_object}->add_volume($volume);
- $new_volume->set_modifier($is_modifier);
- $new_volume->set_name(basename($input_file));
-
- # apply the same translation we applied to the object
- $new_volume->mesh->translate(@{$self->{model_object}->origin_translation});
-
- # set a default extruder value, since user can't add it manually
- $new_volume->config->set_ifndef('extruder', 0);
-
- $self->{parts_changed} = 1;
- }
- }
- }
-
- $self->{model_object}->center_around_origin if $self->{parts_changed};
- $self->_parts_changed;
-}
-
-sub on_btn_lambda {
- my ($self, $is_modifier) = @_;
-
- my $dlg = Slic3r::GUI::Plater::LambdaObjectDialog->new($self);
- if ($dlg->ShowModal() == wxID_CANCEL) {
- return;
- }
- my $params = $dlg->ObjectParameter;
- my $type = "".$params->{"type"};
- my $name = "lambda-".$params->{"type"};
- my $mesh;
-
- if ($type eq "box") {
- $mesh = Slic3r::TriangleMesh::cube($params->{"dim"}[0], $params->{"dim"}[1], $params->{"dim"}[2]);
- } elsif ($type eq "cylinder") {
- $mesh = Slic3r::TriangleMesh::cylinder($params->{"cyl_r"}, $params->{"cyl_h"});
- } elsif ($type eq "sphere") {
- $mesh = Slic3r::TriangleMesh::sphere($params->{"sph_rho"});
- } elsif ($type eq "slab") {
- $mesh = Slic3r::TriangleMesh::cube($self->{model_object}->bounding_box->size->x*1.5, $self->{model_object}->bounding_box->size->y*1.5, $params->{"slab_h"});
- # box sets the base coordinate at 0,0, move to center of plate and move it up to initial_z
- $mesh->translate(-$self->{model_object}->bounding_box->size->x*1.5/2.0, -$self->{model_object}->bounding_box->size->y*1.5/2.0, $params->{"slab_z"});
- } else {
- return;
- }
- $mesh->repair;
- my $new_volume = $self->{model_object}->add_volume(mesh => $mesh);
- $new_volume->set_modifier($is_modifier);
- $new_volume->set_name($name);
-
- # set a default extruder value, since user can't add it manually
- $new_volume->config->set_ifndef('extruder', 0);
-
- $self->{parts_changed} = 1;
- $self->_parts_changed;
-}
-
-sub on_tree_key_down {
- my ($self, $event) = @_;
- my $keycode = $event->GetKeyCode;
- # Wx >= 0.9911
- if (defined(&Wx::TreeEvent::GetKeyEvent)) {
- if ($event->GetKeyEvent->GetModifiers & wxMOD_CONTROL) {
- if ($keycode == WXK_UP) {
- $event->Skip;
- $self->on_btn_move_up;
- } elsif ($keycode == WXK_DOWN) {
- $event->Skip;
- $self->on_btn_move_down;
- }
- } elsif ($keycode == WXK_DELETE) {
- $self->on_btn_delete;
- }
- }
-}
-
-sub on_btn_move_up {
- my ($self) = @_;
- my $itemData = $self->get_selection;
- if ($itemData && $itemData->{type} eq 'volume') {
- my $volume_id = $itemData->{volume_id};
- if ($self->{model_object}->move_volume_up($volume_id)) {
- Slic3r::GUI::_3DScene::move_volume_up($self->{canvas}, $volume_id);
- $self->{parts_changed} = 1;
- $self->reload_tree($volume_id - 1);
- }
- }
-}
-
-sub on_btn_move_down {
- my ($self) = @_;
- my $itemData = $self->get_selection;
- if ($itemData && $itemData->{type} eq 'volume') {
- my $volume_id = $itemData->{volume_id};
- if ($self->{model_object}->move_volume_down($volume_id)) {
- Slic3r::GUI::_3DScene::move_volume_down($self->{canvas}, $volume_id);
- $self->{parts_changed} = 1;
- $self->reload_tree($volume_id + 1);
- }
- }
-}
-
-sub on_btn_delete {
- my ($self) = @_;
-
- my $itemData = $self->get_selection;
- if ($itemData && $itemData->{type} eq 'volume') {
- my $volume = $self->{model_object}->volumes->[$itemData->{volume_id}];
-
- # if user is deleting the last solid part, throw error
- if (!$volume->modifier && scalar(grep !$_->modifier, @{$self->{model_object}->volumes}) == 1) {
- Slic3r::GUI::show_error($self, "You can't delete the last solid part from this object.");
- return;
- }
-
- $self->{model_object}->delete_volume($itemData->{volume_id});
- $self->{parts_changed} = 1;
- }
-
- $self->{model_object}->center_around_origin if $self->{parts_changed};
- $self->_parts_changed;
-}
-
-sub on_btn_split {
- my ($self) = @_;
-
- my $itemData = $self->get_selection;
- if ($itemData && $itemData->{type} eq 'volume') {
- my $volume = $self->{model_object}->volumes->[$itemData->{volume_id}];
- my $nozzle_dmrs = $self->GetParent->GetParent->GetParent->{config}->get('nozzle_diameter');
- $self->{parts_changed} = 1 if $volume->split(scalar(@$nozzle_dmrs)) > 1;
- }
-
- $self->_parts_changed;
-}
-
-sub _parts_changed {
- my ($self) = @_;
-
- $self->reload_tree;
- if ($self->{canvas}) {
- Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
- Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $self->{model_object}, 0, [0]);
- Slic3r::GUI::_3DScene::zoom_to_volumes($self->{canvas});
- Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
- Slic3r::GUI::_3DScene::render($self->{canvas});
- }
-}
-
-sub CanClose {
- my $self = shift;
-
- return 1; # skip validation for now
-
- # validate options before allowing user to dismiss the dialog
- # the validate method only works on full configs so we have
- # to merge our settings with the default ones
- my $config = $self->GetParent->GetParent->GetParent->GetParent->GetParent->config->clone;
- eval {
- $config->apply($self->model_object->config);
- $config->validate;
- };
- return ! Slic3r::GUI::catch_error($self);
-}
-
-sub Destroy {
- my ($self) = @_;
- $self->{canvas}->Destroy if ($self->{canvas});
-}
-
-sub PartsChanged {
- my ($self) = @_;
- return $self->{parts_changed};
-}
-
-sub PartSettingsChanged {
- my ($self) = @_;
- return $self->{part_settings_changed};
-}
-
-sub _update_canvas {
- my ($self) = @_;
-
- if ($self->{canvas}) {
- Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
- Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $self->{model_object}, 0, [0]);
-
- # restore selection, if any
- if (my $itemData = $self->get_selection) {
- if ($itemData->{type} eq 'volume') {
- Slic3r::GUI::_3DScene::select_volume($self->{canvas}, $itemData->{volume_id});
- }
- }
-
- Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
- Slic3r::GUI::_3DScene::render($self->{canvas});
- }
-}
-
-sub _update {
- my ($self) = @_;
- my ($m_x, $m_y, $m_z) = ($self->{move_options}{x}, $self->{move_options}{y}, $self->{move_options}{z});
- my ($l_x, $l_y, $l_z) = ($self->{last_coords}{x}, $self->{last_coords}{y}, $self->{last_coords}{z});
-
- my $itemData = $self->get_selection;
- if ($itemData && $itemData->{type} eq 'volume') {
- my $d = Slic3r::Pointf3->new($m_x - $l_x, $m_y - $l_y, $m_z - $l_z);
- my $volume = $self->{model_object}->volumes->[$itemData->{volume_id}];
- $volume->mesh->translate(@{$d});
- $self->{last_coords}{x} = $m_x;
- $self->{last_coords}{y} = $m_y;
- $self->{last_coords}{z} = $m_z;
- }
-
- $self->{parts_changed} = 1;
- my @objects = ();
- push @objects, $self->{model_object};
- Slic3r::GUI::_3DScene::reset_volumes($self->{canvas});
- Slic3r::GUI::_3DScene::load_model_object($self->{canvas}, $_, 0, [0]) for @objects;
- Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($self->{canvas});
- Slic3r::GUI::_3DScene::render($self->{canvas});
-}
-
-1;
diff --git a/lib/Slic3r/GUI/Plater/ObjectSettingsDialog.pm b/lib/Slic3r/GUI/Plater/ObjectSettingsDialog.pm
deleted file mode 100644
index 3befba708..000000000
--- a/lib/Slic3r/GUI/Plater/ObjectSettingsDialog.pm
+++ /dev/null
@@ -1,224 +0,0 @@
-# This dialog opens up when double clicked on an object line in the list at the right side of the platter.
-# One may load additional STLs and additional modifier STLs,
-# one may change the properties of the print per each modifier mesh or a Z-span.
-
-package Slic3r::GUI::Plater::ObjectSettingsDialog;
-use strict;
-use warnings;
-use utf8;
-
-use Wx qw(:dialog :id :misc :sizer :systemsettings :notebook wxTAB_TRAVERSAL wxTheApp);
-use Wx::Event qw(EVT_BUTTON);
-use base 'Wx::Dialog';
-
-# Called with
-# %params{object} of a Perl type Slic3r::GUI::Plater::Object
-# %params{model_object} of a C++ type Slic3r::ModelObject
-sub new {
- my ($class, $parent, %params) = @_;
- my $self = $class->SUPER::new($parent, -1, "Settings for " . $params{object}->name, wxDefaultPosition, [700,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
- $self->{$_} = $params{$_} for keys %params;
-
- $self->{tabpanel} = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL);
- $self->{tabpanel}->AddPage($self->{parts} = Slic3r::GUI::Plater::ObjectPartsPanel->new($self->{tabpanel}, model_object => $params{model_object}), "Parts");
- $self->{tabpanel}->AddPage($self->{layers} = Slic3r::GUI::Plater::ObjectDialog::LayersTab->new($self->{tabpanel}), "Layers");
-
- my $buttons = $self->CreateStdDialogButtonSizer(wxOK);
- EVT_BUTTON($self, wxID_OK, sub {
- # validate user input
- return if !$self->{parts}->CanClose;
- return if !$self->{layers}->CanClose;
-
- # notify tabs
- $self->{layers}->Closing;
-
- # save window size
- wxTheApp->save_window_pos($self, "object_settings");
-
- $self->EndModal(wxID_OK);
- $self->{parts}->Destroy;
- $self->Destroy;
- });
-
- my $sizer = Wx::BoxSizer->new(wxVERTICAL);
- $sizer->Add($self->{tabpanel}, 1, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 10);
- $sizer->Add($buttons, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10);
-
- $self->SetSizer($sizer);
- $self->SetMinSize($self->GetSize);
-
- $self->Layout;
-
- wxTheApp->restore_window_pos($self, "object_settings");
-
- return $self;
-}
-
-sub PartsChanged {
- my ($self) = @_;
- return $self->{parts}->PartsChanged;
-}
-
-sub PartSettingsChanged {
- my ($self) = @_;
- return $self->{parts}->PartSettingsChanged || $self->{layers}->LayersChanged;
-}
-
-package Slic3r::GUI::Plater::ObjectDialog::BaseTab;
-use base 'Wx::Panel';
-
-sub model_object {
- my ($self) = @_;
- # $self->GetParent->GetParent is of type Slic3r::GUI::Plater::ObjectSettingsDialog
- return $self->GetParent->GetParent->{model_object};
-}
-
-package Slic3r::GUI::Plater::ObjectDialog::LayersTab;
-use Wx qw(:dialog :id :misc :sizer :systemsettings);
-use Wx::Grid;
-use Wx::Event qw(EVT_GRID_CELL_CHANGED);
-use base 'Slic3r::GUI::Plater::ObjectDialog::BaseTab';
-
-sub new {
- my $class = shift;
- my ($parent, %params) = @_;
- my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize);
-
- my $sizer = Wx::BoxSizer->new(wxVERTICAL);
-
- {
- my $label = Wx::StaticText->new($self, -1, "You can use this section to override the default layer height for parts of this object.",
- wxDefaultPosition, [-1, 40]);
- $label->SetFont(Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
- $sizer->Add($label, 0, wxEXPAND | wxALL, 10);
- }
-
- my $grid = $self->{grid} = Wx::Grid->new($self, -1, wxDefaultPosition, wxDefaultSize);
- $sizer->Add($grid, 1, wxEXPAND | wxALL, 10);
- $grid->CreateGrid(0, 3);
- $grid->DisableDragRowSize;
- $grid->HideRowLabels;
- $grid->SetColLabelValue(0, "Min Z (mm)");
- $grid->SetColLabelValue(1, "Max Z (mm)");
- $grid->SetColLabelValue(2, "Layer height (mm)");
- $grid->SetColSize($_, 135) for 0..2;
- $grid->SetDefaultCellAlignment(wxALIGN_CENTRE, wxALIGN_CENTRE);
-
- # load data
- foreach my $range (@{ $self->model_object->layer_height_ranges }) {
- $grid->AppendRows(1);
- my $i = $grid->GetNumberRows-1;
- $grid->SetCellValue($i, $_, $range->[$_]) for 0..2;
- }
- $grid->AppendRows(1); # append one empty row
-
- EVT_GRID_CELL_CHANGED($grid, sub {
- my ($grid, $event) = @_;
-
- # remove any non-numeric character
- my $value = $grid->GetCellValue($event->GetRow, $event->GetCol);
- $value =~ s/,/./g;
- $value =~ s/[^0-9.]//g;
- $grid->SetCellValue($event->GetRow, $event->GetCol, ($event->GetCol == 2) ? $self->_clamp_layer_height($value) : $value);
-
- # if there's no empty row, let's append one
- for my $i (0 .. $grid->GetNumberRows) {
- if ($i == $grid->GetNumberRows) {
- # if we're here then we found no empty row
- $grid->AppendRows(1);
- last;
- }
- if (!grep $grid->GetCellValue($i, $_), 0..2) {
- # exit loop if this row is empty
- last;
- }
- }
-
- $self->{layers_changed} = 1;
- });
-
- $self->SetSizer($sizer);
- $sizer->SetSizeHints($self);
-
- return $self;
-}
-
-sub _clamp_layer_height
-{
- my ($self, $value) = @_;
- # $self->GetParent->GetParent is of type Slic3r::GUI::Plater::ObjectSettingsDialog
- my $config = $self->GetParent->GetParent->{config};
- if ($value =~ /^[0-9,.E]+$/) {
- # Looks like a number. Validate the layer height.
- my $nozzle_dmrs = $config->get('nozzle_diameter');
- my $min_layer_heights = $config->get('min_layer_height');
- my $max_layer_heights = $config->get('max_layer_height');
- my $min_layer_height = 1000.;
- my $max_layer_height = 0.;
- my $max_nozzle_dmr = 0.;
- for (my $i = 0; $i < int(@{$nozzle_dmrs}); $i += 1) {
- $min_layer_height = $min_layer_heights->[$i] if ($min_layer_heights->[$i] < $min_layer_height);
- $max_layer_height = $max_layer_heights->[$i] if ($max_layer_heights->[$i] > $max_layer_height);
- $max_nozzle_dmr = $nozzle_dmrs ->[$i] if ($nozzle_dmrs ->[$i] > $max_nozzle_dmr );
- }
- $min_layer_height = 0.005 if ($min_layer_height < 0.005);
- $max_layer_height = $max_nozzle_dmr * 0.75 if ($max_layer_height == 0.);
- $max_layer_height = $max_nozzle_dmr if ($max_layer_height > $max_nozzle_dmr);
- return ($value < $min_layer_height) ? $min_layer_height :
- ($value > $max_layer_height) ? $max_layer_height : $value;
- } else {
- # If an invalid numeric value has been entered, use the default layer height.
- return $config->get('layer_height');
- }
-}
-
-sub CanClose {
- my $self = shift;
-
- # validate ranges before allowing user to dismiss the dialog
-
- foreach my $range ($self->_get_ranges) {
- my ($min, $max, $height) = @$range;
- if ($max <= $min) {
- Slic3r::GUI::show_error($self, "Invalid Z range $min-$max.");
- return 0;
- }
- if ($min < 0 || $max < 0) {
- Slic3r::GUI::show_error($self, "Invalid Z range $min-$max.");
- return 0;
- }
- if ($height < 0) {
- Slic3r::GUI::show_error($self, "Invalid layer height $height.");
- return 0;
- }
- # TODO: check for overlapping ranges
- }
-
- return 1;
-}
-
-sub Closing {
- my $self = shift;
-
- # save ranges into the plater object
- $self->model_object->set_layer_height_ranges([ $self->_get_ranges ]);
-}
-
-sub _get_ranges {
- my $self = shift;
-
- my @ranges = ();
- for my $i (0 .. $self->{grid}->GetNumberRows-1) {
- my ($min, $max, $height) = map $self->{grid}->GetCellValue($i, $_), 0..2;
- next if $min eq '' || $max eq '' || $height eq '';
- push @ranges, [ $min, $max, $height ];
- }
- return sort { $a->[0] <=> $b->[0] } @ranges;
-}
-
-sub LayersChanged {
- my ($self) = @_;
- return $self->{layers_changed};
-}
-
-1;
diff --git a/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm b/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm
deleted file mode 100644
index ea4ce7132..000000000
--- a/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm
+++ /dev/null
@@ -1,182 +0,0 @@
-# Included in ObjectSettingsDialog -> ObjectPartsPanel.
-# Maintains, displays, adds and removes overrides of slicing parameters for an object and its modifier mesh.
-
-package Slic3r::GUI::Plater::OverrideSettingsPanel;
-use strict;
-use warnings;
-use utf8;
-
-use List::Util qw(first);
-use Wx qw(:misc :sizer :button wxTAB_TRAVERSAL wxSUNKEN_BORDER wxBITMAP_TYPE_PNG
- wxTheApp);
-use Wx::Event qw(EVT_BUTTON EVT_LEFT_DOWN EVT_MENU);
-use base 'Wx::ScrolledWindow';
-
-use constant ICON_MATERIAL => 0;
-use constant ICON_SOLIDMESH => 1;
-use constant ICON_MODIFIERMESH => 2;
-
-my %icons = (
- 'Advanced' => 'wand.png',
- 'Extruders' => 'funnel.png',
- 'Extrusion Width' => 'funnel.png',
- 'Infill' => 'infill.png',
- 'Layers and Perimeters' => 'layers.png',
- 'Skirt and brim' => 'box.png',
- 'Speed' => 'time.png',
- 'Speed > Acceleration' => 'time.png',
- 'Support material' => 'building.png',
-);
-
-sub new {
- my ($class, $parent, %params) = @_;
- my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
- # C++ class Slic3r::DynamicPrintConfig, initially empty.
- $self->{default_config} = Slic3r::Config->new;
- $self->{config} = Slic3r::Config->new;
- # On change callback.
- $self->{on_change} = $params{on_change};
- $self->{fixed_options} = {};
-
- $self->{sizer} = Wx::BoxSizer->new(wxVERTICAL);
-
- $self->{options_sizer} = Wx::BoxSizer->new(wxVERTICAL);
- $self->{sizer}->Add($self->{options_sizer}, 0, wxEXPAND | wxALL, 0);
-
- # option selector
- {
- # create the button
- my $btn = $self->{btn_add} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new(Slic3r::var("add.png"), wxBITMAP_TYPE_PNG),
- wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE);
- EVT_LEFT_DOWN($btn, sub {
- my $menu = Wx::Menu->new;
- # create category submenus
- my %categories = (); # category => submenu
- foreach my $opt_key (@{$self->{options}}) {
- if (my $cat = $Slic3r::Config::Options->{$opt_key}{category}) {
- $categories{$cat} //= Wx::Menu->new;
- }
- }
- # append submenus to main menu
- my @categories = ('Layers and Perimeters', 'Infill', 'Support material', 'Speed', 'Extruders', 'Extrusion Width', 'Advanced');
- #foreach my $cat (sort keys %categories) {
- foreach my $cat (@categories) {
- wxTheApp->append_submenu($menu, $cat, "", $categories{$cat}, undef, $icons{$cat});
- }
- # append options to submenus
- foreach my $opt_key (@{$self->{options}}) {
- my $cat = $Slic3r::Config::Options->{$opt_key}{category} or next;
- my $cb = sub {
- $self->{config}->set($opt_key, $self->{default_config}->get($opt_key));
- $self->update_optgroup;
- $self->{on_change}->($opt_key) if $self->{on_change};
- };
- wxTheApp->append_menu_item($categories{$cat}, $self->{option_labels}{$opt_key},
- $Slic3r::Config::Options->{$opt_key}{tooltip}, $cb);
- }
- $self->PopupMenu($menu, $btn->GetPosition);
- $menu->Destroy;
- });
-
- my $h_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
- $h_sizer->Add($btn, 0, wxALL, 0);
- $self->{sizer}->Add($h_sizer, 0, wxEXPAND | wxBOTTOM, 10);
- }
-
- $self->SetSizer($self->{sizer});
- $self->SetScrollbars(0, 1, 0, 1);
-
- $self->set_opt_keys($params{opt_keys}) if $params{opt_keys};
- $self->update_optgroup;
-
- return $self;
-}
-
-sub set_default_config {
- my ($self, $config) = @_;
- $self->{default_config} = $config;
-}
-
-sub set_config {
- my ($self, $config) = @_;
- $self->{config} = $config;
- $self->update_optgroup;
-}
-
-sub set_opt_keys {
- my ($self, $opt_keys) = @_;
- # sort options by category+label
- $self->{option_labels} = { map { $_ => $Slic3r::Config::Options->{$_}{full_label} // $Slic3r::Config::Options->{$_}{label} } @$opt_keys };
- $self->{options} = [ sort { $self->{option_labels}{$a} cmp $self->{option_labels}{$b} } @$opt_keys ];
-}
-
-sub set_fixed_options {
- my ($self, $opt_keys) = @_;
- $self->{fixed_options} = { map {$_ => 1} @$opt_keys };
- $self->update_optgroup;
-}
-
-sub update_optgroup {
- my $self = shift;
-
- $self->{options_sizer}->Clear(1);
- return if !defined $self->{config};
-
- my %categories = ();
- foreach my $opt_key (@{$self->{config}->get_keys}) {
- my $category = $Slic3r::Config::Options->{$opt_key}{category};
- $categories{$category} ||= [];
- push @{$categories{$category}}, $opt_key;
- }
- foreach my $category (sort keys %categories) {
- my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
- parent => $self,
- title => $category,
- config => $self->{config},
- full_labels => 1,
- label_font => $Slic3r::GUI::small_font,
- sidetext_font => $Slic3r::GUI::small_font,
- label_width => 150,
- on_change => sub { $self->{on_change}->() if $self->{on_change} },
- extra_column => sub {
- my ($line) = @_;
-
- my $opt_key = $line->get_options->[0]->opt_id; # we assume that we have one option per line
-
- # disallow deleting fixed options
- return undef if $self->{fixed_options}{$opt_key};
-
- my $btn = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new(Slic3r::var("delete.png"), wxBITMAP_TYPE_PNG),
- wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE);
- EVT_BUTTON($self, $btn, sub {
- $self->{config}->erase($opt_key);
- $self->{on_change}->() if $self->{on_change};
- wxTheApp->CallAfter(sub { $self->update_optgroup });
- });
- return $btn;
- },
- );
- foreach my $opt_key (sort @{$categories{$category}}) {
- $optgroup->append_single_option_line($opt_key);
- }
- $self->{options_sizer}->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM, 0);
- }
- $self->GetParent->Layout; # we need this for showing scrollbars
-}
-
-# work around a wxMAC bug causing controls not being disabled when calling Disable() on a Window
-sub enable {
- my ($self) = @_;
-
- $self->{btn_add}->Enable;
- $self->Enable;
-}
-
-sub disable {
- my ($self) = @_;
-
- $self->{btn_add}->Disable;
- $self->Disable;
-}
-
-1;
diff --git a/lib/Slic3r/GUI/SystemInfo.pm b/lib/Slic3r/GUI/SystemInfo.pm
deleted file mode 100644
index 717ff12e5..000000000
--- a/lib/Slic3r/GUI/SystemInfo.pm
+++ /dev/null
@@ -1,70 +0,0 @@
-package Slic3r::GUI::SystemInfo;
-use strict;
-use warnings;
-use utf8;
-
-use Wx qw(:font :html :misc :dialog :sizer :systemsettings :frame :id wxTheClipboard);
-use Wx::Event qw(EVT_HTML_LINK_CLICKED EVT_LEFT_DOWN EVT_BUTTON);
-use Wx::Html;
-use base 'Wx::Dialog';
-
-sub new {
- my ($class, %params) = @_;
- my $self = $class->SUPER::new($params{parent}, -1, 'Slic3r Prusa Edition - System Information', wxDefaultPosition, [600, 340],
- wxDEFAULT_DIALOG_STYLE | wxMAXIMIZE_BOX | wxRESIZE_BORDER);
- $self->{text_info} = $params{text_info};
-
- $self->SetBackgroundColour(Wx::wxWHITE);
- my $vsizer = Wx::BoxSizer->new(wxVERTICAL);
- $self->SetSizer($vsizer);
-
- # text
- my $text =
- '<html>' .
- '<body bgcolor="#ffffff" link="#808080">' .
- ($params{slic3r_info} // '') .
- ($params{copyright_info} // '') .
- ($params{system_info} // '') .
- ($params{opengl_info} // '') .
- '</body>' .
- '</html>';
- my $html = $self->{html} = Wx::HtmlWindow->new($self, -1, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_AUTO);
- my $font = Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
- my $size = &Wx::wxMSW ? 8 : 10;
- $html->SetFonts($font->GetFaceName, $font->GetFaceName, [$size * 1.5, $size * 1.4, $size * 1.3, $size, $size, $size, $size]);
- $html->SetBorders(10);
- $html->SetPage($text);
- $vsizer->Add($html, 1, wxEXPAND | wxALIGN_LEFT | wxRIGHT | wxBOTTOM, 0);
- EVT_HTML_LINK_CLICKED($self, $html, \&link_clicked);
-
- my $buttons = $self->CreateStdDialogButtonSizer(wxOK);
- my $btn_copy_to_clipboard = Wx::Button->new($self, -1, "Copy to Clipboard", wxDefaultPosition, wxDefaultSize);
- $buttons->Insert(0, $btn_copy_to_clipboard, 0, wxLEFT, 5);
- EVT_BUTTON($self, $btn_copy_to_clipboard, \&copy_to_clipboard);
- $self->SetEscapeId(wxID_CLOSE);
- EVT_BUTTON($self, wxID_CLOSE, sub {
- $self->EndModal(wxID_CLOSE);
- $self->Close;
- });
-# $vsizer->Add($buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);
- $vsizer->Add($buttons, 0, wxEXPAND | wxALL, 5);
-
- return $self;
-}
-
-sub link_clicked {
- my ($self, $event) = @_;
-
- Wx::LaunchDefaultBrowser($event->GetLinkInfo->GetHref);
- $event->Skip(0);
-}
-
-sub copy_to_clipboard {
- my ($self, $event) = @_;
- my $data = $self->{text_info};
- wxTheClipboard->Open;
- wxTheClipboard->SetData(Wx::TextDataObject->new($data));
- wxTheClipboard->Close;
-}
-
-1;
diff --git a/lib/Slic3r/Geometry.pm b/lib/Slic3r/Geometry.pm
index 180d0d028..286a73e2d 100644
--- a/lib/Slic3r/Geometry.pm
+++ b/lib/Slic3r/Geometry.pm
@@ -122,6 +122,7 @@ sub line_intersection {
: undef;
}
+# Used by test cases.
sub collinear {
my ($line1, $line2, $require_overlapping) = @_;
my $intersection = _line_intersection(map @$_, @$line1, @$line2);
@@ -226,6 +227,7 @@ sub bounding_box {
return @bb[X1,Y1,X2,Y2];
}
+# used by ExPolygon::size
sub size_2D {
my @bounding_box = bounding_box(@_);
return (
@@ -234,6 +236,7 @@ sub size_2D {
);
}
+# Used by sub collinear, which is used by test cases.
# bounding_box_intersect($d, @a, @b)
# Return true if the given bounding boxes @a and @b intersect
# in $d dimensions. Used by sub collinear.
@@ -252,6 +255,7 @@ sub bounding_box_intersect {
return 1;
}
+# Used by test cases.
# this assumes a CCW rotation from $p2 to $p3 around $p1
sub angle3points {
my ($p1, $p2, $p3) = @_;
diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm
index 38aa318e6..85c3ed757 100644
--- a/lib/Slic3r/Print.pm
+++ b/lib/Slic3r/Print.pm
@@ -24,7 +24,7 @@ sub run_post_process_scripts {
my ($self, $output_file) = @_;
# run post-processing scripts
if (@{$self->config->post_process}) {
-# $self->status_cb->(95, "Running post-processing scripts");
+# $self->set_status(95, "Running post-processing scripts");
$self->config->setenv;
for my $script (@{$self->config->post_process}) {
# Ignore empty post processing script lines.
@@ -57,13 +57,13 @@ sub export_png {
for(my $oi = 0; $oi < $objnum; $oi++)
{
$sobjects[$oi]->slice;
- $self->status_cb->(($oi + 1)*100/$objnum - 1, "Slicing...");
+ $self->set_status(($oi + 1)*100/$objnum - 1, "Slicing...");
}
my $fh = $params{output_file};
- $self->status_cb->(90, "Exporting zipped archive...");
+ $self->set_status(90, "Exporting zipped archive...");
$self->print_to_png($fh);
- $self->status_cb->(100, "Done.");
+ $self->set_status(100, "Done.");
}
# Export SVG slices for the offline SLA printing.
@@ -77,7 +77,7 @@ sub export_svg {
for(my $oi = 0; $oi < $objnum; $oi++)
{
$sobjects[$oi]->slice;
- $self->status_cb->(($oi + 1)*100/$objnum - 1, "Slicing...");
+ $self->set_status(($oi + 1)*100/$objnum - 1, "Slicing...");
}
my $fh = $params{output_fh};
diff --git a/lib/Slic3r/SVG.pm b/lib/Slic3r/SVG.pm
deleted file mode 100644
index 1aa7dd27d..000000000
--- a/lib/Slic3r/SVG.pm
+++ /dev/null
@@ -1,142 +0,0 @@
-package Slic3r::SVG;
-use strict;
-use warnings;
-
-use SVG;
-
-use constant X => 0;
-use constant Y => 1;
-
-our $filltype = 'evenodd';
-
-sub factor {
- return &Slic3r::SCALING_FACTOR * 10;
-}
-
-sub svg {
- my $svg = SVG->new(width => 200 * 10, height => 200 * 10);
- my $marker_end = $svg->marker(
- id => "endArrow",
- viewBox => "0 0 10 10",
- refX => "1",
- refY => "5",
- markerUnits => "strokeWidth",
- orient => "auto",
- markerWidth => "10",
- markerHeight => "8",
- );
- $marker_end->polyline(
- points => "0,0 10,5 0,10 1,5",
- fill => "darkblue",
- );
-
- return $svg;
-}
-
-sub output {
- my ($filename, @things) = @_;
-
- my $svg = svg();
- my $arrows = 1;
-
- while (my $type = shift @things) {
- my $value = shift @things;
-
- if ($type eq 'no_arrows') {
- $arrows = 0;
- } elsif ($type =~ /^(?:(.+?)_)?expolygons$/) {
- my $colour = $1;
- $value = [ map $_->pp, @$value ];
-
- my $g = $svg->group(
- style => {
- 'stroke-width' => 0,
- 'stroke' => $colour || 'black',
- 'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
- 'fill-type' => $filltype,
- },
- );
- foreach my $expolygon (@$value) {
- my $points = join ' ', map "M $_ z", map join(" ", reverse map $_->[0]*factor() . " " . $_->[1]*factor(), @$_), @$expolygon;
- $g->path(
- d => $points,
- );
- }
- } elsif ($type =~ /^(?:(.+?)_)?(polygon|polyline)s$/) {
- my ($colour, $method) = ($1, $2);
- $value = [ map $_->pp, @$value ];
-
- my $g = $svg->group(
- style => {
- 'stroke-width' => ($method eq 'polyline') ? 1 : 0,
- 'stroke' => $colour || 'black',
- 'fill' => ($type !~ /polygons/ ? 'none' : ($colour || 'grey')),
- },
- );
- foreach my $polygon (@$value) {
- my $path = $svg->get_path(
- 'x' => [ map($_->[X] * factor(), @$polygon) ],
- 'y' => [ map($_->[Y] * factor(), @$polygon) ],
- -type => 'polygon',
- );
- $g->$method(
- %$path,
- 'marker-end' => !$arrows ? "" : "url(#endArrow)",
- );
- }
- } elsif ($type =~ /^(?:(.+?)_)?points$/) {
- my $colour = $1 // 'black';
- my $r = $colour eq 'black' ? 1 : 3;
- $value = [ map $_->pp, @$value ];
-
- my $g = $svg->group(
- style => {
- 'stroke-width' => 2,
- 'stroke' => $colour,
- 'fill' => $colour,
- },
- );
- foreach my $point (@$value) {
- $g->circle(
- cx => $point->[X] * factor(),
- cy => $point->[Y] * factor(),
- r => $r,
- );
- }
- } elsif ($type =~ /^(?:(.+?)_)?lines$/) {
- my $colour = $1;
- $value = [ map $_->pp, @$value ];
-
- my $g = $svg->group(
- style => {
- 'stroke-width' => 2,
- },
- );
- foreach my $line (@$value) {
- $g->line(
- x1 => $line->[0][X] * factor(),
- y1 => $line->[0][Y] * factor(),
- x2 => $line->[1][X] * factor(),
- y2 => $line->[1][Y] * factor(),
- style => {
- 'stroke' => $colour || 'black',
- },
- 'marker-end' => !$arrows ? "" : "url(#endArrow)",
- );
- }
- }
- }
-
- write_svg($svg, $filename);
-}
-
-sub write_svg {
- my ($svg, $filename) = @_;
-
- Slic3r::open(\my $fh, '>', $filename);
- print $fh $svg->xmlify;
- close $fh;
- printf "SVG written to %s\n", $filename;
-}
-
-1;