diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index f2b8b0772..0c9e0e5c2 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -140,8 +140,8 @@ sub _init_tabpanel { if ($self->{plater}) { $self->{plater}->on_select_preset(sub { - my ($group, $preset) = @_; - $self->{options_tabs}{$group}->select_preset($preset); + my ($group, $i) = @_; + $self->{options_tabs}{$group}->select_preset($i); }); # load initial config diff --git a/lib/Slic3r/GUI/OptionsGroup.pm b/lib/Slic3r/GUI/OptionsGroup.pm index d6a486828..864916665 100644 --- a/lib/Slic3r/GUI/OptionsGroup.pm +++ b/lib/Slic3r/GUI/OptionsGroup.pm @@ -167,6 +167,11 @@ sub _build_field { parent => $self->parent, option => $opt, ); + } elsif ($type eq 'color') { + $field = Slic3r::GUI::OptionsGroup::Field::ColourPicker->new( + parent => $self->parent, + option => $opt, + ); } elsif ($type =~ /^(f|s|s@|percent)$/) { $field = Slic3r::GUI::OptionsGroup::Field::TextCtrl->new( parent => $self->parent, diff --git a/lib/Slic3r/GUI/OptionsGroup/Field.pm b/lib/Slic3r/GUI/OptionsGroup/Field.pm index bc8e6a02d..2721853d4 100644 --- a/lib/Slic3r/GUI/OptionsGroup/Field.pm +++ b/lib/Slic3r/GUI/OptionsGroup/Field.pm @@ -340,6 +340,47 @@ sub get_value { } +package Slic3r::GUI::OptionsGroup::Field::ColourPicker; +use Moo; +extends 'Slic3r::GUI::OptionsGroup::Field::wxWindow'; + +use Wx qw(:misc :colour); +use Wx::Event qw(EVT_COLOURPICKER_CHANGED); + +sub BUILD { + my ($self) = @_; + + my $field = Wx::ColourPickerCtrl->new($self->parent, -1, + $self->_string_to_colour($self->option->default), wxDefaultPosition, + $self->_default_size); + $self->wxWindow($field); + + EVT_COLOURPICKER_CHANGED($self->parent, $field, sub { + $self->_on_change($self->option->opt_id); + }); +} + +sub set_value { + my ($self, $value) = @_; + + $self->disable_change_event(1); + $self->wxWindow->SetColour($self->_string_to_colour($value)); + $self->disable_change_event(0); +} + +sub get_value { + my ($self) = @_; + return $self->wxWindow->GetColour->GetAsString(wxC2S_HTML_SYNTAX); +} + +sub _string_to_colour { + my ($self, $string) = @_; + + $string =~ s/^#//; + return Wx::Colour->new(unpack 'C*', pack 'H*', $string); +} + + package Slic3r::GUI::OptionsGroup::Field::wxSizer; use Moo; extends 'Slic3r::GUI::OptionsGroup::Field'; diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index c44dca8f5..8589887a6 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -8,10 +8,10 @@ use List::Util qw(sum first max); use Slic3r::Geometry qw(X Y Z MIN MAX scale unscale deg2rad); use threads::shared qw(shared_clone); use Wx qw(:button :cursor :dialog :filedialog :keycode :icon :font :id :listctrl :misc - :panel :sizer :toolbar :window wxTheApp :notebook); + :panel :sizer :toolbar :window wxTheApp :notebook :combobox); use Wx::Event qw(EVT_BUTTON EVT_COMMAND EVT_KEY_DOWN EVT_LIST_ITEM_ACTIVATED EVT_LIST_ITEM_DESELECTED EVT_LIST_ITEM_SELECTED EVT_MOUSE_EVENTS EVT_PAINT EVT_TOOL - EVT_CHOICE EVT_TIMER EVT_NOTEBOOK_PAGE_CHANGED); + EVT_CHOICE EVT_COMBOBOX EVT_TIMER EVT_NOTEBOOK_PAGE_CHANGED); use base 'Wx::Panel'; use constant TB_ADD => &Wx::NewId; @@ -36,7 +36,7 @@ our $ERROR_EVENT : shared = Wx::NewEventType; our $EXPORT_COMPLETED_EVENT : shared = Wx::NewEventType; our $PROCESS_COMPLETED_EVENT : shared = Wx::NewEventType; -use constant FILAMENT_CHOOSERS_SPACING => 3; +use constant FILAMENT_CHOOSERS_SPACING => 0; use constant PROCESS_DELAY => 0.5 * 1000; # milliseconds my $PreventListEvents = 0; @@ -328,12 +328,11 @@ sub new { 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::Choice->new($self, -1, wxDefaultPosition, wxDefaultSize, []); - $choice->SetFont($Slic3r::GUI::small_font); + my $choice = Wx::BitmapComboBox->new($self, -1, "", wxDefaultPosition, wxDefaultSize, [], wxCB_READONLY); $self->{preset_choosers}{$group} = [$choice]; - EVT_CHOICE($choice, $choice, sub { $self->_on_select_preset($group, @_) }); + EVT_COMBOBOX($choice, $choice, sub { $self->_on_select_preset($group, @_) }); $presets->Add($text, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL | wxRIGHT, 4); - $presets->Add($choice, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxBOTTOM, 8); + $presets->Add($choice, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND | wxBOTTOM, 0); } } @@ -438,13 +437,33 @@ sub GetFrame { sub update_presets { my $self = shift; - my ($group, $items, $selected) = @_; + my ($group, $presets, $selected) = @_; foreach my $choice (@{ $self->{preset_choosers}{$group} }) { my $sel = $choice->GetSelection; $choice->Clear; - $choice->Append($_) for @$items; - $choice->SetSelection($sel) if $sel <= $#$items; + foreach my $preset (@$presets) { + my $bitmap; + if ($group eq 'filament') { + my $config = $preset->config(['filament_colour']); + my $rgb_hex = $config->filament_colour->[0]; + if ($preset->default) { + $bitmap = Wx::Bitmap->new("$Slic3r::var/spool.png", wxBITMAP_TYPE_PNG); + } else { + $rgb_hex =~ s/^#//; + my @rgb = unpack 'C*', pack 'H*', $rgb_hex; + my $image = Wx::Image->new(16,16); + $image->SetRGB(Wx::Rect->new(0,0,16,16), @rgb); + $bitmap = Wx::Bitmap->new($image); + } + } 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); + } + $choice->SetSelection($sel) if $sel <= $#$presets; } $self->{preset_choosers}{$group}[0]->SetSelection($selected); } @@ -1334,11 +1353,10 @@ sub on_extruders_change { my $choices = $self->{preset_choosers}{filament}; while (@$choices < $num_extruders) { my @presets = $choices->[0]->GetStrings; - push @$choices, Wx::Choice->new($self, -1, wxDefaultPosition, [150, -1], [@presets]); - $choices->[-1]->SetFont($Slic3r::GUI::small_font); + push @$choices, Wx::BitmapComboBox->new($self, -1, "", wxDefaultPosition, wxDefaultSize, [@presets], wxCB_READONLY); $self->{presets_sizer}->Insert(4 + ($#$choices-1)*2, 0, 0); $self->{presets_sizer}->Insert(5 + ($#$choices-1)*2, $choices->[-1], 0, wxEXPAND | wxBOTTOM, FILAMENT_CHOOSERS_SPACING); - EVT_CHOICE($choices->[-1], $choices->[-1], sub { $self->_on_select_preset('filament', @_) }); + EVT_COMBOBOX($choices->[-1], $choices->[-1], sub { $self->_on_select_preset('filament', @_) }); my $i = first { $choices->[-1]->GetString($_) eq ($Slic3r::GUI::Settings->{presets}{"filament_" . $#$choices} || '') } 0 .. $#presets; $choices->[-1]->SetSelection($i || 0); } diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 00eb1d6fa..230314004 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -177,7 +177,7 @@ sub _update {} sub _on_presets_changed { my $self = shift; - $self->{on_presets_changed}->([$self->{presets_choice}->GetStrings], $self->{presets_choice}->GetSelection) + $self->{on_presets_changed}->($self->{presets}, $self->{presets_choice}->GetSelection) if $self->{on_presets_changed}; } @@ -360,10 +360,10 @@ sub load_presets { $self->current_preset(undef); $self->{presets_choice}->Clear; - $self->{presets_choice}->Append($_->{name}) for @{$self->{presets}}; + $self->{presets_choice}->Append($_->name) for @{$self->{presets}}; { # load last used preset - my $i = first { basename($self->{presets}[$_]{file}) eq ($Slic3r::GUI::Settings->{presets}{$self->name} || '') } 1 .. $#{$self->{presets}}; + my $i = first { basename($self->{presets}[$_]->file) eq ($Slic3r::GUI::Settings->{presets}{$self->name} || '') } 1 .. $#{$self->{presets}}; $self->select_preset($i || 0); } $self->_on_presets_changed; @@ -813,7 +813,7 @@ sub build { my $self = shift; $self->init_config_options(qw( - filament_diameter extrusion_multiplier + filament_colour filament_diameter extrusion_multiplier temperature first_layer_temperature bed_temperature first_layer_bed_temperature fan_always_on cooling min_fan_speed max_fan_speed bridge_fan_speed disable_fan_first_layers @@ -824,6 +824,7 @@ sub build { my $page = $self->add_options_page('Filament', 'spool.png'); { my $optgroup = $page->new_optgroup('Filament'); + $optgroup->append_single_option_line('filament_colour', 0); $optgroup->append_single_option_line('filament_diameter', 0); $optgroup->append_single_option_line('extrusion_multiplier', 0); } diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index b5c42ec0b..7d454eae8 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -232,6 +232,12 @@ PrintConfigDef::build_def() { Options["fan_below_layer_time"].min = 0; Options["fan_below_layer_time"].max = 1000; + Options["filament_colour"].type = coStrings; + Options["filament_colour"].label = "Color"; + Options["filament_colour"].tooltip = "This is only used in the Slic3r interface as a visual help."; + Options["filament_colour"].cli = "filament-color=s@"; + Options["filament_colour"].gui_type = "color"; + Options["filament_diameter"].type = coFloats; Options["filament_diameter"].label = "Diameter"; Options["filament_diameter"].tooltip = "Enter your filament diameter here. Good precision is required, so use a caliper and do multiple measurements along the filament, then compute the average."; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 14c3fc79f..287f33cf7 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -409,6 +409,7 @@ class PrintConfig : public GCodeConfig ConfigOptionPoints extruder_offset; ConfigOptionBool fan_always_on; ConfigOptionInt fan_below_layer_time; + ConfigOptionStrings filament_colour; ConfigOptionFloat first_layer_acceleration; ConfigOptionInt first_layer_bed_temperature; ConfigOptionFloatOrPercent first_layer_extrusion_width; @@ -464,6 +465,8 @@ class PrintConfig : public GCodeConfig this->extruder_offset.values[0] = Pointf(0,0); this->fan_always_on.value = false; this->fan_below_layer_time.value = 60; + this->filament_colour.values.resize(1); + this->filament_colour.values[0] = "#FFFFFF"; this->first_layer_acceleration.value = 0; this->first_layer_bed_temperature.value = 0; this->first_layer_extrusion_width.value = 200; @@ -523,6 +526,7 @@ class PrintConfig : public GCodeConfig if (opt_key == "extruder_offset") return &this->extruder_offset; if (opt_key == "fan_always_on") return &this->fan_always_on; if (opt_key == "fan_below_layer_time") return &this->fan_below_layer_time; + if (opt_key == "filament_colour") return &this->filament_colour; if (opt_key == "first_layer_acceleration") return &this->first_layer_acceleration; if (opt_key == "first_layer_bed_temperature") return &this->first_layer_bed_temperature; if (opt_key == "first_layer_extrusion_width") return &this->first_layer_extrusion_width;