mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-06 05:24:01 -06:00
merge with master
This commit is contained in:
commit
50a45949d1
177 changed files with 9348 additions and 3124 deletions
|
@ -1390,7 +1390,7 @@ sub _load_image_set_texture {
|
|||
my ($self, $file_name) = @_;
|
||||
# Load a PNG with an alpha channel.
|
||||
my $img = Wx::Image->new;
|
||||
$img->LoadFile($Slic3r::var->($file_name), wxBITMAP_TYPE_PNG);
|
||||
$img->LoadFile(Slic3r::var($file_name), wxBITMAP_TYPE_PNG);
|
||||
# Get RGB & alpha raw data from wxImage, interleave them into a Perl array.
|
||||
my @rgb = unpack 'C*', $img->GetData();
|
||||
my @alpha = $img->HasAlpha ? unpack 'C*', $img->GetAlpha() : (255) x (int(@rgb) / 3);
|
||||
|
|
|
@ -97,7 +97,7 @@ sub new {
|
|||
my $class = shift;
|
||||
my $self = $class->SUPER::new(@_);
|
||||
|
||||
$self->{logo} = Wx::Bitmap->new($Slic3r::var->("Slic3r_192px.png"), wxBITMAP_TYPE_PNG);
|
||||
$self->{logo} = Wx::Bitmap->new(Slic3r::var("Slic3r_192px.png"), wxBITMAP_TYPE_PNG);
|
||||
$self->SetMinSize(Wx::Size->new($self->{logo}->GetWidth, $self->{logo}->GetHeight));
|
||||
|
||||
EVT_PAINT($self, \&repaint);
|
||||
|
|
|
@ -14,14 +14,14 @@ our $wizard = 'Wizard';
|
|||
$wizard = 'Assistant' if &Wx::wxMAC || &Wx::wxGTK;
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my ($parent) = @_;
|
||||
my ($class, $parent, $presets) = @_;
|
||||
my $self = $class->SUPER::new($parent, -1, "Configuration $wizard");
|
||||
|
||||
# initialize an empty repository
|
||||
$self->{config} = Slic3r::Config->new;
|
||||
|
||||
$self->add_page(Slic3r::GUI::ConfigWizard::Page::Welcome->new($self));
|
||||
my $welcome_page = Slic3r::GUI::ConfigWizard::Page::Welcome->new($self);
|
||||
$self->add_page($welcome_page);
|
||||
$self->add_page(Slic3r::GUI::ConfigWizard::Page::Firmware->new($self));
|
||||
$self->add_page(Slic3r::GUI::ConfigWizard::Page::Bed->new($self));
|
||||
$self->add_page(Slic3r::GUI::ConfigWizard::Page::Nozzle->new($self));
|
||||
|
@ -32,12 +32,13 @@ sub new {
|
|||
|
||||
$_->build_index for @{$self->{pages}};
|
||||
|
||||
$welcome_page->set_selection_presets([@{$presets}, 'Other']);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub add_page {
|
||||
my $self = shift;
|
||||
my ($page) = @_;
|
||||
my ($self, $page) = @_;
|
||||
|
||||
my $n = push @{$self->{pages}}, $page;
|
||||
# add first page to the page area sizer
|
||||
|
@ -48,13 +49,13 @@ sub add_page {
|
|||
}
|
||||
|
||||
sub run {
|
||||
my $self = shift;
|
||||
|
||||
my ($self) = @_;
|
||||
my $result = undef;
|
||||
if (Wx::Wizard::RunWizard($self, $self->{pages}[0])) {
|
||||
|
||||
# it would be cleaner to have these defined inside each page class,
|
||||
# in some event getting called before leaving the page
|
||||
{
|
||||
my $preset_name = $self->{pages}[0]->{preset_name};
|
||||
if ($preset_name eq 'Other') {
|
||||
# it would be cleaner to have these defined inside each page class,
|
||||
# in some event getting called before leaving the page
|
||||
# set first_layer_height + layer_height based on nozzle_diameter
|
||||
my $nozzle = $self->{config}->nozzle_diameter;
|
||||
$self->{config}->set('first_layer_height', $nozzle->[0]);
|
||||
|
@ -66,14 +67,13 @@ sub run {
|
|||
# set first_layer_bed_temperature to temperature + 5
|
||||
$self->{config}->set('first_layer_bed_temperature',
|
||||
[ ($self->{config}->bed_temperature->[0] > 0) ? ($self->{config}->bed_temperature->[0] + 5) : 0 ]);
|
||||
$result = $self->{config};
|
||||
} else {
|
||||
$result = $preset_name;
|
||||
}
|
||||
|
||||
$self->Destroy;
|
||||
return $self->{config};
|
||||
} else {
|
||||
$self->Destroy;
|
||||
return undef;
|
||||
}
|
||||
$self->Destroy;
|
||||
return $result;
|
||||
}
|
||||
|
||||
package Slic3r::GUI::ConfigWizard::Index;
|
||||
|
@ -89,11 +89,11 @@ sub new {
|
|||
push @{$self->{titles}}, $title;
|
||||
$self->{own_index} = 0;
|
||||
|
||||
$self->{bullets}->{before} = Wx::Bitmap->new($Slic3r::var->("bullet_black.png"), wxBITMAP_TYPE_PNG);
|
||||
$self->{bullets}->{own} = Wx::Bitmap->new($Slic3r::var->("bullet_blue.png"), wxBITMAP_TYPE_PNG);
|
||||
$self->{bullets}->{after} = Wx::Bitmap->new($Slic3r::var->("bullet_white.png"), wxBITMAP_TYPE_PNG);
|
||||
$self->{bullets}->{before} = Wx::Bitmap->new(Slic3r::var("bullet_black.png"), wxBITMAP_TYPE_PNG);
|
||||
$self->{bullets}->{own} = Wx::Bitmap->new(Slic3r::var("bullet_blue.png"), wxBITMAP_TYPE_PNG);
|
||||
$self->{bullets}->{after} = Wx::Bitmap->new(Slic3r::var("bullet_white.png"), wxBITMAP_TYPE_PNG);
|
||||
|
||||
$self->{background} = Wx::Bitmap->new($Slic3r::var->("Slic3r_192px_transparent.png"), wxBITMAP_TYPE_PNG);
|
||||
$self->{background} = Wx::Bitmap->new(Slic3r::var("Slic3r_192px_transparent.png"), wxBITMAP_TYPE_PNG);
|
||||
$self->SetMinSize(Wx::Size->new($self->{background}->GetWidth, $self->{background}->GetHeight));
|
||||
|
||||
EVT_PAINT($self, \&repaint);
|
||||
|
@ -127,6 +127,8 @@ sub repaint {
|
|||
|
||||
$dc->SetTextForeground(Wx::Colour->new(128, 128, 128)) if $i > $self->{own_index};
|
||||
$dc->DrawLabel($_, $bullet, Wx::Rect->new(0, $i * ($label_h + $gap), $label_w, $label_h));
|
||||
# Only show the first bullet if this is the only wizard page to be displayed.
|
||||
last if $i == 0 && $self->{just_welcome};
|
||||
$i++;
|
||||
}
|
||||
|
||||
|
@ -202,7 +204,7 @@ sub append_option {
|
|||
|
||||
# populate repository with the factory default
|
||||
my ($opt_key, $opt_index) = split /#/, $full_key, 2;
|
||||
$self->config->apply(Slic3r::Config->new_from_defaults($opt_key));
|
||||
$self->config->apply(Slic3r::Config::new_from_defaults_keys([$opt_key]));
|
||||
|
||||
# draw the control
|
||||
my $optgroup = Slic3r::GUI::ConfigOptionsGroup->new(
|
||||
|
@ -263,19 +265,58 @@ sub config {
|
|||
|
||||
package Slic3r::GUI::ConfigWizard::Page::Welcome;
|
||||
use base 'Slic3r::GUI::ConfigWizard::Page';
|
||||
use Wx qw(:misc :sizer wxID_FORWARD);
|
||||
use Wx::Event qw(EVT_ACTIVATE EVT_CHOICE);
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my ($parent) = @_;
|
||||
my $self = $class->SUPER::new($parent, "Welcome to the Slic3r Configuration $wizard", 'Welcome');
|
||||
$self->{full_wizard_workflow} = 1;
|
||||
|
||||
$self->append_text('Hello, welcome to Slic3r! This '.lc($wizard).' helps you with the initial configuration; just a few settings and you will be ready to print.');
|
||||
$self->append_text('To import an existing configuration instead, cancel this '.lc($wizard).' and use the Open Config menu item found in the File menu.');
|
||||
$self->append_text('To continue, click Next.');
|
||||
$self->append_text('Hello, welcome to Slic3r Prusa Edition! This '.lc($wizard).' helps you with the initial configuration; just a few settings and you will be ready to print.');
|
||||
$self->append_text('Please select your printer vendor and printer type. If your printer is not listed, you may try your luck and select a similar one. If you select "Other", this ' . lc($wizard) . ' will let you set the basic 3D printer parameters.');
|
||||
# To import an existing configuration instead, cancel this '.lc($wizard).' and use the Open Config menu item found in the File menu.');
|
||||
$self->append_text('If you received a configuration file or a config bundle from your 3D printer vendor, cancel this '.lc($wizard).' and use the "File->Load Config" or "File->Load Config Bundle" menu.');
|
||||
|
||||
$self->{choice} = my $choice = Wx::Choice->new($self, -1, wxDefaultPosition, wxDefaultSize, []);
|
||||
$self->{vsizer}->Add($choice, 0, wxEXPAND | wxTOP | wxBOTTOM, 10);
|
||||
|
||||
EVT_CHOICE($parent, $choice, sub {
|
||||
my $sel = $self->{choice}->GetStringSelection;
|
||||
$self->{preset_name} = $sel;
|
||||
$self->set_full_wizard_workflow(($sel eq 'Other') || ($sel eq ''));
|
||||
});
|
||||
|
||||
EVT_ACTIVATE($parent, sub {
|
||||
$self->set_full_wizard_workflow($self->{preset_name} eq 'Other');
|
||||
});
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub set_full_wizard_workflow {
|
||||
my ($self, $full_workflow) = @_;
|
||||
$self->{full_wizard_workflow} = $full_workflow;
|
||||
$self->{index}->{just_welcome} = !$full_workflow;
|
||||
$self->{index}->Refresh;
|
||||
my $next_button = $self->GetParent->FindWindow(wxID_FORWARD);
|
||||
$next_button->SetLabel($full_workflow ? "&Next >" : "&Finish");
|
||||
}
|
||||
|
||||
# Set the preset names, select the first item.
|
||||
sub set_selection_presets {
|
||||
my ($self, $names) = @_;
|
||||
$self->{choice}->Append($names);
|
||||
$self->{choice}->SetSelection(0);
|
||||
$self->{preset_name} = $names->[0];
|
||||
}
|
||||
|
||||
sub GetNext {
|
||||
my $self = shift;
|
||||
return $self->{full_wizard_workflow} ? $self->{next_page} : undef;
|
||||
}
|
||||
|
||||
package Slic3r::GUI::ConfigWizard::Page::Firmware;
|
||||
use base 'Slic3r::GUI::ConfigWizard::Page';
|
||||
|
||||
|
@ -300,7 +341,7 @@ sub new {
|
|||
|
||||
$self->append_text('Set the shape of your printer\'s bed, then click Next.');
|
||||
|
||||
$self->config->apply(Slic3r::Config->new_from_defaults('bed_shape'));
|
||||
$self->config->apply(Slic3r::Config::new_from_defaults_keys(['bed_shape']));
|
||||
$self->{bed_shape_panel} = my $panel = Slic3r::GUI::BedShapePanel->new($self, $self->config->bed_shape);
|
||||
$self->{bed_shape_panel}->on_change(sub {
|
||||
$self->config->set('bed_shape', $self->{bed_shape_panel}->GetValue);
|
||||
|
|
|
@ -10,6 +10,7 @@ use utf8;
|
|||
use Wx qw(wxTheApp :frame :id :misc :sizer :bitmap :button :icon :dialog);
|
||||
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));
|
||||
|
||||
|
@ -32,27 +33,25 @@ sub new {
|
|||
|
||||
# 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),
|
||||
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);
|
||||
$btn->SetToolTipString("Add printer…")
|
||||
if $btn->can('SetToolTipString');
|
||||
|
||||
EVT_LEFT_DOWN($btn, sub {
|
||||
my $menu = Wx::Menu->new;
|
||||
my %presets = wxTheApp->presets('printer');
|
||||
|
||||
my $menu = Wx::Menu->new;
|
||||
my @panels = $self->print_panels;
|
||||
# remove printers that already exist
|
||||
my @panels = $self->print_panels;
|
||||
delete $presets{$_} for map $_->printer_name, @panels;
|
||||
|
||||
foreach my $preset_name (sort keys %presets) {
|
||||
my $config = Slic3r::Config->load($presets{$preset_name});
|
||||
next if !$config->serial_port;
|
||||
|
||||
# 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, $config);
|
||||
$self->add_printer($preset_name, $myconfig);
|
||||
});
|
||||
}
|
||||
$self->PopupMenu($menu, $btn->GetPosition);
|
||||
|
@ -98,12 +97,8 @@ sub OnActivate {
|
|||
my ($self) = @_;
|
||||
|
||||
# get all available presets
|
||||
my %presets = ();
|
||||
{
|
||||
my %all = wxTheApp->presets('printer');
|
||||
my %configs = map { my $name = $_; $name => Slic3r::Config->load($all{$name}) } keys %all;
|
||||
%presets = map { $_ => $configs{$_} } grep $configs{$_}->serial_port, keys %all;
|
||||
}
|
||||
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 = ();
|
||||
|
@ -121,7 +116,7 @@ sub OnActivate {
|
|||
}
|
||||
if (!%active) {
|
||||
# enable printers whose port is available
|
||||
my %ports = map { $_ => 1 } wxTheApp->scan_serial_ports;
|
||||
my %ports = map { $_ => 1 } Slic3r::GUI::scan_serial_ports;
|
||||
$active{$_} = 1
|
||||
for grep exists $ports{$presets{$_}->serial_port}, keys %presets;
|
||||
}
|
||||
|
@ -177,26 +172,19 @@ sub print_panels {
|
|||
map $_->GetWindow, $self->{sizer}->GetChildren;
|
||||
}
|
||||
|
||||
# Called by
|
||||
# Slic3r::GUI::Tab::Print::_on_presets_changed
|
||||
# Slic3r::GUI::Tab::Filament::_on_presets_changed
|
||||
# Slic3r::GUI::Tab::Printer::_on_presets_changed
|
||||
# when the presets are loaded or the user select another preset.
|
||||
# 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 = shift;
|
||||
my ($group, $presets, $default_suppressed, $selected, $is_dirty) = @_;
|
||||
|
||||
my ($self, $presets) = @_;
|
||||
# update configs of currently loaded print panels
|
||||
my @presets = @$presets;
|
||||
foreach my $panel ($self->print_panels) {
|
||||
foreach my $preset (@$presets) {
|
||||
if ($panel->printer_name eq $preset->name) {
|
||||
my $config = $preset->config(\@ConfigOptions);
|
||||
$panel->config->apply($config);
|
||||
}
|
||||
}
|
||||
my $preset = $presets->find_preset($panel->printer_name, 0);
|
||||
$panel->config($preset->config->clone_only(\@ConfigOptions))
|
||||
if defined $preset;
|
||||
}
|
||||
|
||||
$self->_selected_printer_preset($presets->[$selected]->name);
|
||||
|
||||
$self->_selected_printer_preset($presets->get_selected_preset->name);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -34,7 +34,7 @@ sub new {
|
|||
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->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);
|
||||
|
|
|
@ -103,7 +103,7 @@ sub new {
|
|||
$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),
|
||||
$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');
|
||||
|
@ -127,7 +127,7 @@ sub new {
|
|||
{
|
||||
$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));
|
||||
$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);
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ sub new {
|
|||
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));
|
||||
$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);
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ sub new {
|
|||
{
|
||||
$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->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 {
|
||||
|
@ -348,7 +348,7 @@ sub update_serial_ports {
|
|||
my $cb = $self->{serial_port_combobox};
|
||||
my $current = $cb->GetValue;
|
||||
$cb->Clear;
|
||||
$cb->Append($_) for wxTheApp->scan_serial_ports;
|
||||
$cb->Append($_) for Slic3r::GUI::scan_serial_ports;
|
||||
$cb->SetValue($current);
|
||||
}
|
||||
|
||||
|
@ -577,7 +577,7 @@ sub new {
|
|||
$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));
|
||||
$btn->SetBitmap(Wx::Bitmap->new(Slic3r::var("delete.png"), wxBITMAP_TYPE_PNG));
|
||||
if ($job->printing) {
|
||||
$btn->Hide;
|
||||
}
|
||||
|
@ -597,8 +597,8 @@ sub new {
|
|||
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->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);
|
||||
|
@ -616,8 +616,8 @@ sub new {
|
|||
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));
|
||||
$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 {
|
||||
|
@ -633,8 +633,8 @@ sub new {
|
|||
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));
|
||||
$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 {
|
||||
|
@ -650,8 +650,8 @@ sub new {
|
|||
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));
|
||||
$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 {
|
||||
|
|
|
@ -6,6 +6,7 @@ use warnings;
|
|||
use utf8;
|
||||
|
||||
use File::Basename qw(basename dirname);
|
||||
use FindBin;
|
||||
use List::Util qw(min);
|
||||
use Slic3r::Geometry qw(X Y);
|
||||
use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedialog
|
||||
|
@ -21,13 +22,14 @@ sub new {
|
|||
my ($class, %params) = @_;
|
||||
|
||||
my $self = $class->SUPER::new(undef, -1, $Slic3r::FORK_NAME . ' - ' . $Slic3r::VERSION, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE);
|
||||
Slic3r::GUI::set_main_frame($self);
|
||||
if ($^O eq 'MSWin32') {
|
||||
# Load the icon either from the exe, or fron the ico file.
|
||||
my $iconfile = $Slic3r::var->('..\slic3r.exe');
|
||||
$iconfile = $Slic3r::var->("Slic3r.ico") unless -f $iconfile;
|
||||
# Load the icon either from the exe, or from the ico file.
|
||||
my $iconfile = Slic3r::decode_path($FindBin::Bin) . '\slic3r.exe';
|
||||
$iconfile = Slic3r::var("Slic3r.ico") unless -f $iconfile;
|
||||
$self->SetIcon(Wx::Icon->new($iconfile, wxBITMAP_TYPE_ICO));
|
||||
} else {
|
||||
$self->SetIcon(Wx::Icon->new($Slic3r::var->("Slic3r_128px.png"), wxBITMAP_TYPE_PNG));
|
||||
$self->SetIcon(Wx::Icon->new(Slic3r::var("Slic3r_128px.png"), wxBITMAP_TYPE_PNG));
|
||||
}
|
||||
|
||||
# store input params
|
||||
|
@ -69,15 +71,15 @@ sub new {
|
|||
# declare events
|
||||
EVT_CLOSE($self, sub {
|
||||
my (undef, $event) = @_;
|
||||
|
||||
if ($event->CanVeto && !$self->check_unsaved_changes) {
|
||||
$event->Veto;
|
||||
return;
|
||||
}
|
||||
|
||||
# save window size
|
||||
wxTheApp->save_window_pos($self, "main_frame");
|
||||
|
||||
# Save the slic3r.ini. Usually the ini file is saved from "on idle" callback,
|
||||
# but in rare cases it may not have been called yet.
|
||||
wxTheApp->{app_config}->save;
|
||||
# propagate event
|
||||
$event->Skip;
|
||||
});
|
||||
|
@ -91,6 +93,8 @@ sub _init_tabpanel {
|
|||
my ($self) = @_;
|
||||
|
||||
$self->{tabpanel} = my $panel = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL);
|
||||
Slic3r::GUI::set_tab_panel($panel);
|
||||
|
||||
EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub {
|
||||
my $panel = $self->{tabpanel}->GetCurrentPage;
|
||||
$panel->OnActivate if $panel->can('OnActivate');
|
||||
|
@ -112,7 +116,7 @@ sub _init_tabpanel {
|
|||
# Callback to be executed after any of the configuration fields (Perl class Slic3r::GUI::OptionsGroup::Field) change their value.
|
||||
$tab->on_value_change(sub {
|
||||
my ($opt_key, $value) = @_;
|
||||
my $config = $tab->config;
|
||||
my $config = $tab->{presets}->get_current_preset->config;
|
||||
if ($self->{plater}) {
|
||||
$self->{plater}->on_config_change($config); # propagate config change events to the plater
|
||||
$self->{plater}->on_extruders_change($value) if $opt_key eq 'extruders_count';
|
||||
|
@ -126,24 +130,38 @@ sub _init_tabpanel {
|
|||
if ($self->{plater}) {
|
||||
# Update preset combo boxes (Print settings, Filament, Printer) from their respective tabs.
|
||||
$self->{plater}->update_presets($tab_name, @_);
|
||||
$self->{plater}->on_config_change($tab->config);
|
||||
if ($self->{controller}) {
|
||||
$self->{controller}->update_presets($tab_name, @_);
|
||||
if ($tab_name eq 'printer') {
|
||||
# Printer selected at the Printer tab, update "compatible" marks at the print and filament selectors.
|
||||
wxTheApp->{preset_bundle}->print->update_tab_ui(
|
||||
$self->{options_tabs}{'print'}->{presets_choice},
|
||||
$self->{options_tabs}{'print'}->{show_incompatible_presets});
|
||||
wxTheApp->{preset_bundle}->filament->update_tab_ui(
|
||||
$self->{options_tabs}{'filament'}->{presets_choice},
|
||||
$self->{options_tabs}{'filament'}->{show_incompatible_presets});
|
||||
# Update the controller printers.
|
||||
$self->{controller}->update_presets(@_) if $self->{controller};
|
||||
}
|
||||
$self->{plater}->on_config_change($tab->{presets}->get_current_preset->config);
|
||||
}
|
||||
});
|
||||
$tab->load_presets;
|
||||
# Load the currently selected preset into the GUI, update the preset selection box.
|
||||
$tab->load_current_preset;
|
||||
$panel->AddPage($tab, $tab->title);
|
||||
}
|
||||
|
||||
#TODO this is an example of a Slic3r XS interface call to add a new preset editor page to the main view.
|
||||
# Slic3r::GUI::create_preset_tab("print");
|
||||
|
||||
if ($self->{plater}) {
|
||||
$self->{plater}->on_select_preset(sub {
|
||||
my ($group, $i) = @_;
|
||||
$self->{options_tabs}{$group}->select_preset($i);
|
||||
my ($group, $name) = @_;
|
||||
$self->{options_tabs}{$group}->select_preset($name);
|
||||
});
|
||||
|
||||
# load initial config
|
||||
$self->{plater}->on_config_change($self->config);
|
||||
my $full_config = wxTheApp->{preset_bundle}->full_config;
|
||||
$self->{plater}->on_config_change($full_config);
|
||||
# Show a correct number of filament fields.
|
||||
$self->{plater}->on_extruders_change(int(@{$full_config->nozzle_diameter}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,6 +171,9 @@ sub _init_menubar {
|
|||
# File menu
|
||||
my $fileMenu = Wx::Menu->new;
|
||||
{
|
||||
wxTheApp->append_menu_item($fileMenu, "Open STL/OBJ/AMF…\tCtrl+O", 'Open a model', sub {
|
||||
$self->{plater}->add if $self->{plater};
|
||||
}, undef, undef); #'brick_add.png');
|
||||
$self->_append_menu_item($fileMenu, "&Load Config…\tCtrl+L", 'Load exported configuration file', sub {
|
||||
$self->load_config_file;
|
||||
}, undef, 'plugin_add.png');
|
||||
|
@ -262,13 +283,14 @@ sub _init_menubar {
|
|||
# \xA0 is a non-breaing space. It is entered here to spoil the automatic accelerators,
|
||||
# as the simple numeric accelerators spoil all numeric data entry.
|
||||
# The camera control accelerators are captured by 3DScene Perl module instead.
|
||||
$self->_append_menu_item($self->{viewMenu}, "Iso\t\xA00" , 'Iso View' , sub { $self->select_view('iso' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, "Top\t\xA01" , 'Top View' , sub { $self->select_view('top' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, "Bottom\t\xA02" , 'Bottom View' , sub { $self->select_view('bottom' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, "Front\t\xA03" , 'Front View' , sub { $self->select_view('front' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, "Rear\t\xA04" , 'Rear View' , sub { $self->select_view('rear' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, "Left\t\xA05" , 'Left View' , sub { $self->select_view('left' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, "Right\t\xA06" , 'Right View' , sub { $self->select_view('right' ); });
|
||||
my $accel = ($^O eq 'MSWin32') ? sub { $_[0] . "\t\xA0" . $_[1] } : sub { $_[0] };
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Iso', '0'), 'Iso View' , sub { $self->select_view('iso' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Top', '1'), 'Top View' , sub { $self->select_view('top' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Bottom', '2'), 'Bottom View' , sub { $self->select_view('bottom' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Front', '3'), 'Front View' , sub { $self->select_view('front' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Rear', '4'), 'Rear View' , sub { $self->select_view('rear' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Left', '5'), 'Left View' , sub { $self->select_view('left' ); });
|
||||
$self->_append_menu_item($self->{viewMenu}, $accel->('Right', '6'), 'Right View' , sub { $self->select_view('right' ); });
|
||||
}
|
||||
|
||||
# Help menu
|
||||
|
@ -317,6 +339,8 @@ sub _init_menubar {
|
|||
$menubar->Append($windowMenu, "&Window");
|
||||
$menubar->Append($self->{viewMenu}, "&View") if $self->{viewMenu};
|
||||
$menubar->Append($helpMenu, "&Help");
|
||||
# Add an optional debug menu. In production code, the add_debug_menu() call should do nothing.
|
||||
Slic3r::GUI::add_debug_menu($menubar);
|
||||
$self->SetMenuBar($menubar);
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +353,6 @@ sub is_loaded {
|
|||
# Selection of a 3D object changed on the platter.
|
||||
sub on_plater_selection_changed {
|
||||
my ($self, $have_selection) = @_;
|
||||
|
||||
return if !defined $self->{object_menu};
|
||||
$self->{object_menu}->Enable($_->GetId, $have_selection)
|
||||
for $self->{object_menu}->GetMenuItems;
|
||||
|
@ -337,20 +360,20 @@ sub on_plater_selection_changed {
|
|||
|
||||
# To perform the "Quck Slice", "Quick Slice and Save As", "Repeat last Quick Slice" and "Slice to SVG".
|
||||
sub quick_slice {
|
||||
my $self = shift;
|
||||
my %params = @_;
|
||||
my ($self, %params) = @_;
|
||||
|
||||
my $progress_dialog;
|
||||
eval {
|
||||
# validate configuration
|
||||
my $config = $self->config;
|
||||
my $config = wxTheApp->{preset_bundle}->full_config();
|
||||
$config->validate;
|
||||
|
||||
# select input file
|
||||
my $input_file;
|
||||
my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || '';
|
||||
if (!$params{reslice}) {
|
||||
my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/PRUSA):', $dir, "", &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/PRUSA):',
|
||||
wxTheApp->{app_config}->get_last_dir, "",
|
||||
&Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if ($dialog->ShowModal != wxID_OK) {
|
||||
$dialog->Destroy;
|
||||
return;
|
||||
|
@ -372,8 +395,7 @@ sub quick_slice {
|
|||
$input_file = $qs_last_input_file;
|
||||
}
|
||||
my $input_file_basename = basename($input_file);
|
||||
$Slic3r::GUI::Settings->{recent}{skein_directory} = dirname($input_file);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_skein_dir(dirname($input_file));
|
||||
|
||||
my $print_center;
|
||||
{
|
||||
|
@ -395,20 +417,19 @@ sub quick_slice {
|
|||
$sprint->apply_config($config);
|
||||
$sprint->set_model($model);
|
||||
|
||||
{
|
||||
my $extra = $self->extra_variables;
|
||||
$sprint->placeholder_parser->set($_, $extra->{$_}) for keys %$extra;
|
||||
}
|
||||
|
||||
# Copy the names of active presets into the placeholder parser.
|
||||
wxTheApp->{preset_bundle}->export_selections_pp($sprint->placeholder_parser);
|
||||
|
||||
# select output file
|
||||
my $output_file;
|
||||
if ($params{reslice}) {
|
||||
$output_file = $qs_last_output_file if defined $qs_last_output_file;
|
||||
} elsif ($params{save_as}) {
|
||||
# The following line may die if the output_filename_format template substitution fails.
|
||||
$output_file = $sprint->output_filepath;
|
||||
$output_file =~ s/\.[gG][cC][oO][dD][eE]$/.svg/ if $params{export_svg};
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save ' . ($params{export_svg} ? 'SVG' : 'G-code') . ' file as:',
|
||||
wxTheApp->output_path(dirname($output_file)),
|
||||
wxTheApp->{app_config}->get_last_output_dir(dirname($output_file)),
|
||||
basename($output_file), $params{export_svg} ? &Slic3r::GUI::FILE_WILDCARDS->{svg} : &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if ($dlg->ShowModal != wxID_OK) {
|
||||
$dlg->Destroy;
|
||||
|
@ -416,8 +437,7 @@ sub quick_slice {
|
|||
}
|
||||
$output_file = $dlg->GetPath;
|
||||
$qs_last_output_file = $output_file unless $params{export_svg};
|
||||
$Slic3r::GUI::Settings->{_}{last_output_path} = dirname($output_file);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_last_output_dir(dirname($output_file));
|
||||
$dlg->Destroy;
|
||||
}
|
||||
|
||||
|
@ -452,9 +472,7 @@ sub quick_slice {
|
|||
|
||||
sub reslice_now {
|
||||
my ($self) = @_;
|
||||
if ($self->{plater}) {
|
||||
$self->{plater}->reslice;
|
||||
}
|
||||
$self->{plater}->reslice if $self->{plater};
|
||||
}
|
||||
|
||||
sub repair_stl {
|
||||
|
@ -462,8 +480,9 @@ sub repair_stl {
|
|||
|
||||
my $input_file;
|
||||
{
|
||||
my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || '';
|
||||
my $dialog = Wx::FileDialog->new($self, 'Select the STL file to repair:', $dir, "", &Slic3r::GUI::FILE_WILDCARDS->{stl}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
my $dialog = Wx::FileDialog->new($self, 'Select the STL file to repair:',
|
||||
wxTheApp->{app_config}->get_last_dir, "",
|
||||
&Slic3r::GUI::FILE_WILDCARDS->{stl}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if ($dialog->ShowModal != wxID_OK) {
|
||||
$dialog->Destroy;
|
||||
return;
|
||||
|
@ -492,36 +511,25 @@ sub repair_stl {
|
|||
Slic3r::GUI::show_info($self, "Your file was repaired.", "Repair");
|
||||
}
|
||||
|
||||
sub extra_variables {
|
||||
my $self = shift;
|
||||
my %extra_variables = ();
|
||||
$extra_variables{"${_}_preset"} = $self->{options_tabs}{$_}->get_current_preset->name
|
||||
for qw(print filament printer);
|
||||
return { %extra_variables };
|
||||
}
|
||||
|
||||
sub export_config {
|
||||
my $self = shift;
|
||||
|
||||
my $config = $self->config;
|
||||
eval {
|
||||
# validate configuration
|
||||
$config->validate;
|
||||
};
|
||||
# Generate a cummulative configuration for the selected print, filaments and printer.
|
||||
my $config = wxTheApp->{preset_bundle}->full_config();
|
||||
# Validate the cummulative configuration.
|
||||
eval { $config->validate; };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
|
||||
my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
|
||||
my $filename = $last_config ? basename($last_config) : "config.ini";
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save configuration as:', $dir, $filename,
|
||||
# Ask user for the file name for the config file.
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save configuration as:',
|
||||
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
|
||||
$last_config ? basename($last_config) : "config.ini",
|
||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if ($dlg->ShowModal == wxID_OK) {
|
||||
my $file = $dlg->GetPath;
|
||||
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
||||
wxTheApp->save_settings;
|
||||
my $file = ($dlg->ShowModal == wxID_OK) ? $dlg->GetPath : undef;
|
||||
$dlg->Destroy;
|
||||
if (defined $file) {
|
||||
wxTheApp->{app_config}->update_config_dir(dirname($file));
|
||||
$last_config = $file;
|
||||
$config->save($file);
|
||||
}
|
||||
$dlg->Destroy;
|
||||
}
|
||||
|
||||
# Load a config file containing a Print, Filament & Printer preset.
|
||||
|
@ -529,222 +537,139 @@ sub load_config_file {
|
|||
my ($self, $file) = @_;
|
||||
if (!$file) {
|
||||
return unless $self->check_unsaved_changes;
|
||||
my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
|
||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini",
|
||||
'INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g', wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:',
|
||||
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
|
||||
"config.ini",
|
||||
'INI files (*.ini, *.gcode)|*.ini;*.INI;*.gcode;*.g', wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
return unless $dlg->ShowModal == wxID_OK;
|
||||
$file = $dlg->GetPaths;
|
||||
$dlg->Destroy;
|
||||
}
|
||||
for my $tab (values %{$self->{options_tabs}}) {
|
||||
# Dont proceed further if the config file cannot be loaded.
|
||||
return undef if ! $tab->load_config_file($file);
|
||||
}
|
||||
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
||||
wxTheApp->save_settings;
|
||||
eval { wxTheApp->{preset_bundle}->load_config_file($file); };
|
||||
# Dont proceed further if the config file cannot be loaded.
|
||||
return if Slic3r::GUI::catch_error($self);
|
||||
$_->load_current_preset for (values %{$self->{options_tabs}});
|
||||
wxTheApp->{app_config}->update_config_dir(dirname($file));
|
||||
$last_config = $file;
|
||||
}
|
||||
|
||||
sub export_configbundle {
|
||||
my $self = shift;
|
||||
|
||||
eval {
|
||||
# validate current configuration in case it's dirty
|
||||
$self->config->validate;
|
||||
};
|
||||
my ($self) = @_;
|
||||
return unless $self->check_unsaved_changes;
|
||||
# validate current configuration in case it's dirty
|
||||
eval { wxTheApp->{preset_bundle}->full_config->validate; };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
|
||||
my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
|
||||
my $filename = "Slic3r_config_bundle.ini";
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:', $dir, $filename,
|
||||
# Ask user for a file name.
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save presets bundle as:',
|
||||
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
|
||||
"Slic3r_config_bundle.ini",
|
||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if ($dlg->ShowModal == wxID_OK) {
|
||||
my $file = $dlg->GetPath;
|
||||
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
||||
wxTheApp->save_settings;
|
||||
|
||||
# leave default category empty to prevent the bundle from being parsed as a normal config file
|
||||
my $ini = { _ => {} };
|
||||
$ini->{settings}{$_} = $Slic3r::GUI::Settings->{_}{$_} for qw(autocenter);
|
||||
$ini->{presets} = $Slic3r::GUI::Settings->{presets};
|
||||
|
||||
foreach my $section (qw(print filament printer)) {
|
||||
my %presets = wxTheApp->presets($section);
|
||||
foreach my $preset_name (keys %presets) {
|
||||
my $config = Slic3r::Config->load($presets{$preset_name});
|
||||
$ini->{"$section:$preset_name"} = $config->as_ini->{_};
|
||||
}
|
||||
}
|
||||
|
||||
Slic3r::Config->write_ini($file, $ini);
|
||||
}
|
||||
my $file = ($dlg->ShowModal == wxID_OK) ? $dlg->GetPath : undef;
|
||||
$dlg->Destroy;
|
||||
if (defined $file) {
|
||||
# Export the config bundle.
|
||||
wxTheApp->{app_config}->update_config_dir(dirname($file));
|
||||
eval { wxTheApp->{preset_bundle}->export_configbundle($file); };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
}
|
||||
}
|
||||
|
||||
# Loading a config bundle with an external file name used to be used
|
||||
# to auto-install a config bundle on a fresh user account,
|
||||
# but that behavior was not documented and likely buggy.
|
||||
sub load_configbundle {
|
||||
my ($self, $file, $skip_no_id) = @_;
|
||||
|
||||
my ($self, $file) = @_;
|
||||
return unless $self->check_unsaved_changes;
|
||||
if (!$file) {
|
||||
my $dir = $last_config ? dirname($last_config) : $Slic3r::GUI::Settings->{recent}{config_directory} || $Slic3r::GUI::Settings->{recent}{skein_directory} || '';
|
||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:', $dir, "config.ini",
|
||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
my $dlg = Wx::FileDialog->new($self, 'Select configuration to load:',
|
||||
$last_config ? dirname($last_config) : wxTheApp->{app_config}->get_last_dir,
|
||||
"config.ini",
|
||||
&Slic3r::GUI::FILE_WILDCARDS->{ini}, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
return unless $dlg->ShowModal == wxID_OK;
|
||||
$file = $dlg->GetPaths;
|
||||
$dlg->Destroy;
|
||||
}
|
||||
|
||||
$Slic3r::GUI::Settings->{recent}{config_directory} = dirname($file);
|
||||
wxTheApp->save_settings;
|
||||
|
||||
# load .ini file
|
||||
my $ini = Slic3r::Config->read_ini($file);
|
||||
|
||||
if ($ini->{settings}) {
|
||||
$Slic3r::GUI::Settings->{_}{$_} = $ini->{settings}{$_} for keys %{$ini->{settings}};
|
||||
wxTheApp->save_settings;
|
||||
}
|
||||
if ($ini->{presets}) {
|
||||
$Slic3r::GUI::Settings->{presets} = $ini->{presets};
|
||||
wxTheApp->save_settings;
|
||||
}
|
||||
wxTheApp->{app_config}->update_config_dir(dirname($file));
|
||||
|
||||
my $imported = 0;
|
||||
INI_BLOCK: foreach my $ini_category (sort keys %$ini) {
|
||||
next unless $ini_category =~ /^(print|filament|printer):(.+)$/;
|
||||
my ($section, $preset_name) = ($1, $2);
|
||||
my $config = Slic3r::Config->load_ini_hash($ini->{$ini_category});
|
||||
next if $skip_no_id && !$config->get($section . "_settings_id");
|
||||
|
||||
{
|
||||
my %current_presets = Slic3r::GUI->presets($section);
|
||||
my %current_ids = map { $_ => 1 }
|
||||
grep $_,
|
||||
map Slic3r::Config->load($_)->get($section . "_settings_id"),
|
||||
values %current_presets;
|
||||
next INI_BLOCK if exists $current_ids{$config->get($section . "_settings_id")};
|
||||
}
|
||||
|
||||
$config->save(sprintf "$Slic3r::GUI::datadir/%s/%s.ini", $section, $preset_name);
|
||||
Slic3r::debugf "Imported %s preset %s\n", $section, $preset_name;
|
||||
$imported++;
|
||||
}
|
||||
my $presets_imported = 0;
|
||||
eval { $presets_imported = wxTheApp->{preset_bundle}->load_configbundle($file); };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
|
||||
# Load the currently selected preset into the GUI, update the preset selection box.
|
||||
foreach my $tab (values %{$self->{options_tabs}}) {
|
||||
$tab->load_presets;
|
||||
$tab->load_current_preset;
|
||||
}
|
||||
|
||||
return if !$imported;
|
||||
|
||||
my $message = sprintf "%d presets successfully imported.", $imported;
|
||||
my $message = sprintf "%d presets successfully imported.", $presets_imported;
|
||||
Slic3r::GUI::show_info($self, $message);
|
||||
}
|
||||
|
||||
# Load a provied DynamicConfig into the Print / Filament / Printer tabs, thus modifying the active preset.
|
||||
# Also update the platter with the new presets.
|
||||
sub load_config {
|
||||
my $self = shift;
|
||||
my ($config) = @_;
|
||||
|
||||
foreach my $tab (values %{$self->{options_tabs}}) {
|
||||
$tab->load_config($config);
|
||||
}
|
||||
if ($self->{plater}) {
|
||||
$self->{plater}->on_config_change($config);
|
||||
}
|
||||
my ($self, $config) = @_;
|
||||
$_->load_config($config) foreach values %{$self->{options_tabs}};
|
||||
$self->{plater}->on_config_change($config) if $self->{plater};
|
||||
}
|
||||
|
||||
sub config_wizard {
|
||||
my $self = shift;
|
||||
|
||||
return unless $self->check_unsaved_changes;
|
||||
if (my $config = Slic3r::GUI::ConfigWizard->new($self)->run) {
|
||||
for my $tab (values %{$self->{options_tabs}}) {
|
||||
$tab->select_default_preset;
|
||||
}
|
||||
$self->load_config($config);
|
||||
for my $tab (values %{$self->{options_tabs}}) {
|
||||
$tab->save_preset('My Settings');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
=head2 config
|
||||
|
||||
This method collects all config values from the tabs and merges them into a single config object.
|
||||
|
||||
=cut
|
||||
|
||||
sub config {
|
||||
my $self = shift;
|
||||
|
||||
return Slic3r::Config->new_from_defaults
|
||||
if !exists $self->{options_tabs}{print}
|
||||
|| !exists $self->{options_tabs}{filament}
|
||||
|| !exists $self->{options_tabs}{printer};
|
||||
|
||||
# retrieve filament presets and build a single config object for them
|
||||
my $filament_config;
|
||||
if (!$self->{plater} || $self->{plater}->filament_presets == 1) {
|
||||
$filament_config = $self->{options_tabs}{filament}->config;
|
||||
} else {
|
||||
my $i = -1;
|
||||
foreach my $preset_idx ($self->{plater}->filament_presets) {
|
||||
$i++;
|
||||
my $config;
|
||||
if ($preset_idx == $self->{options_tabs}{filament}->current_preset) {
|
||||
# the selected preset for this extruder is the one in the tab
|
||||
# use the tab's config instead of the preset in case it is dirty
|
||||
# perhaps plater shouldn't expose dirty presets at all in multi-extruder environments.
|
||||
$config = $self->{options_tabs}{filament}->config;
|
||||
} else {
|
||||
my $preset = $self->{options_tabs}{filament}->get_preset($preset_idx);
|
||||
$config = $self->{options_tabs}{filament}->get_preset_config($preset);
|
||||
}
|
||||
if (!$filament_config) {
|
||||
$filament_config = $config->clone;
|
||||
next;
|
||||
}
|
||||
foreach my $opt_key (@{$config->get_keys}) {
|
||||
my $value = $filament_config->get($opt_key);
|
||||
next unless ref $value eq 'ARRAY';
|
||||
$value->[$i] = $config->get($opt_key)->[0];
|
||||
$filament_config->set($opt_key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $config = Slic3r::Config->merge(
|
||||
Slic3r::Config->new_from_defaults,
|
||||
$self->{options_tabs}{print}->config,
|
||||
$self->{options_tabs}{printer}->config,
|
||||
$filament_config,
|
||||
);
|
||||
|
||||
my $extruders_count = $self->{options_tabs}{printer}{extruders_count};
|
||||
$config->set("${_}_extruder", min($config->get("${_}_extruder"), $extruders_count))
|
||||
for qw(perimeter infill solid_infill support_material support_material_interface);
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
sub filament_preset_names {
|
||||
my ($self) = @_;
|
||||
return map $self->{options_tabs}{filament}->get_preset($_)->name,
|
||||
$self->{plater}->filament_presets;
|
||||
# Exit wizard if there are unsaved changes and the user cancels the action.
|
||||
return unless $self->check_unsaved_changes;
|
||||
# Enumerate the profiles bundled with the Slic3r installation under resources/profiles.
|
||||
my $directory = Slic3r::resources_dir() . "/profiles";
|
||||
my @profiles = ();
|
||||
if (opendir(DIR, Slic3r::encode_path($directory))) {
|
||||
while (my $file = readdir(DIR)) {
|
||||
if ($file =~ /\.ini$/) {
|
||||
$file =~ s/\.ini$//;
|
||||
push @profiles, Slic3r::decode_path($file);
|
||||
}
|
||||
}
|
||||
closedir(DIR);
|
||||
}
|
||||
# Open the wizard.
|
||||
if (my $config = Slic3r::GUI::ConfigWizard->new($self, \@profiles)->run) {
|
||||
if (ref($config)) {
|
||||
# Wizard returned a config. Add the config to each of the preset types.
|
||||
for my $tab (values %{$self->{options_tabs}}) {
|
||||
# Select the first visible preset, force.
|
||||
$tab->select_preset(undef, 1);
|
||||
}
|
||||
# Load the config over the previously selected defaults.
|
||||
$self->load_config($config);
|
||||
for my $tab (values %{$self->{options_tabs}}) {
|
||||
# Save the settings under a new name, select the name.
|
||||
$tab->save_preset('My Settings');
|
||||
}
|
||||
} else {
|
||||
# Wizard returned a name of a preset bundle bundled with the installation. Unpack it.
|
||||
eval { wxTheApp->{preset_bundle}->load_configbundle($directory . '/' . $config . '.ini'); };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
# Load the currently selected preset into the GUI, update the preset selection box.
|
||||
foreach my $tab (values %{$self->{options_tabs}}) {
|
||||
$tab->load_current_preset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# This is called when closing the application, when loading a config file or when starting the config wizard
|
||||
# to notify the user whether he is aware that some preset changes will be lost.
|
||||
sub check_unsaved_changes {
|
||||
my $self = shift;
|
||||
|
||||
my @dirty = ();
|
||||
foreach my $tab (values %{$self->{options_tabs}}) {
|
||||
push @dirty, $tab->title if $tab->is_dirty;
|
||||
push @dirty, $tab->title if $tab->{presets}->current_is_dirty;
|
||||
}
|
||||
|
||||
if (@dirty) {
|
||||
my $titles = join ', ', @dirty;
|
||||
my $confirm = Wx::MessageDialog->new($self, "You have unsaved changes ($titles). Discard changes and continue anyway?",
|
||||
'Unsaved Presets', wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT);
|
||||
return ($confirm->ShowModal == wxID_YES);
|
||||
return $confirm->ShowModal == wxID_YES;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -765,21 +690,18 @@ sub select_view {
|
|||
|
||||
sub _append_menu_item {
|
||||
my ($self, $menu, $string, $description, $cb, $id, $icon) = @_;
|
||||
|
||||
$id //= &Wx::NewId();
|
||||
my $item = $menu->Append($id, $string, $description);
|
||||
$self->_set_menu_item_icon($item, $icon);
|
||||
|
||||
EVT_MENU($self, $id, $cb);
|
||||
return $item;
|
||||
}
|
||||
|
||||
sub _set_menu_item_icon {
|
||||
my ($self, $menuItem, $icon) = @_;
|
||||
|
||||
# SetBitmap was not available on OS X before Wx 0.9927
|
||||
if ($icon && $menuItem->can('SetBitmap')) {
|
||||
$menuItem->SetBitmap(Wx::Bitmap->new($Slic3r::var->($icon), wxBITMAP_TYPE_PNG));
|
||||
$menuItem->SetBitmap(Wx::Bitmap->new(Slic3r::var($icon), wxBITMAP_TYPE_PNG));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -787,8 +709,11 @@ sub _set_menu_item_icon {
|
|||
# Update the UI based on the current preferences.
|
||||
sub update_ui_from_settings {
|
||||
my ($self) = @_;
|
||||
$self->{menu_item_reslice_now}->Enable(! $Slic3r::GUI::Settings->{_}{background_processing});
|
||||
$self->{menu_item_reslice_now}->Enable(! wxTheApp->{app_config}->get("background_processing"));
|
||||
$self->{plater}->update_ui_from_settings if ($self->{plater});
|
||||
for my $tab_name (qw(print filament printer)) {
|
||||
$self->{options_tabs}{$tab_name}->update_ui_from_settings;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -6,7 +6,7 @@ use Moo;
|
|||
|
||||
has 'growler' => (is => 'rw');
|
||||
|
||||
my $icon = $Slic3r::var->("Slic3r.png");
|
||||
my $icon = Slic3r::var("Slic3r.png");
|
||||
|
||||
sub BUILD {
|
||||
my ($self) = @_;
|
||||
|
|
|
@ -124,6 +124,10 @@ sub BUILD {
|
|||
});
|
||||
}
|
||||
|
||||
sub get_value {
|
||||
my ($self) = @_;
|
||||
return $self->wxWindow->GetValue ? 1 : 0;
|
||||
}
|
||||
|
||||
package Slic3r::GUI::OptionsGroup::Field::SpinCtrl;
|
||||
use Moo;
|
||||
|
|
|
@ -46,15 +46,14 @@ use constant PROCESS_DELAY => 0.5 * 1000; # milliseconds
|
|||
my $PreventListEvents = 0;
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my ($parent) = @_;
|
||||
my ($class, $parent) = @_;
|
||||
my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
$self->{config} = Slic3r::Config->new_from_defaults(qw(
|
||||
$self->{config} = Slic3r::Config::new_from_defaults_keys([qw(
|
||||
bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width variable_layer_height
|
||||
serial_port serial_speed octoprint_host octoprint_apikey
|
||||
nozzle_diameter single_extruder_multi_material
|
||||
wipe_tower wipe_tower_x wipe_tower_y wipe_tower_width wipe_tower_per_color_wipe extruder_colour filament_colour
|
||||
));
|
||||
)]);
|
||||
# C++ Slic3r::Model with Perl extensions in Slic3r/Model.pm
|
||||
$self->{model} = Slic3r::Model->new;
|
||||
# C++ Slic3r::Print with Perl extensions in Slic3r/Print.pm
|
||||
|
@ -64,12 +63,7 @@ sub new {
|
|||
|
||||
$self->{print}->set_status_cb(sub {
|
||||
my ($percent, $message) = @_;
|
||||
|
||||
if ($Slic3r::have_threads) {
|
||||
Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $PROGRESS_BAR_EVENT, shared_clone([$percent, $message])));
|
||||
} else {
|
||||
$self->on_progress_event($percent, $message);
|
||||
}
|
||||
Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $PROGRESS_BAR_EVENT, shared_clone([$percent, $message])));
|
||||
});
|
||||
|
||||
# Initialize preview notebook
|
||||
|
@ -105,6 +99,7 @@ sub new {
|
|||
$self->{canvas3D}->set_on_select_object($on_select_object);
|
||||
$self->{canvas3D}->set_on_double_click($on_double_click);
|
||||
$self->{canvas3D}->set_on_right_click(sub { $on_right_click->($self->{canvas3D}, @_); });
|
||||
$self->{canvas3D}->set_on_arrange(sub { $self->arrange });
|
||||
$self->{canvas3D}->set_on_rotate_object_left(sub { $self->rotate(-45, Z, 'relative') });
|
||||
$self->{canvas3D}->set_on_rotate_object_right(sub { $self->rotate( 45, Z, 'relative') });
|
||||
$self->{canvas3D}->set_on_scale_object_uniformly(sub { $self->changescale(undef) });
|
||||
|
@ -120,7 +115,7 @@ sub new {
|
|||
$self->GetFrame->{options_tabs}{print}->load_config($cfg);
|
||||
});
|
||||
$self->{canvas3D}->set_on_model_update(sub {
|
||||
if ($Slic3r::GUI::Settings->{_}{background_processing}) {
|
||||
if (wxTheApp->{app_config}->get("background_processing")) {
|
||||
$self->schedule_background_process;
|
||||
} else {
|
||||
# Hide the print info box, it is no more valid.
|
||||
|
@ -166,22 +161,22 @@ sub new {
|
|||
if (!&Wx::wxMSW) {
|
||||
Wx::ToolTip::Enable(1);
|
||||
$self->{htoolbar} = Wx::ToolBar->new($self, -1, wxDefaultPosition, wxDefaultSize, wxTB_HORIZONTAL | wxTB_TEXT | wxBORDER_SIMPLE | wxTAB_TRAVERSAL);
|
||||
$self->{htoolbar}->AddTool(TB_ADD, "Add…", Wx::Bitmap->new($Slic3r::var->("brick_add.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_REMOVE, "Delete", Wx::Bitmap->new($Slic3r::var->("brick_delete.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_RESET, "Delete All", Wx::Bitmap->new($Slic3r::var->("cross.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_ARRANGE, "Arrange", Wx::Bitmap->new($Slic3r::var->("bricks.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_ADD, "Add…", Wx::Bitmap->new(Slic3r::var("brick_add.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_REMOVE, "Delete", Wx::Bitmap->new(Slic3r::var("brick_delete.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_RESET, "Delete All", Wx::Bitmap->new(Slic3r::var("cross.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_ARRANGE, "Arrange", Wx::Bitmap->new(Slic3r::var("bricks.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddSeparator;
|
||||
$self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new($Slic3r::var->("add.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_FEWER, "Fewer", Wx::Bitmap->new($Slic3r::var->("delete.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_MORE, "More", Wx::Bitmap->new(Slic3r::var("add.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_FEWER, "Fewer", Wx::Bitmap->new(Slic3r::var("delete.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddSeparator;
|
||||
$self->{htoolbar}->AddTool(TB_45CCW, "45° ccw", Wx::Bitmap->new($Slic3r::var->("arrow_rotate_anticlockwise.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_45CW, "45° cw", Wx::Bitmap->new($Slic3r::var->("arrow_rotate_clockwise.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_SCALE, "Scale…", Wx::Bitmap->new($Slic3r::var->("arrow_out.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_SPLIT, "Split", Wx::Bitmap->new($Slic3r::var->("shape_ungroup.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_CUT, "Cut…", Wx::Bitmap->new($Slic3r::var->("package.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_45CCW, "45° ccw", Wx::Bitmap->new(Slic3r::var("arrow_rotate_anticlockwise.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_45CW, "45° cw", Wx::Bitmap->new(Slic3r::var("arrow_rotate_clockwise.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_SCALE, "Scale…", Wx::Bitmap->new(Slic3r::var("arrow_out.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_SPLIT, "Split", Wx::Bitmap->new(Slic3r::var("shape_ungroup.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_CUT, "Cut…", Wx::Bitmap->new(Slic3r::var("package.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddSeparator;
|
||||
$self->{htoolbar}->AddTool(TB_SETTINGS, "Settings…", Wx::Bitmap->new($Slic3r::var->("cog.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_LAYER_EDITING, 'Layer Editing', Wx::Bitmap->new($Slic3r::var->("variable_layer_height.png"), wxBITMAP_TYPE_PNG), wxNullBitmap, 1, 0, 'Layer Editing');
|
||||
$self->{htoolbar}->AddTool(TB_SETTINGS, "Settings…", Wx::Bitmap->new(Slic3r::var("cog.png"), wxBITMAP_TYPE_PNG), '');
|
||||
$self->{htoolbar}->AddTool(TB_LAYER_EDITING, 'Layer Editing', Wx::Bitmap->new(Slic3r::var("variable_layer_height.png"), wxBITMAP_TYPE_PNG), wxNullBitmap, 1, 0, 'Layer Editing');
|
||||
} else {
|
||||
my %tbar_buttons = (
|
||||
add => "Add…",
|
||||
|
@ -256,7 +251,7 @@ sub new {
|
|||
settings cog.png
|
||||
);
|
||||
for (grep $self->{"btn_$_"}, keys %icons) {
|
||||
$self->{"btn_$_"}->SetBitmap(Wx::Bitmap->new($Slic3r::var->($icons{$_}), wxBITMAP_TYPE_PNG));
|
||||
$self->{"btn_$_"}->SetBitmap(Wx::Bitmap->new(Slic3r::var($icons{$_}), wxBITMAP_TYPE_PNG));
|
||||
}
|
||||
$self->selection_changed(0);
|
||||
$self->object_list_changed;
|
||||
|
@ -331,7 +326,7 @@ sub new {
|
|||
$self->on_process_completed($event->GetData);
|
||||
});
|
||||
|
||||
if ($Slic3r::have_threads) {
|
||||
{
|
||||
my $timer_id = Wx::NewId();
|
||||
$self->{apply_config_timer} = Wx::Timer->new($self, $timer_id);
|
||||
EVT_TIMER($self, $timer_id, sub {
|
||||
|
@ -366,20 +361,17 @@ sub new {
|
|||
# once a printer preset with multiple extruders is activated.
|
||||
# $self->{preset_choosers}{$group}[$idx]
|
||||
$self->{preset_choosers} = {};
|
||||
# Boolean indicating whether the '- default -' preset is shown by the combo box.
|
||||
$self->{preset_choosers_default_suppressed} = {};
|
||||
for my $group (qw(print filament printer)) {
|
||||
my $text = Wx::StaticText->new($self, -1, "$group_labels{$group}:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
|
||||
$text->SetFont($Slic3r::GUI::small_font);
|
||||
my $choice = Wx::BitmapComboBox->new($self, -1, "", wxDefaultPosition, wxDefaultSize, [], wxCB_READONLY);
|
||||
EVT_LEFT_DOWN($choice, sub { $self->filament_color_box_lmouse_down(0, @_); } );
|
||||
$self->{preset_choosers}{$group} = [$choice];
|
||||
$self->{preset_choosers_default_suppressed}{$group} = 0;
|
||||
# setup the listener
|
||||
EVT_COMBOBOX($choice, $choice, sub {
|
||||
my ($choice) = @_;
|
||||
wxTheApp->CallAfter(sub {
|
||||
$self->_on_select_preset($group, $choice);
|
||||
$self->_on_select_preset($group, $choice, 0);
|
||||
});
|
||||
});
|
||||
$presets->Add($text, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4);
|
||||
|
@ -414,7 +406,7 @@ sub new {
|
|||
$self->{"object_info_$field"} = Wx::StaticText->new($self, -1, "", wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
||||
$self->{"object_info_$field"}->SetFont($Slic3r::GUI::small_font);
|
||||
if ($field eq 'manifold') {
|
||||
$self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($self, -1, Wx::Bitmap->new($Slic3r::var->("error.png"), wxBITMAP_TYPE_PNG));
|
||||
$self->{object_info_manifold_warning_icon} = Wx::StaticBitmap->new($self, -1, Wx::Bitmap->new(Slic3r::var("error.png"), wxBITMAP_TYPE_PNG));
|
||||
$self->{object_info_manifold_warning_icon}->Hide;
|
||||
|
||||
my $h_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
|
@ -438,6 +430,7 @@ sub new {
|
|||
$grid_sizer->AddGrowableCol(3, 1);
|
||||
$print_info_sizer->Add($grid_sizer, 0, wxEXPAND);
|
||||
my @info = (
|
||||
fil_m => "Used Filament (m)",
|
||||
fil_mm3 => "Used Filament (mm^3)",
|
||||
fil_g => "Used Filament (g)",
|
||||
cost => "Cost",
|
||||
|
@ -453,7 +446,6 @@ sub new {
|
|||
$self->{"print_info_$field"}->SetFont($Slic3r::GUI::small_font);
|
||||
$grid_sizer->Add($self->{"print_info_$field"}, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
my $buttons_sizer = Wx::BoxSizer->new(wxHORIZONTAL);
|
||||
|
@ -505,30 +497,26 @@ sub on_select_preset {
|
|||
$self->{on_select_preset} = $cb;
|
||||
}
|
||||
|
||||
# Called from the platter combo boxes selecting the active print, filament or printer.
|
||||
sub _on_select_preset {
|
||||
my $self = shift;
|
||||
my ($group, $choice) = @_;
|
||||
|
||||
my ($self, $group, $choice, $idx) = @_;
|
||||
# If user changed a filament preset and the selected machine is equipped with multiple extruders,
|
||||
# there are multiple filament selection combo boxes shown at the platter. In that case
|
||||
# don't propagate the filament selection changes to the tab.
|
||||
my $default_suppressed = $self->{preset_choosers_default_suppressed}{$group};
|
||||
if ($group eq 'filament') {
|
||||
wxTheApp->{preset_bundle}->set_filament_preset($idx, $choice->GetStringSelection);
|
||||
}
|
||||
if ($group eq 'filament' && @{$self->{preset_choosers}{filament}} > 1) {
|
||||
# Indices of the filaments selected.
|
||||
my @filament_presets = $self->filament_presets;
|
||||
$Slic3r::GUI::Settings->{presets}{filament} = $choice->GetString($filament_presets[0] - $default_suppressed) . ".ini";
|
||||
$Slic3r::GUI::Settings->{presets}{"filament_${_}"} = $choice->GetString($filament_presets[$_] - $default_suppressed)
|
||||
for 1 .. $#filament_presets;
|
||||
wxTheApp->save_settings;
|
||||
$self->update_filament_colors_preview($choice);
|
||||
wxTheApp->{preset_bundle}->update_platter_filament_ui($idx, $choice);
|
||||
} else {
|
||||
# call GetSelection() in scalar context as it's context-aware
|
||||
$self->{on_select_preset}->($group, scalar($choice->GetSelection) + $default_suppressed)
|
||||
$self->{on_select_preset}->($group, $choice->GetStringSelection)
|
||||
if $self->{on_select_preset};
|
||||
}
|
||||
|
||||
# Synchronize config.ini with the current selections.
|
||||
wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config});
|
||||
# get new config and generate on_config_change() event for updating plater and other things
|
||||
$self->on_config_change($self->GetFrame->config);
|
||||
$self->on_config_change(wxTheApp->{preset_bundle}->full_config);
|
||||
}
|
||||
|
||||
sub on_layer_editing_toggled {
|
||||
|
@ -558,8 +546,8 @@ sub GetFrame {
|
|||
sub update_ui_from_settings
|
||||
{
|
||||
my ($self) = @_;
|
||||
if (defined($self->{btn_reslice}) && $self->{buttons_sizer}->IsShown($self->{btn_reslice}) != (! $Slic3r::GUI::Settings->{_}{background_processing})) {
|
||||
$self->{buttons_sizer}->Show($self->{btn_reslice}, ! $Slic3r::GUI::Settings->{_}{background_processing});
|
||||
if (defined($self->{btn_reslice}) && $self->{buttons_sizer}->IsShown($self->{btn_reslice}) != (! wxTheApp->{app_config}->get("background_processing"))) {
|
||||
$self->{buttons_sizer}->Show($self->{btn_reslice}, ! wxTheApp->{app_config}->get("background_processing"));
|
||||
$self->{buttons_sizer}->Layout;
|
||||
}
|
||||
}
|
||||
|
@ -573,128 +561,41 @@ sub update_ui_from_settings
|
|||
# For Print settings and Printer, synchronize the selection index with their tabs.
|
||||
# For Filament, synchronize the selection index for a single extruder printer only, otherwise keep the selection.
|
||||
sub update_presets {
|
||||
my $self = shift;
|
||||
# $presets: one of qw(print filament printer)
|
||||
# $selected: index of the selected preset in the array. This may not correspond
|
||||
# with the index of selection in the UI element, where not all items are displayed.
|
||||
my ($group, $presets, $default_suppressed, $selected, $is_dirty) = @_;
|
||||
|
||||
my @choosers = @{ $self->{preset_choosers}{$group} };
|
||||
my $choice_idx = 0;
|
||||
foreach my $choice (@choosers) {
|
||||
if ($group eq 'filament' && @choosers > 1) {
|
||||
# if we have more than one filament chooser, keep our selection
|
||||
# instead of importing the one from the tab
|
||||
$selected = $choice->GetSelection + $self->{preset_choosers_default_suppressed}{$group};
|
||||
$is_dirty = 0;
|
||||
# $group: one of qw(print filament printer)
|
||||
# $presets: PresetCollection
|
||||
my ($self, $group, $presets) = @_;
|
||||
my @choosers = @{$self->{preset_choosers}{$group}};
|
||||
if ($group eq 'filament') {
|
||||
my $choice_idx = 0;
|
||||
if (int(@choosers) == 1) {
|
||||
# Single filament printer, synchronize the filament presets.
|
||||
wxTheApp->{preset_bundle}->set_filament_preset(0, wxTheApp->{preset_bundle}->filament->get_selected_preset->name);
|
||||
}
|
||||
$choice->Clear;
|
||||
foreach my $preset (@$presets) {
|
||||
next if ($preset->default && $default_suppressed);
|
||||
my $bitmap;
|
||||
if ($group eq 'filament') {
|
||||
$bitmap = Wx::Bitmap->new($Slic3r::var->("spool.png"), wxBITMAP_TYPE_PNG);
|
||||
} elsif ($group eq 'print') {
|
||||
$bitmap = Wx::Bitmap->new($Slic3r::var->("cog.png"), wxBITMAP_TYPE_PNG);
|
||||
} elsif ($group eq 'printer') {
|
||||
$bitmap = Wx::Bitmap->new($Slic3r::var->("printer_empty.png"), wxBITMAP_TYPE_PNG);
|
||||
}
|
||||
$choice->AppendString($preset->name, $bitmap);
|
||||
foreach my $choice (@choosers) {
|
||||
wxTheApp->{preset_bundle}->update_platter_filament_ui($choice_idx, $choice);
|
||||
$choice_idx += 1;
|
||||
}
|
||||
|
||||
if ($selected <= $#$presets) {
|
||||
my $idx = $selected - $default_suppressed;
|
||||
if ($idx >= 0) {
|
||||
if ($is_dirty) {
|
||||
$choice->SetString($idx, $choice->GetString($idx) . " (modified)");
|
||||
}
|
||||
# call SetSelection() only after SetString() otherwise the new string
|
||||
# won't be picked up as the visible string
|
||||
$choice->SetSelection($idx);
|
||||
}
|
||||
}
|
||||
$choice_idx += 1;
|
||||
}
|
||||
|
||||
$self->{preset_choosers_default_suppressed}{$group} = $default_suppressed;
|
||||
|
||||
wxTheApp->CallAfter(sub { $self->update_filament_colors_preview }) if $group eq 'filament' || $group eq 'printer';
|
||||
}
|
||||
|
||||
# Update the color icon in front of each filament selection on the platter.
|
||||
# If the extruder has a preview color assigned, apply the extruder color to the active selection.
|
||||
# Always apply the filament color to the non-active selections.
|
||||
sub update_filament_colors_preview {
|
||||
my ($self, $extruder_idx) = shift;
|
||||
|
||||
my @choosers = @{$self->{preset_choosers}{filament}};
|
||||
|
||||
if (ref $extruder_idx) {
|
||||
# $extruder_idx is the chooser.
|
||||
foreach my $chooser (@choosers) {
|
||||
if ($extruder_idx == $chooser) {
|
||||
$extruder_idx = $chooser;
|
||||
last;
|
||||
}
|
||||
} elsif ($group eq 'print') {
|
||||
wxTheApp->{preset_bundle}->print->update_platter_ui($choosers[0]);
|
||||
} elsif ($group eq 'printer') {
|
||||
# Update the print choosers to only contain the compatible presets, update the dirty flags.
|
||||
wxTheApp->{preset_bundle}->print->update_platter_ui($self->{preset_choosers}{print}->[0]);
|
||||
# Update the printer choosers, update the dirty flags.
|
||||
wxTheApp->{preset_bundle}->printer->update_platter_ui($choosers[0]);
|
||||
# Update the filament choosers to only contain the compatible presets, update the color preview,
|
||||
# update the dirty flags.
|
||||
my $choice_idx = 0;
|
||||
foreach my $choice (@{$self->{preset_choosers}{filament}}) {
|
||||
wxTheApp->{preset_bundle}->update_platter_filament_ui($choice_idx, $choice);
|
||||
$choice_idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
my @extruder_colors = @{$self->{config}->extruder_colour};
|
||||
|
||||
my @extruder_list;
|
||||
if (defined $extruder_idx) {
|
||||
@extruder_list = ($extruder_idx);
|
||||
} else {
|
||||
# Collect extruder indices.
|
||||
@extruder_list = (0..$#extruder_colors);
|
||||
}
|
||||
|
||||
my $filament_tab = $self->GetFrame->{options_tabs}{filament};
|
||||
my $presets = $filament_tab->{presets};
|
||||
my $default_suppressed = $filament_tab->{default_suppressed};
|
||||
|
||||
foreach my $extruder_idx (@extruder_list) {
|
||||
my $chooser = $choosers[$extruder_idx];
|
||||
my $extruder_color = $self->{config}->extruder_colour->[$extruder_idx];
|
||||
my $preset_idx = 0;
|
||||
my $selection_idx = $chooser->GetSelection;
|
||||
foreach my $preset (@$presets) {
|
||||
my $bitmap;
|
||||
if ($preset->default) {
|
||||
next if $default_suppressed;
|
||||
} else {
|
||||
# Assign an extruder color to the selected item if the extruder color is defined.
|
||||
my $filament_rgb = $preset->config(['filament_colour'])->filament_colour->[0];
|
||||
my $extruder_rgb = ($preset_idx == $selection_idx && $extruder_color =~ m/^#[[:xdigit:]]{6}/) ? $extruder_color : $filament_rgb;
|
||||
$filament_rgb =~ s/^#//;
|
||||
$extruder_rgb =~ s/^#//;
|
||||
my $image = Wx::Image->new(24,16);
|
||||
if ($filament_rgb ne $extruder_rgb) {
|
||||
my @rgb = unpack 'C*', pack 'H*', $extruder_rgb;
|
||||
$image->SetRGB(Wx::Rect->new(0,0,16,16), @rgb);
|
||||
@rgb = unpack 'C*', pack 'H*', $filament_rgb;
|
||||
$image->SetRGB(Wx::Rect->new(16,0,8,16), @rgb);
|
||||
} else {
|
||||
my @rgb = unpack 'C*', pack 'H*', $filament_rgb;
|
||||
$image->SetRGB(Wx::Rect->new(0,0,24,16), @rgb);
|
||||
}
|
||||
$bitmap = Wx::Bitmap->new($image);
|
||||
}
|
||||
$chooser->SetItemBitmap($preset_idx, $bitmap) if $bitmap;
|
||||
$preset_idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Return a vector of indices of filaments selected by the $self->{preset_choosers}{filament} combo boxes.
|
||||
sub filament_presets {
|
||||
my $self = shift;
|
||||
# force scalar context for GetSelection() as it's context-aware
|
||||
return map scalar($_->GetSelection) + $self->{preset_choosers_default_suppressed}{filament}, @{ $self->{preset_choosers}{filament} };
|
||||
# Synchronize config.ini with the current selections.
|
||||
wxTheApp->{preset_bundle}->export_selections(wxTheApp->{app_config});
|
||||
}
|
||||
|
||||
sub add {
|
||||
my $self = shift;
|
||||
my ($self) = @_;
|
||||
my @input_files = wxTheApp->open_model($self);
|
||||
$self->load_files(\@input_files);
|
||||
}
|
||||
|
@ -759,8 +660,7 @@ sub load_files {
|
|||
}
|
||||
|
||||
# Note the current directory for the file open dialog.
|
||||
$Slic3r::GUI::Settings->{recent}{skein_directory} = dirname($input_files->[-1]);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_skein_dir(dirname($input_files->[-1]));
|
||||
|
||||
$process_dialog->Destroy;
|
||||
$self->statusbar->SetStatusText("Loaded " . join(',', @loaded_files));
|
||||
|
@ -808,7 +708,7 @@ sub load_model_objects {
|
|||
}
|
||||
|
||||
# if user turned autocentering off, automatic arranging would disappoint them
|
||||
if (!$Slic3r::GUI::Settings->{_}{autocenter}) {
|
||||
if (! wxTheApp->{app_config}->get("autocenter")) {
|
||||
$need_arrange = 0;
|
||||
}
|
||||
|
||||
|
@ -921,7 +821,7 @@ sub increase {
|
|||
|
||||
# only autoarrange if user has autocentering enabled
|
||||
$self->stop_background_process;
|
||||
if ($Slic3r::GUI::Settings->{_}{autocenter}) {
|
||||
if (wxTheApp->{app_config}->get("autocenter")) {
|
||||
$self->arrange;
|
||||
} else {
|
||||
$self->update;
|
||||
|
@ -1164,7 +1064,7 @@ sub arrange {
|
|||
$self->pause_background_process;
|
||||
|
||||
my $bb = Slic3r::Geometry::BoundingBoxf->new_from_points($self->{config}->bed_shape);
|
||||
my $success = $self->{model}->arrange_objects($self->GetFrame->config->min_object_distance, $bb);
|
||||
my $success = $self->{model}->arrange_objects(wxTheApp->{preset_bundle}->full_config->min_object_distance, $bb);
|
||||
# ignore arrange failures on purpose: user has visual feedback and we don't need to warn him
|
||||
# when parts don't fit in print bed
|
||||
|
||||
|
@ -1225,7 +1125,7 @@ sub async_apply_config {
|
|||
$self->pause_background_process;
|
||||
|
||||
# apply new config
|
||||
my $invalidated = $self->{print}->apply_config($self->GetFrame->config);
|
||||
my $invalidated = $self->{print}->apply_config(wxTheApp->{preset_bundle}->full_config);
|
||||
|
||||
# Just redraw the 3D canvas without reloading the scene.
|
||||
# $self->{canvas3D}->Refresh if ($invalidated && $self->{canvas3D}->layer_editing_enabled);
|
||||
|
@ -1234,7 +1134,7 @@ sub async_apply_config {
|
|||
# Hide the slicing results if the current slicing status is no more valid.
|
||||
$self->{"print_info_box_show"}->(0) if $invalidated;
|
||||
|
||||
if ($Slic3r::GUI::Settings->{_}{background_processing}) {
|
||||
if (wxTheApp->{app_config}->get("background_processing")) {
|
||||
if ($invalidated) {
|
||||
# kill current thread if any
|
||||
$self->stop_background_process;
|
||||
|
@ -1256,7 +1156,6 @@ sub async_apply_config {
|
|||
sub start_background_process {
|
||||
my ($self) = @_;
|
||||
|
||||
return if !$Slic3r::have_threads;
|
||||
return if !@{$self->{objects}};
|
||||
return if $self->{process_thread};
|
||||
|
||||
|
@ -1267,7 +1166,7 @@ sub start_background_process {
|
|||
# don't start process thread if config is not valid
|
||||
eval {
|
||||
# this will throw errors if config is not valid
|
||||
$self->GetFrame->config->validate;
|
||||
wxTheApp->{preset_bundle}->full_config->validate;
|
||||
$self->{print}->validate;
|
||||
};
|
||||
if ($@) {
|
||||
|
@ -1275,11 +1174,8 @@ sub start_background_process {
|
|||
return;
|
||||
}
|
||||
|
||||
# apply extra variables
|
||||
{
|
||||
my $extra = $self->GetFrame->extra_variables;
|
||||
$self->{print}->placeholder_parser->set($_, $extra->{$_}) for keys %$extra;
|
||||
}
|
||||
# Copy the names of active presets into the placeholder parser.
|
||||
wxTheApp->{preset_bundle}->export_selections_pp($self->{print}->placeholder_parser);
|
||||
|
||||
# start thread
|
||||
@_ = ();
|
||||
|
@ -1350,7 +1246,7 @@ sub reslice {
|
|||
# explicitly cancel a previous thread and start a new one.
|
||||
my ($self) = @_;
|
||||
# Don't reslice if export of G-code or sending to OctoPrint is running.
|
||||
if ($Slic3r::have_threads && ! defined($self->{export_gcode_output_file}) && ! defined($self->{send_gcode_file})) {
|
||||
if (! defined($self->{export_gcode_output_file}) && ! defined($self->{send_gcode_file})) {
|
||||
# Stop the background processing threads, stop the async update timer.
|
||||
$self->stop_background_process;
|
||||
# Rather perform one additional unnecessary update of the print object instead of skipping a pending async update.
|
||||
|
@ -1379,66 +1275,57 @@ sub export_gcode {
|
|||
# (we assume that if it is running, config is valid)
|
||||
eval {
|
||||
# this will throw errors if config is not valid
|
||||
$self->GetFrame->config->validate;
|
||||
wxTheApp->{preset_bundle}->full_config->validate;
|
||||
$self->{print}->validate;
|
||||
};
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
|
||||
|
||||
# apply config and validate print
|
||||
my $config = $self->GetFrame->config;
|
||||
my $config = wxTheApp->{preset_bundle}->full_config;
|
||||
eval {
|
||||
# this will throw errors if config is not valid
|
||||
$config->validate;
|
||||
$self->{print}->apply_config($config);
|
||||
$self->{print}->validate;
|
||||
};
|
||||
if (!$Slic3r::have_threads) {
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
}
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
|
||||
# select output file
|
||||
if ($output_file) {
|
||||
$self->{export_gcode_output_file} = $self->{print}->output_filepath($output_file);
|
||||
$self->{export_gcode_output_file} = eval { $self->{print}->output_filepath($output_file) };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
} else {
|
||||
my $default_output_file = $self->{print}->output_filepath($main::opt{output} // '');
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:', wxTheApp->output_path(dirname($default_output_file)),
|
||||
my $default_output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') };
|
||||
Slic3r::GUI::catch_error($self) and return;
|
||||
my $dlg = Wx::FileDialog->new($self, 'Save G-code file as:',
|
||||
wxTheApp->{app_config}->get_last_output_dir(dirname($default_output_file)),
|
||||
basename($default_output_file), &Slic3r::GUI::FILE_WILDCARDS->{gcode}, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if ($dlg->ShowModal != wxID_OK) {
|
||||
$dlg->Destroy;
|
||||
return;
|
||||
}
|
||||
my $path = $dlg->GetPath;
|
||||
$Slic3r::GUI::Settings->{_}{last_output_path} = dirname($path);
|
||||
wxTheApp->save_settings;
|
||||
wxTheApp->{app_config}->update_last_output_dir(dirname($path));
|
||||
$self->{export_gcode_output_file} = $path;
|
||||
$dlg->Destroy;
|
||||
}
|
||||
|
||||
$self->statusbar->StartBusy;
|
||||
|
||||
if ($Slic3r::have_threads) {
|
||||
$self->statusbar->SetCancelCallback(sub {
|
||||
$self->stop_background_process;
|
||||
$self->statusbar->SetStatusText("Export cancelled");
|
||||
$self->{export_gcode_output_file} = undef;
|
||||
$self->{send_gcode_file} = undef;
|
||||
|
||||
# this updates buttons status
|
||||
$self->object_list_changed;
|
||||
});
|
||||
$self->statusbar->SetCancelCallback(sub {
|
||||
$self->stop_background_process;
|
||||
$self->statusbar->SetStatusText("Export cancelled");
|
||||
$self->{export_gcode_output_file} = undef;
|
||||
$self->{send_gcode_file} = undef;
|
||||
|
||||
# start background process, whose completion event handler
|
||||
# will detect $self->{export_gcode_output_file} and proceed with export
|
||||
$self->start_background_process;
|
||||
} else {
|
||||
eval {
|
||||
$self->{print}->process;
|
||||
$self->{print}->export_gcode(output_file => $self->{export_gcode_output_file});
|
||||
};
|
||||
my $result = !Slic3r::GUI::catch_error($self);
|
||||
$self->on_export_completed($result);
|
||||
}
|
||||
# this updates buttons status
|
||||
$self->object_list_changed;
|
||||
});
|
||||
|
||||
# start background process, whose completion event handler
|
||||
# will detect $self->{export_gcode_output_file} and proceed with export
|
||||
$self->start_background_process;
|
||||
|
||||
# this updates buttons status
|
||||
$self->object_list_changed;
|
||||
|
@ -1542,6 +1429,7 @@ sub on_export_completed {
|
|||
$self->{"print_info_fil_g"}->SetLabel(sprintf("%.2f" , $self->{print}->total_weight));
|
||||
$self->{"print_info_fil_mm3"}->SetLabel(sprintf("%.2f" , $self->{print}->total_extruded_volume));
|
||||
$self->{"print_info_time"}->SetLabel(sprintf("%.2f" , $self->{print}->estimated_print_time));
|
||||
$self->{"print_info_fil_m"}->SetLabel(sprintf("%.2f" , $self->{print}->total_used_filament / 1000));
|
||||
$self->{"print_info_box_show"}->(1);
|
||||
|
||||
# this updates buttons status
|
||||
|
@ -1551,14 +1439,12 @@ sub on_export_completed {
|
|||
sub do_print {
|
||||
my ($self) = @_;
|
||||
|
||||
my $printer_tab = $self->GetFrame->{options_tabs}{printer};
|
||||
my $printer_name = $printer_tab->get_current_preset->name;
|
||||
|
||||
my $controller = $self->GetFrame->{controller};
|
||||
my $printer_panel = $controller->add_printer($printer_name, $printer_tab->config);
|
||||
my $printer_preset = wxTheApp->{preset_bundle}->printer->get_edited_preset;
|
||||
my $printer_panel = $controller->add_printer($printer_preset->name, $printer_preset->config);
|
||||
|
||||
my $filament_stats = $self->{print}->filament_stats;
|
||||
my @filament_names = $self->GetFrame->filament_preset_names;
|
||||
my @filament_names = wxTheApp->{preset_bundle}->filament_presets;
|
||||
$filament_stats = { map { $filament_names[$_] => $filament_stats->{$_} } keys %$filament_stats };
|
||||
$printer_panel->load_print_job($self->{print_file}, $filament_stats);
|
||||
|
||||
|
@ -1599,11 +1485,11 @@ sub send_gcode {
|
|||
}
|
||||
|
||||
sub export_stl {
|
||||
my $self = shift;
|
||||
|
||||
my ($self) = @_;
|
||||
return if !@{$self->{objects}};
|
||||
|
||||
# Ask user for a file name to write into.
|
||||
my $output_file = $self->_get_export_file('STL') or return;
|
||||
# Store a binary STL.
|
||||
$self->{model}->store_stl($output_file, 1);
|
||||
$self->statusbar->SetStatusText("STL file exported to $output_file");
|
||||
}
|
||||
|
@ -1615,6 +1501,7 @@ sub reload_from_disk {
|
|||
return if !defined $obj_idx;
|
||||
|
||||
my $model_object = $self->{model}->objects->[$obj_idx];
|
||||
#FIXME convert to local file encoding
|
||||
return if !$model_object->input_file
|
||||
|| !-e $model_object->input_file;
|
||||
|
||||
|
@ -1625,59 +1512,55 @@ sub reload_from_disk {
|
|||
my $o = $self->{model}->objects->[$new_obj_idx];
|
||||
$o->clear_instances;
|
||||
$o->add_instance($_) for @{$model_object->instances};
|
||||
#$o->invalidate_bounding_box;
|
||||
|
||||
if ($o->volumes_count == $model_object->volumes_count) {
|
||||
for my $i (0..($o->volumes_count-1)) {
|
||||
$o->get_volume($i)->config->apply($model_object->get_volume($i)->config);
|
||||
}
|
||||
}
|
||||
#FIXME restore volumes and their configs, layer_height_ranges, layer_height_profile, layer_height_profile_valid,
|
||||
}
|
||||
|
||||
$self->remove($obj_idx);
|
||||
}
|
||||
|
||||
sub export_object_stl {
|
||||
my $self = shift;
|
||||
|
||||
my ($self) = @_;
|
||||
my ($obj_idx, $object) = $self->selected_object;
|
||||
return if !defined $obj_idx;
|
||||
|
||||
my $model_object = $self->{model}->objects->[$obj_idx];
|
||||
|
||||
# Ask user for a file name to write into.
|
||||
my $output_file = $self->_get_export_file('STL') or return;
|
||||
$model_object->mesh->write_binary($output_file);
|
||||
$self->statusbar->SetStatusText("STL file exported to $output_file");
|
||||
}
|
||||
|
||||
sub export_amf {
|
||||
my $self = shift;
|
||||
|
||||
my ($self) = @_;
|
||||
return if !@{$self->{objects}};
|
||||
|
||||
# Ask user for a file name to write into.
|
||||
my $output_file = $self->_get_export_file('AMF') or return;
|
||||
$self->{model}->store_amf($output_file);
|
||||
$self->statusbar->SetStatusText("AMF file exported to $output_file");
|
||||
}
|
||||
|
||||
# Ask user to select an output file for a given file format (STl, AMF, 3MF).
|
||||
# Propose a default file name based on the 'output_filename_format' configuration value.
|
||||
sub _get_export_file {
|
||||
my $self = shift;
|
||||
my ($format) = @_;
|
||||
|
||||
my ($self, $format) = @_;
|
||||
my $suffix = $format eq 'STL' ? '.stl' : '.amf.xml';
|
||||
|
||||
my $output_file = $main::opt{output};
|
||||
{
|
||||
$output_file = $self->{print}->output_filepath($output_file);
|
||||
$output_file =~ s/\.[gG][cC][oO][dD][eE]$/$suffix/;
|
||||
my $dlg = Wx::FileDialog->new($self, "Save $format file as:", dirname($output_file),
|
||||
basename($output_file), &Slic3r::GUI::MODEL_WILDCARD, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if ($dlg->ShowModal != wxID_OK) {
|
||||
$dlg->Destroy;
|
||||
return undef;
|
||||
}
|
||||
$output_file = $dlg->GetPath;
|
||||
my $output_file = eval { $self->{print}->output_filepath($main::opt{output} // '') };
|
||||
Slic3r::GUI::catch_error($self) and return undef;
|
||||
$output_file =~ s/\.[gG][cC][oO][dD][eE]$/$suffix/;
|
||||
my $dlg = Wx::FileDialog->new($self, "Save $format file as:", dirname($output_file),
|
||||
basename($output_file), &Slic3r::GUI::MODEL_WILDCARD, wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if ($dlg->ShowModal != wxID_OK) {
|
||||
$dlg->Destroy;
|
||||
return undef;
|
||||
}
|
||||
$output_file = $dlg->GetPath;
|
||||
$dlg->Destroy;
|
||||
return $output_file;
|
||||
}
|
||||
|
||||
|
@ -1691,7 +1574,7 @@ sub reset_thumbnail {
|
|||
sub update {
|
||||
my ($self, $force_autocenter) = @_;
|
||||
|
||||
if ($Slic3r::GUI::Settings->{_}{autocenter} || $force_autocenter) {
|
||||
if (wxTheApp->{app_config}->get("autocenter") || $force_autocenter) {
|
||||
$self->{model}->center_instances_around_point($self->bed_centerf);
|
||||
}
|
||||
|
||||
|
@ -1714,11 +1597,13 @@ sub update {
|
|||
}
|
||||
|
||||
# When a number of extruders changes, the UI needs to be updated to show a single filament selection combo box per extruder.
|
||||
# Also the wxTheApp->{preset_bundle}->filament_presets needs to be resized accordingly
|
||||
# and some reasonable default has to be selected for the additional extruders.
|
||||
sub on_extruders_change {
|
||||
my ($self, $num_extruders) = @_;
|
||||
|
||||
my $choices = $self->{preset_choosers}{filament};
|
||||
while (@$choices < $num_extruders) {
|
||||
|
||||
while (int(@$choices) < $num_extruders) {
|
||||
# copy strings from first choice
|
||||
my @presets = $choices->[0]->GetStrings;
|
||||
|
||||
|
@ -1727,25 +1612,20 @@ sub on_extruders_change {
|
|||
my $extruder_idx = scalar @$choices;
|
||||
EVT_LEFT_DOWN($choice, sub { $self->filament_color_box_lmouse_down($extruder_idx, @_); } );
|
||||
push @$choices, $choice;
|
||||
|
||||
# copy icons from first choice
|
||||
$choice->SetItemBitmap($_, $choices->[0]->GetItemBitmap($_)) for 0..$#presets;
|
||||
|
||||
# insert new choice into sizer
|
||||
$self->{presets_sizer}->Insert(4 + ($#$choices-1)*2, 0, 0);
|
||||
$self->{presets_sizer}->Insert(5 + ($#$choices-1)*2, $choice, 0, wxEXPAND | wxBOTTOM, FILAMENT_CHOOSERS_SPACING);
|
||||
|
||||
# setup the listener
|
||||
EVT_COMBOBOX($choice, $choice, sub {
|
||||
my ($choice) = @_;
|
||||
wxTheApp->CallAfter(sub {
|
||||
$self->_on_select_preset('filament', $choice);
|
||||
$self->_on_select_preset('filament', $choice, $extruder_idx);
|
||||
});
|
||||
});
|
||||
|
||||
# initialize selection
|
||||
my $i = first { $choice->GetString($_) eq ($Slic3r::GUI::Settings->{presets}{"filament_" . $#$choices} || '') } 0 .. $#presets;
|
||||
$choice->SetSelection($i || 0);
|
||||
wxTheApp->{preset_bundle}->update_platter_filament_ui($extruder_idx, $choice);
|
||||
}
|
||||
|
||||
# remove unused choices if any
|
||||
|
@ -1759,8 +1639,7 @@ sub on_extruders_change {
|
|||
}
|
||||
|
||||
sub on_config_change {
|
||||
my $self = shift;
|
||||
my ($config) = @_;
|
||||
my ($self, $config) = @_;
|
||||
|
||||
my $update_scheduled;
|
||||
foreach my $opt_key (@{$self->{config}->diff($config)}) {
|
||||
|
@ -1817,7 +1696,6 @@ sub on_config_change {
|
|||
sub list_item_deselected {
|
||||
my ($self, $event) = @_;
|
||||
return if $PreventListEvents;
|
||||
|
||||
if ($self->{list}->GetFirstSelected == -1) {
|
||||
$self->select_object(undef);
|
||||
$self->{canvas}->Refresh;
|
||||
|
@ -1829,7 +1707,6 @@ sub list_item_deselected {
|
|||
sub list_item_selected {
|
||||
my ($self, $event) = @_;
|
||||
return if $PreventListEvents;
|
||||
|
||||
my $obj_idx = $event->GetIndex;
|
||||
$self->select_object($obj_idx);
|
||||
$self->{canvas}->Refresh;
|
||||
|
@ -1861,19 +1738,18 @@ sub filament_color_box_lmouse_down
|
|||
my $dialog = Wx::ColourDialog->new($self->GetFrame, $data);
|
||||
if ($dialog->ShowModal == wxID_OK) {
|
||||
my $cfg = Slic3r::Config->new;
|
||||
my $colors = $self->GetFrame->config->get('extruder_colour');
|
||||
my $colors = wxTheApp->{preset_bundle}->full_config->get('extruder_colour');
|
||||
$colors->[$extruder_idx] = $dialog->GetColourData->GetColour->GetAsString(wxC2S_HTML_SYNTAX);
|
||||
$cfg->set('extruder_colour', $colors);
|
||||
$self->GetFrame->{options_tabs}{printer}->load_config($cfg);
|
||||
$self->update_filament_colors_preview($extruder_idx);
|
||||
wxTheApp->{preset_bundle}->update_platter_filament_ui($extruder_idx, $combobox);
|
||||
}
|
||||
$dialog->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
sub object_cut_dialog {
|
||||
my $self = shift;
|
||||
my ($obj_idx) = @_;
|
||||
my ($self, $obj_idx) = @_;
|
||||
|
||||
if (!defined $obj_idx) {
|
||||
($obj_idx, undef) = $self->selected_object;
|
||||
|
@ -1898,23 +1774,20 @@ sub object_cut_dialog {
|
|||
}
|
||||
|
||||
sub object_settings_dialog {
|
||||
my $self = shift;
|
||||
my ($obj_idx) = @_;
|
||||
|
||||
if (!defined $obj_idx) {
|
||||
($obj_idx, undef) = $self->selected_object;
|
||||
}
|
||||
my ($self, $obj_idx) = @_;
|
||||
($obj_idx, undef) = $self->selected_object if !defined $obj_idx;
|
||||
my $model_object = $self->{model}->objects->[$obj_idx];
|
||||
|
||||
# validate config before opening the settings dialog because
|
||||
# that dialog can't be closed if validation fails, but user
|
||||
# can't fix any error which is outside that dialog
|
||||
return unless $self->validate_config;
|
||||
eval { wxTheApp->{preset_bundle}->full_config->validate; };
|
||||
return if Slic3r::GUI::catch_error($_[0]);
|
||||
|
||||
my $dlg = Slic3r::GUI::Plater::ObjectSettingsDialog->new($self,
|
||||
object => $self->{objects}[$obj_idx],
|
||||
model_object => $model_object,
|
||||
config => $self->GetFrame->config,
|
||||
config => wxTheApp->{preset_bundle}->full_config,
|
||||
);
|
||||
$self->pause_background_process;
|
||||
$dlg->ShowModal;
|
||||
|
@ -1965,9 +1838,9 @@ sub object_list_changed {
|
|||
for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode);
|
||||
}
|
||||
|
||||
# Selection of an active 3D object changed.
|
||||
sub selection_changed {
|
||||
my $self = shift;
|
||||
|
||||
my ($self) = @_;
|
||||
my ($obj_idx, $object) = $self->selected_object;
|
||||
my $have_sel = defined $obj_idx;
|
||||
|
||||
|
@ -2028,7 +1901,6 @@ sub select_object {
|
|||
$_->selected(0) for @{ $self->{objects} };
|
||||
if (defined $obj_idx) {
|
||||
$self->{objects}->[$obj_idx]->selected(1);
|
||||
|
||||
# We use this flag to avoid circular event handling
|
||||
# Select() happens to fire a wxEVT_LIST_ITEM_SELECTED on Windows,
|
||||
# whose event handler calls this method again and again and again
|
||||
|
@ -2042,26 +1914,13 @@ sub select_object {
|
|||
}
|
||||
|
||||
sub selected_object {
|
||||
my $self = shift;
|
||||
|
||||
my ($self) = @_;
|
||||
my $obj_idx = first { $self->{objects}[$_]->selected } 0..$#{ $self->{objects} };
|
||||
return undef if !defined $obj_idx;
|
||||
return ($obj_idx, $self->{objects}[$obj_idx]),
|
||||
}
|
||||
|
||||
sub validate_config {
|
||||
my $self = shift;
|
||||
|
||||
eval {
|
||||
$self->GetFrame->config->validate;
|
||||
};
|
||||
return 0 if Slic3r::GUI::catch_error($self);
|
||||
return 1;
|
||||
return defined $obj_idx ? ($obj_idx, $self->{objects}[$obj_idx]) : undef;
|
||||
}
|
||||
|
||||
sub statusbar {
|
||||
my $self = shift;
|
||||
return $self->GetFrame->{statusbar};
|
||||
return $_[0]->GetFrame->{statusbar};
|
||||
}
|
||||
|
||||
sub object_menu {
|
||||
|
@ -2069,23 +1928,24 @@ sub object_menu {
|
|||
|
||||
my $frame = $self->GetFrame;
|
||||
my $menu = Wx::Menu->new;
|
||||
$frame->_append_menu_item($menu, "Delete\t\xA0Del", 'Remove the selected object', sub {
|
||||
my $accel = ($^O eq 'MSWin32') ? sub { $_[0] . "\t\xA0" . $_[1] } : sub { $_[0] };
|
||||
$frame->_append_menu_item($menu, $accel->('Delete', 'Del'), 'Remove the selected object', sub {
|
||||
$self->remove;
|
||||
}, undef, 'brick_delete.png');
|
||||
$frame->_append_menu_item($menu, "Increase copies\t\xA0+", 'Place one more copy of the selected object', sub {
|
||||
$frame->_append_menu_item($menu, $accel->('Increase copies', '+'), 'Place one more copy of the selected object', sub {
|
||||
$self->increase;
|
||||
}, undef, 'add.png');
|
||||
$frame->_append_menu_item($menu, "Decrease copies\t\xA0-", 'Remove one copy of the selected object', sub {
|
||||
$frame->_append_menu_item($menu, $accel->('Decrease copies', '-'), 'Remove one copy of the selected object', sub {
|
||||
$self->decrease;
|
||||
}, undef, 'delete.png');
|
||||
$frame->_append_menu_item($menu, "Set number of copies…", 'Change the number of copies of the selected object', sub {
|
||||
$self->set_number_of_copies;
|
||||
}, undef, 'textfield.png');
|
||||
$menu->AppendSeparator();
|
||||
$frame->_append_menu_item($menu, "Rotate 45° clockwise\t\xA0l", 'Rotate the selected object by 45° clockwise', sub {
|
||||
$frame->_append_menu_item($menu, $accel->('Rotate 45° clockwise', 'l'), 'Rotate the selected object by 45° clockwise', sub {
|
||||
$self->rotate(-45, Z, 'relative');
|
||||
}, undef, 'arrow_rotate_clockwise.png');
|
||||
$frame->_append_menu_item($menu, "Rotate 45° counter-clockwise\t\xA0r", 'Rotate the selected object by 45° counter-clockwise', sub {
|
||||
$frame->_append_menu_item($menu, $accel->('Rotate 45° counter-clockwise', 'r'), 'Rotate the selected object by 45° counter-clockwise', sub {
|
||||
$self->rotate(+45, Z, 'relative');
|
||||
}, undef, 'arrow_rotate_anticlockwise.png');
|
||||
|
||||
|
@ -2118,7 +1978,7 @@ sub object_menu {
|
|||
my $scaleMenu = Wx::Menu->new;
|
||||
my $scaleMenuItem = $menu->AppendSubMenu($scaleMenu, "Scale", 'Scale the selected object along a single axis');
|
||||
$frame->_set_menu_item_icon($scaleMenuItem, 'arrow_out.png');
|
||||
$frame->_append_menu_item($scaleMenu, "Uniformly…\t\xA0s", 'Scale the selected object along the XYZ axes', sub {
|
||||
$frame->_append_menu_item($scaleMenu, $accel->('Uniformly…', 's'), 'Scale the selected object along the XYZ axes', sub {
|
||||
$self->changescale(undef);
|
||||
});
|
||||
$frame->_append_menu_item($scaleMenu, "Along X axis…", 'Scale the selected object along the X axis', sub {
|
||||
|
@ -2187,24 +2047,19 @@ use Wx::DND;
|
|||
use base 'Wx::FileDropTarget';
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my ($window) = @_;
|
||||
my ($class, $window) = @_;
|
||||
my $self = $class->SUPER::new;
|
||||
$self->{window} = $window;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub OnDropFiles {
|
||||
my $self = shift;
|
||||
my ($x, $y, $filenames) = @_;
|
||||
|
||||
my ($self, $x, $y, $filenames) = @_;
|
||||
# stop scalars leaking on older perl
|
||||
# https://rt.perl.org/rt3/Public/Bug/Display.html?id=70602
|
||||
@_ = ();
|
||||
|
||||
# only accept STL, OBJ and AMF files
|
||||
return 0 if grep !/\.(?:[sS][tT][lL]|[oO][bB][jJ]|[aA][mM][fF](?:\.[xX][mM][lL])?|[pP][rR][uU][sS][aA])$/, @$filenames;
|
||||
|
||||
$self->{window}->load_files($filenames);
|
||||
}
|
||||
|
||||
|
@ -2220,10 +2075,8 @@ has 'selected' => (is => 'rw', default => sub { 0 });
|
|||
|
||||
sub make_thumbnail {
|
||||
my ($self, $model, $obj_idx) = @_;
|
||||
|
||||
# make method idempotent
|
||||
$self->thumbnail->clear;
|
||||
|
||||
# raw_mesh is the non-transformed (non-rotated, non-scaled, non-translated) sum of non-modifier object volumes.
|
||||
my $mesh = $model->objects->[$obj_idx]->raw_mesh;
|
||||
#FIXME The "correct" variant could be extremely slow.
|
||||
|
@ -2239,7 +2092,6 @@ sub make_thumbnail {
|
|||
my $convex_hull = Slic3r::ExPolygon->new($mesh->convex_hull);
|
||||
$self->thumbnail->append($convex_hull);
|
||||
# }
|
||||
|
||||
return $self->thumbnail;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ 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(:misc :pen :brush :sizer :font :cursor wxTAB_TRAVERSAL);
|
||||
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';
|
||||
|
||||
|
@ -102,7 +102,7 @@ sub repaint {
|
|||
}
|
||||
|
||||
# draw print center
|
||||
if (@{$self->{objects}} && $Slic3r::GUI::Settings->{_}{autocenter}) {
|
||||
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]);
|
||||
|
@ -197,7 +197,6 @@ sub repaint {
|
|||
|
||||
sub mouse_event {
|
||||
my ($self, $event) = @_;
|
||||
|
||||
my $pos = $event->GetPosition;
|
||||
my $point = $self->point_to_model_units([ $pos->x, $pos->y ]); #]]
|
||||
if ($event->ButtonDown) {
|
||||
|
@ -257,7 +256,7 @@ sub mouse_event {
|
|||
}
|
||||
|
||||
sub update_bed_size {
|
||||
my $self = shift;
|
||||
my ($self) = @_;
|
||||
|
||||
# when the canvas is not rendered yet, its GetSize() method returns 0,0
|
||||
my $canvas_size = $self->GetSize;
|
||||
|
|
|
@ -9,7 +9,7 @@ use Wx::Event qw(EVT_KEY_DOWN EVT_CHAR);
|
|||
use base qw(Slic3r::GUI::3DScene Class::Accessor);
|
||||
|
||||
__PACKAGE__->mk_accessors(qw(
|
||||
on_rotate_object_left on_rotate_object_right on_scale_object_uniformly
|
||||
on_arrange on_rotate_object_left on_rotate_object_right on_scale_object_uniformly
|
||||
on_remove_object on_increase_objects on_decrease_objects));
|
||||
|
||||
sub new {
|
||||
|
@ -88,7 +88,9 @@ sub new {
|
|||
$event->Skip;
|
||||
} else {
|
||||
my $key = $event->GetKeyCode;
|
||||
if ($key == ord('l')) {
|
||||
if ($key == ord('a')) {
|
||||
$self->on_arrange->() if $self->on_arrange;
|
||||
} elsif ($key == ord('l')) {
|
||||
$self->on_rotate_object_left->() if $self->on_rotate_object_left;
|
||||
} elsif ($key == ord('r')) {
|
||||
$self->on_rotate_object_right->() if $self->on_rotate_object_right;
|
||||
|
@ -122,6 +124,11 @@ sub set_on_right_click {
|
|||
$self->on_right_click($cb);
|
||||
}
|
||||
|
||||
sub set_on_arrange {
|
||||
my ($self, $cb) = @_;
|
||||
$self->on_arrange($cb);
|
||||
}
|
||||
|
||||
sub set_on_rotate_object_left {
|
||||
my ($self, $cb) = @_;
|
||||
$self->on_rotate_object_left($cb);
|
||||
|
|
|
@ -42,9 +42,9 @@ sub new {
|
|||
{
|
||||
$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
|
||||
$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' });
|
||||
|
@ -58,13 +58,13 @@ sub new {
|
|||
$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));
|
||||
$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);
|
||||
|
@ -312,7 +312,7 @@ sub selection_changed {
|
|||
$config = $self->{model_object}->config;
|
||||
}
|
||||
# get default values
|
||||
my $default_config = Slic3r::Config->new_from_defaults(@opt_keys);
|
||||
my $default_config = Slic3r::Config::new_from_defaults_keys(\@opt_keys);
|
||||
|
||||
# append default extruder
|
||||
push @opt_keys, 'extruder';
|
||||
|
@ -490,12 +490,12 @@ sub CanClose {
|
|||
# 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 = Slic3r::Config->merge($self->GetParent->GetParent->GetParent->GetParent->GetParent->config, $self->model_object->config);
|
||||
my $config = $self->GetParent->GetParent->GetParent->GetParent->GetParent->config->clone;
|
||||
eval {
|
||||
$config->apply($self->model_object->config);
|
||||
$config->validate;
|
||||
};
|
||||
return 0 if Slic3r::GUI::catch_error($self);
|
||||
return 1;
|
||||
return ! Slic3r::GUI::catch_error($self);
|
||||
}
|
||||
|
||||
sub PartsChanged {
|
||||
|
|
|
@ -46,7 +46,7 @@ sub new {
|
|||
# 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),
|
||||
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;
|
||||
|
@ -146,7 +146,7 @@ sub update_optgroup {
|
|||
# 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),
|
||||
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);
|
||||
|
|
|
@ -10,6 +10,7 @@ sub new {
|
|||
my $self = $class->SUPER::new($parent, -1, "Preferences", wxDefaultPosition, wxDefaultSize);
|
||||
$self->{values} = {};
|
||||
|
||||
my $app_config = wxTheApp->{app_config};
|
||||
my $optgroup;
|
||||
$optgroup = Slic3r::GUI::OptionsGroup->new(
|
||||
parent => $self,
|
||||
|
@ -25,7 +26,7 @@ sub new {
|
|||
# type => 'bool',
|
||||
# label => 'Check for updates',
|
||||
# tooltip => 'If this is enabled, Slic3r will check for updates daily and display a reminder if a newer version is available.',
|
||||
# default => $Slic3r::GUI::Settings->{_}{version_check} // 1,
|
||||
# default => $app_config->get("version_check") // 1,
|
||||
# readonly => !wxTheApp->have_version_check,
|
||||
# ));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
|
@ -33,36 +34,43 @@ sub new {
|
|||
type => 'bool',
|
||||
label => 'Remember output directory',
|
||||
tooltip => 'If this is enabled, Slic3r will prompt the last output directory instead of the one containing the input files.',
|
||||
default => $Slic3r::GUI::Settings->{_}{remember_output_path},
|
||||
default => $app_config->get("remember_output_path"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'autocenter',
|
||||
type => 'bool',
|
||||
label => 'Auto-center parts',
|
||||
tooltip => 'If this is enabled, Slic3r will auto-center objects around the print bed center.',
|
||||
default => $Slic3r::GUI::Settings->{_}{autocenter},
|
||||
default => $app_config->get("autocenter"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'background_processing',
|
||||
type => 'bool',
|
||||
label => 'Background processing',
|
||||
tooltip => 'If this is enabled, Slic3r will pre-process objects as soon as they\'re loaded in order to save time when exporting G-code.',
|
||||
default => $Slic3r::GUI::Settings->{_}{background_processing},
|
||||
readonly => !$Slic3r::have_threads,
|
||||
default => $app_config->get("background_processing"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'no_controller',
|
||||
type => 'bool',
|
||||
label => 'Disable USB/serial connection',
|
||||
tooltip => 'Disable communication with the printer over a serial / USB cable. This simplifies the user interface in case the printer is never attached to the computer.',
|
||||
default => $Slic3r::GUI::Settings->{_}{no_controller},
|
||||
default => $app_config->get("no_controller"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'no_defaults',
|
||||
type => 'bool',
|
||||
label => 'Suppress "- default -" presets',
|
||||
tooltip => 'Suppress "- default -" presets in the Print / Filament / Printer selections once there are any other valid presets available.',
|
||||
default => $Slic3r::GUI::Settings->{_}{no_defaults},
|
||||
default => $app_config->get("no_defaults"),
|
||||
));
|
||||
$optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new(
|
||||
opt_id => 'show_incompatible_presets',
|
||||
type => 'bool',
|
||||
label => 'Show incompatible print and filament presets',
|
||||
tooltip => 'When checked, the print and filament presets are shown in the preset editor even ' .
|
||||
'if they are marked as incompatible with the active printer',
|
||||
default => $app_config->get("show_incompatible_presets"),
|
||||
));
|
||||
|
||||
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
|
@ -79,14 +87,15 @@ sub new {
|
|||
}
|
||||
|
||||
sub _accept {
|
||||
my $self = shift;
|
||||
my ($self) = @_;
|
||||
|
||||
if (defined($self->{values}{no_controller})) {
|
||||
if (defined($self->{values}{no_controller}) ||
|
||||
defined($self->{values}{no_defaults})) {
|
||||
Slic3r::GUI::warning_catcher($self)->("You need to restart Slic3r to make the changes effective.");
|
||||
}
|
||||
|
||||
$Slic3r::GUI::Settings->{_}{$_} = $self->{values}{$_} for keys %{$self->{values}};
|
||||
wxTheApp->save_settings;
|
||||
my $app_config = wxTheApp->{app_config};
|
||||
$app_config->set($_, $self->{values}{$_}) for keys %{$self->{values}};
|
||||
|
||||
$self->EndModal(wxID_OK);
|
||||
$self->Close; # needed on Linux
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue