From 793301d3192403aecad8c01df0f0b9485cc6671b Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 7 Aug 2012 18:44:47 +0200 Subject: [PATCH] Allow to select multiple filaments in GUI when multiple extruders are configured --- lib/Slic3r/GUI/Plater.pm | 52 +++++++++++++++++++++++-- lib/Slic3r/GUI/SkeinPanel.pm | 21 +++++++++- lib/Slic3r/GUI/Tab.pm | 75 +++++++++++++++++++++--------------- 3 files changed, 110 insertions(+), 38 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 46e2d3e09..e7eceb8ca 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -9,7 +9,7 @@ use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 scale unscale); use Slic3r::Geometry::Clipper qw(JT_ROUND); use threads::shared qw(shared_clone); use Wx qw(:bitmap :brush :button :cursor :dialog :filedialog :font :keycode :icon :id :listctrl :misc :panel :pen :sizer :toolbar :window); -use Wx::Event qw(EVT_BUTTON EVT_COMMAND EVT_KEY_DOWN EVT_LIST_ITEM_DESELECTED EVT_LIST_ITEM_SELECTED EVT_MOUSE_EVENTS EVT_PAINT EVT_TOOL); +use Wx::Event qw(EVT_BUTTON EVT_COMMAND EVT_KEY_DOWN EVT_LIST_ITEM_DESELECTED EVT_LIST_ITEM_SELECTED EVT_MOUSE_EVENTS EVT_PAINT EVT_TOOL EVT_CHOICE); use base 'Wx::Panel'; use constant TB_MORE => &Wx::NewId; @@ -30,13 +30,14 @@ use constant CANVAS_SIZE => [300,300]; use constant CANVAS_TEXT => join('-', +(localtime)[3,4]) eq '13-8' ? 'What do you want to print today? ™' # Sept. 13, 2006. The first part ever printed by a RepRap to make another RepRap. : 'Drag your objects here'; +use constant FILAMENT_CHOOSERS_SPACING => 3; sub new { my $class = shift; my ($parent) = @_; my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); $self->{config} = Slic3r::Config->new_from_defaults(qw( - bed_size print_center complete_objects extruder_clearance_radius skirts skirt_distance + bed_size print_center complete_objects extruder_clearance_radius skirts skirt_distance extruders_count )); $self->{canvas} = Wx::Panel->new($self, -1, wxDefaultPosition, CANVAS_SIZE, wxTAB_TRAVERSAL); @@ -219,11 +220,22 @@ sub new { printer => 'Printer', ); $self->{preset_choosers} = {}; + $self->{preset_choosers_sizers} = {}; for my $group (qw(print filament printer)) { my $text = Wx::StaticText->new($self, -1, "$group_labels{$group}:", wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT); - $self->{preset_choosers}{$group} = Wx::Choice->new($self, -1, wxDefaultPosition, [150, -1], []); + my $choice = Wx::Choice->new($self, -1, wxDefaultPosition, [150, -1], []); + $self->{preset_choosers}{$group} = [$choice]; + EVT_CHOICE($choice, $choice, sub { + my $choice = shift; # avoid leaks + return if $group eq 'filament' && ($self->{config}->get('extruders_count') // 1) > 1; #/ + $self->skeinpanel->{options_tabs}{$group}->select_preset($choice->GetSelection); + }); + + $self->{preset_choosers_sizers}{$group} = Wx::BoxSizer->new(wxVERTICAL); + $self->{preset_choosers_sizers}{$group}->Add($choice, 0, wxEXPAND | wxBOTTOM, FILAMENT_CHOOSERS_SPACING); + $presets->Add($text, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4); - $presets->Add($self->{preset_choosers}{$group}, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 15); + $presets->Add($self->{preset_choosers_sizers}{$group}, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 15); } $presets->AddStretchSpacer(1); @@ -242,6 +254,25 @@ sub skeinpanel { return $self->GetParent->GetParent; } +sub update_presets { + my $self = shift; + my ($group, $items, $selected) = @_; + + foreach my $choice (@{ $self->{preset_choosers}{$group} }) { + my $sel = $choice->GetSelection; + $choice->Clear; + $choice->Append($_) for @$items; + $choice->SetSelection($sel) if $sel <= $#$items; + } + $self->{preset_choosers}{$group}[0]->SetSelection($selected); +} + +sub filament_presets { + my $self = shift; + + return map $_->GetSelection, @{ $self->{preset_choosers}{filament} }; +} + sub load { my $self = shift; @@ -683,6 +714,19 @@ sub on_config_change { if (exists $self->{config}{$opt_key}) { $self->{config}->set($opt_key, $value); $self->_update_bed_size if $opt_key eq 'bed_size'; + if ($opt_key eq 'extruders_count' && defined $value) { + my $choices = $self->{preset_choosers}{filament}; + while (@$choices < $value) { + push @$choices, Wx::Choice->new($self, -1, wxDefaultPosition, [150, -1], [$choices->[0]->GetStrings]); + $self->{preset_choosers_sizers}{filament}->Add($choices->[-1], 0, wxEXPAND | wxBOTTOM, FILAMENT_CHOOSERS_SPACING); + } + while (@$choices > $value) { + $self->{preset_choosers_sizers}{filament}->Remove(-1); + $choices->[-1]->Destroy; + pop @$choices; + } + $self->Layout; + } } } diff --git a/lib/Slic3r/GUI/SkeinPanel.pm b/lib/Slic3r/GUI/SkeinPanel.pm index be81a0a45..7ac2dde01 100644 --- a/lib/Slic3r/GUI/SkeinPanel.pm +++ b/lib/Slic3r/GUI/SkeinPanel.pm @@ -25,7 +25,7 @@ sub new { for my $tab_name (qw(print filament printer)) { $self->{options_tabs}{$tab_name} = ("Slic3r::GUI::Tab::" . ucfirst $tab_name)->new( $self->{tabpanel}, - sync_presets_with => $self->{plater}{preset_choosers}{$tab_name}, + plater => $self->{plater}, on_value_change => sub { $self->{plater}->on_config_change(@_) }, # propagate config change events to the plater ); $self->{tabpanel}->AddPage($self->{options_tabs}{$tab_name}, $self->{options_tabs}{$tab_name}->title); @@ -235,9 +235,26 @@ This method collects all config values from the tabs and merges them into a sing sub config { my $self = shift; + # retrieve filament presets and build a single config object for them + my $filament_config; + foreach my $preset_idx ($self->{plater}->filament_presets) { + my $preset = $self->{options_tabs}{filament}->get_preset($preset_idx); + my $config = $self->{options_tabs}{filament}->get_preset_config($preset); + if (!$filament_config) { + $filament_config = $config; + next; + } + foreach my $opt_key (keys %$config) { + next unless ref $filament_config->get($opt_key) eq 'ARRAY'; + push @{ $filament_config->get($opt_key) }, $config->get($opt_key)->[0]; + } + } + return Slic3r::Config->merge( Slic3r::Config->new_from_defaults, - (map $_->config, values %{$self->{options_tabs}}), + $self->{options_tabs}{print}->config, + $self->{options_tabs}{printer}->config, + $filament_config, ); } diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 284dea175..797961e7d 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -14,12 +14,7 @@ sub new { my ($parent, %params) = @_; my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxBK_LEFT | wxTAB_TRAVERSAL); $self->{options} = []; # array of option names handled by this tab - - $self->{$_} = $params{$_} for qw(sync_presets_with on_value_change); - EVT_CHOICE($parent, $self->{sync_presets_with}, sub { - $self->{presets_choice}->SetSelection($self->{sync_presets_with}->GetSelection); - $self->on_select_preset; - }); + $self->{$_} = $params{$_} for qw(plater on_value_change); # horizontal sizer $self->{sizer} = Wx::BoxSizer->new(wxHORIZONTAL); @@ -142,6 +137,11 @@ sub current_preset { return $self->{presets}[ $self->{presets_choice}->GetSelection ]; } +sub get_preset { + my $self = shift; + return $self->{presets}[ $_[0] ]; +} + # propagate event to the parent sub on_value_change { my $self = shift; @@ -157,6 +157,12 @@ sub select_default_preset { $self->{presets_choice}->SetSelection(0); } +sub select_preset { + my $self = shift; + $self->{presets_choice}->SetSelection($_[0]); + $self->on_select_preset; +} + sub on_select_preset { my $self = shift; @@ -172,27 +178,18 @@ sub on_select_preset { } my $preset = $self->current_preset; - if ($preset->{default}) { - # default settings: disable the delete button - $self->{config}->apply(Slic3r::Config->new_from_defaults(@{$self->{options}})); - $self->{btn_delete_preset}->Disable; - } else { - if (!-e $preset->{file}) { - Slic3r::GUI::show_error($self, "The selected preset does not exist anymore ($preset->{file})."); - return; + my $preset_config = $self->get_preset_config($preset); + eval { + local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); + foreach my $opt_key (@{$self->{options}}) { + $self->{config}->set($opt_key, $preset_config->get($opt_key)); } - eval { - local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); - my $external_config = Slic3r::Config->load($preset->{file}); - foreach my $opt_key (@{$self->{options}}) { - $self->{config}->set($opt_key, $external_config->get($opt_key)); - } - }; - Slic3r::GUI::catch_error($self); - $preset->{external} - ? $self->{btn_delete_preset}->Disable - : $self->{btn_delete_preset}->Enable; - } + }; + Slic3r::GUI::catch_error($self); + ($preset->{default} || $preset->{external}) + ? $self->{btn_delete_preset}->Disable + : $self->{btn_delete_preset}->Enable; + $self->on_preset_loaded; $self->reload_values; $self->set_dirty(0); @@ -200,6 +197,25 @@ sub on_select_preset { Slic3r::GUI->save_settings; } +sub get_preset_config { + my $self = shift; + my ($preset) = @_; + + my $config = Slic3r::Config->new_from_defaults(@{$self->{options}}); + + if (!$preset->{default}) { + if (!-e $preset->{file}) { + Slic3r::GUI::show_error($self, "The selected preset does not exist anymore ($preset->{file})."); + return; + } + + # apply preset values on top of defaults + $config->apply(Slic3r::Config->load($preset->{file})); + } + + return $config; +} + sub add_options_page { my $self = shift; my ($title, $icon, %params) = @_; @@ -347,12 +363,7 @@ sub load_external_config { sub sync_presets { my $self = shift; - return unless $self->{sync_presets_with}; - $self->{sync_presets_with}->Clear; - foreach my $item ($self->{presets_choice}->GetStrings) { - $self->{sync_presets_with}->Append($item); - } - $self->{sync_presets_with}->SetSelection($self->{presets_choice}->GetSelection); + $self->{plater}->update_presets($self->name, [$self->{presets_choice}->GetStrings], $self->{presets_choice}->GetSelection); } package Slic3r::GUI::Tab::Print;