From d09b5f47fbc76cfc43e8adf2cc6531f550bb1f26 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 15 Apr 2017 11:10:53 +0200 Subject: [PATCH 01/14] Fixed regression causing posPrepareInfill invalidation to have no effects. #3874 --- lib/Slic3r/Print/Object.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 368a23406..300b8e361 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -156,7 +156,6 @@ sub prepare_infill { my ($self) = @_; return if $self->step_done(STEP_PREPARE_INFILL); - $self->set_step_started(STEP_PREPARE_INFILL); # This prepare_infill() is not really idempotent. # TODO: It should clear and regenerate fill_surfaces at every run @@ -164,6 +163,9 @@ sub prepare_infill { $self->invalidate_step(STEP_PERIMETERS); $self->make_perimeters; + # Do this after invalidating STEP_PERIMETERS because that would re-invalidate STEP_PREPARE_INFILL + $self->set_step_started(STEP_PREPARE_INFILL); + # prerequisites $self->detect_surfaces_type; From 3ca6ff38e84a72c20177f9955e79eec5b6b21bcc Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 15 Apr 2017 11:17:15 +0200 Subject: [PATCH 02/14] Bugfix: support_material_angle was parsed in radians rather than degrees. #3861 --- lib/Slic3r/Print/SupportMaterial.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/Print/SupportMaterial.pm b/lib/Slic3r/Print/SupportMaterial.pm index c533aa433..ecb044068 100644 --- a/lib/Slic3r/Print/SupportMaterial.pm +++ b/lib/Slic3r/Print/SupportMaterial.pm @@ -722,7 +722,7 @@ sub generate_toolpaths { # interface and contact infill if (@$interface || @$contact_infill) { - $fillers{interface}->set_angle($interface_angle); + $fillers{interface}->set_angle(deg2rad($interface_angle)); $fillers{interface}->set_min_spacing($_interface_flow->spacing); # find centerline of the external loop @@ -772,7 +772,7 @@ sub generate_toolpaths { # support or flange if (@$base) { my $filler = $fillers{support}; - $filler->set_angle($angles[ ($layer_id) % @angles ]); + $filler->set_angle(deg2rad($angles[ ($layer_id) % @angles ])); # We don't use $base_flow->spacing because we need a constant spacing # value that guarantees that all layers are correctly aligned. @@ -789,7 +789,7 @@ sub generate_toolpaths { # base flange if ($layer_id == 0) { $filler = $fillers{interface}; - $filler->set_angle($self->object_config->support_material_angle + 90); + $filler->set_angle(deg2rad($self->object_config->support_material_angle + 90)); $density = 0.5; $base_flow = $self->first_layer_flow; From 19a36cfda5c596cab61d72ac958173b0473432fa Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 17 Apr 2017 20:11:17 +0200 Subject: [PATCH 03/14] Rename 'overridable' to 'shortcuts' and change semantics accordingly: options in plater update the selected preset automatically instead of overriding it --- lib/Slic3r/GUI/Plater.pm | 21 ++++++++++++++------- lib/Slic3r/GUI/Preset.pm | 2 ++ lib/Slic3r/GUI/PresetEditor.pm | 24 ++++++++++++------------ xs/src/libslic3r/PrintConfig.cpp | 5 +++-- 4 files changed, 31 insertions(+), 21 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 5df6e6766..26ef4e51e 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -49,7 +49,7 @@ sub new { my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL); $self->{config} = Slic3r::Config->new_from_defaults(qw( bed_shape complete_objects extruder_clearance_radius skirts skirt_distance brim_width - serial_port serial_speed octoprint_host octoprint_apikey overridable filament_colour + serial_port serial_speed octoprint_host octoprint_apikey shortcuts filament_colour )); $self->{model} = Slic3r::Model->new; $self->{print} = Slic3r::Print->new; @@ -367,6 +367,13 @@ sub new { { my $o = $self->{settings_override_panel} = Slic3r::GUI::Plater::OverrideSettingsPanel->new($self, on_change => sub { + my ($preset) = $self->selected_presets('print'); + + # Apply the overrides to the current Print preset, potentially making it dirty + $preset->load_config; + $preset->_dirty_config->apply($self->{settings_override_config}); + + $self->load_presets; $self->config_changed; }); $o->set_editable(1); @@ -568,10 +575,10 @@ sub _on_select_preset { $o_config->clear; } - my $overridable = $config->get('overridable'); + my $shortcuts = $config->get('shortcuts'); # Add/remove options (we do it this way for preserving current options) - foreach my $opt_key (@$overridable) { + foreach my $opt_key (@$shortcuts) { # Populate option with the default value taken from configuration # (re-set the override always, because if we here it means user # switched to this preset or opened/closed the editor, so he expects @@ -579,15 +586,15 @@ sub _on_select_preset { $o_config->set($opt_key, $config->get($opt_key)); } foreach my $opt_key (@{$o_config->get_keys}) { - # Keep options listed among overridable and options added on the fly - if ((none { $_ eq $opt_key } @$overridable) + # Keep options listed among shortcuts and options added on the fly + if ((none { $_ eq $opt_key } @$shortcuts) && (any { $_ eq $opt_key } $o_panel->fixed_options)) { $o_config->erase($opt_key); } } $o_panel->set_default_config($config); - $o_panel->set_fixed_options(\@$overridable); + $o_panel->set_fixed_options(\@$shortcuts); $o_panel->update_optgroup; } elsif ($group eq 'printer') { # reload print and filament settings to honor their compatible_printer options @@ -766,7 +773,7 @@ sub config { my $config = Slic3r::Config->new_from_defaults; # get defaults also for the values tracked by the Plater's config - # (for example 'overridable') + # (for example 'shortcuts') $config->apply(Slic3r::Config->new_from_defaults(@{$self->{config}->get_keys})); my %classes = map { $_ => "Slic3r::GUI::PresetEditor::".ucfirst($_) } diff --git a/lib/Slic3r/GUI/Preset.pm b/lib/Slic3r/GUI/Preset.pm index 5bdd0f20e..03de04467 100644 --- a/lib/Slic3r/GUI/Preset.pm +++ b/lib/Slic3r/GUI/Preset.pm @@ -167,6 +167,8 @@ sub dirty_config { sub load_config { my ($self) = @_; + return if $self->_loaded; + my @keys = $self->_group_class->options; my @extra_keys = $self->_group_class->overriding_options; diff --git a/lib/Slic3r/GUI/PresetEditor.pm b/lib/Slic3r/GUI/PresetEditor.pm index dbeae5568..14234acfd 100644 --- a/lib/Slic3r/GUI/PresetEditor.pm +++ b/lib/Slic3r/GUI/PresetEditor.pm @@ -441,7 +441,7 @@ sub options { external_perimeter_extrusion_width infill_extrusion_width solid_infill_extrusion_width top_infill_extrusion_width support_material_extrusion_width infill_overlap bridge_flow_ratio - xy_size_compensation resolution overridable compatible_printers + xy_size_compensation resolution shortcuts compatible_printers print_settings_id ) } @@ -449,7 +449,7 @@ sub options { sub build { my $self = shift; - my $overridable_widget = sub { + my $shortcuts_widget = sub { my ($parent) = @_; my $Options = $Slic3r::Config::Options; @@ -458,15 +458,15 @@ sub build { grep { exists $Options->{$_} && $Options->{$_}{category} } $self->options ); my @opt_keys = sort { $options{$a} cmp $options{$b} } keys %options; - $self->{overridable_opt_keys} = [ @opt_keys ]; + $self->{shortcuts_opt_keys} = [ @opt_keys ]; - my $listbox = $self->{overridable_list} = Wx::CheckListBox->new($parent, -1, + my $listbox = $self->{shortcuts_list} = Wx::CheckListBox->new($parent, -1, wxDefaultPosition, [-1, 320], [ map $options{$_}, @opt_keys ]); EVT_CHECKLISTBOX($self, $listbox, sub { my $value = [ map $opt_keys[$_], grep $listbox->IsChecked($_), 0..$#opt_keys ]; - $self->config->set('overridable', $value); - $self->_on_value_change('overridable'); + $self->config->set('shortcuts', $value); + $self->_on_value_change('shortcuts'); }); my $sizer = Wx::BoxSizer->new(wxVERTICAL); @@ -715,7 +715,7 @@ sub build { } { - my $page = $self->add_options_page('Overrides', 'wrench.png'); + my $page = $self->add_options_page('Shortcuts', 'wrench.png'); { my $optgroup = $page->new_optgroup('Profile preferences'); { @@ -727,10 +727,10 @@ sub build { } } { - my $optgroup = $page->new_optgroup('Overridable settings (they will be displayed in the plater for quick changes)'); + my $optgroup = $page->new_optgroup('Show shortcuts for the following settings'); { my $line = Slic3r::GUI::OptionsGroup::Line->new( - widget => $overridable_widget, + widget => $shortcuts_widget, full_width => 1, ); $optgroup->append_line($line); @@ -745,9 +745,9 @@ sub reload_config { $self->_reload_compatible_printers_widget; { - my %overridable = map { $_ => 1 } @{ $self->config->get('overridable') }; - for my $i (0..$#{$self->{overridable_opt_keys}}) { - $self->{overridable_list}->Check($i, $overridable{ $self->{overridable_opt_keys}[$i] }); + my %shortcuts = map { $_ => 1 } @{ $self->config->get('shortcuts') }; + for my $i (0..$#{$self->{shortcuts_opt_keys}}) { + $self->{shortcuts_list}->Check($i, $shortcuts{ $self->{shortcuts_opt_keys}[$i] }); } } diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 8a63ef268..62d16fbbe 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -853,8 +853,9 @@ PrintConfigDef::PrintConfigDef() def->cli = "overhangs|detect-bridging-perimeters!"; def->default_value = new ConfigOptionBool(true); - def = this->add("overridable", coStrings); - def->label = "Overridable options"; + def = this->add("shortcuts", coStrings); + def->label = "Shortcuts"; + def->aliases.push_back("overridable"); { ConfigOptionStrings* opt = new ConfigOptionStrings(); opt->values.push_back("support_material"); From 2efb863a8708ccc1ce02cd62564cf8db640b70b1 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 29 Apr 2017 20:55:30 +0200 Subject: [PATCH 04/14] Update all shortcuts (including manually added ones) when closing the preset editor --- lib/Slic3r/GUI/Plater.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index fcc402064..d561158f7 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -577,11 +577,13 @@ sub _on_select_preset { my $shortcuts = $config->get('shortcuts'); # Add/remove options (we do it this way for preserving current options) - foreach my $opt_key (@$shortcuts) { + foreach my $opt_key (@{$o_config->get_keys}, @$shortcuts) { # Populate option with the default value taken from configuration # (re-set the override always, because if we here it means user # switched to this preset or opened/closed the editor, so he expects # the new values set in the editor to be used). + # Do this for both the current options and the configured shortcuts + # to make sure everything gets updated. $o_config->set($opt_key, $config->get($opt_key)); } foreach my $opt_key (@{$o_config->get_keys}) { From 0cc9dad14aebfdb1c98ef3953576b15cc75a3726 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 29 Apr 2017 21:18:52 +0200 Subject: [PATCH 05/14] Further change. Since we now have shortcuts, and not overrides, remove the + button for adding them on the fly, as it doesn't provide any advantage over actually opening the profile. Oh the other hand, automatically list dirty options in the plater --- lib/Slic3r/GUI/Plater.pm | 41 ++++++++----------- .../GUI/Plater/OverrideSettingsPanel.pm | 27 +++++++++--- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index d561158f7..a57446148 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -366,16 +366,25 @@ sub new { { my $o = $self->{settings_override_panel} = Slic3r::GUI::Plater::OverrideSettingsPanel->new($self, on_change => sub { - my ($preset) = $self->selected_presets('print'); + my ($opt_key) = @_; - # Apply the overrides to the current Print preset, potentially making it dirty + my ($preset) = $self->selected_presets('print'); $preset->load_config; - $preset->_dirty_config->apply($self->{settings_override_config}); + + # If this option is not in the override panel it means it was manually deleted, + # so let's restore the profile value. + if (!$self->{settings_override_config}->has($opt_key)) { + $preset->_dirty_config->set($opt_key, $preset->_config->get($opt_key)); + } else { + # Apply the overrides to the current Print preset, potentially making it dirty + $preset->_dirty_config->apply($self->{settings_override_config}); + } $self->load_presets; $self->config_changed; }); - $o->set_editable(1); + $o->can_add(0); + $o->can_delete(1); $o->set_opt_keys([ Slic3r::GUI::PresetEditor::Print->options ]); $self->{settings_override_config} = Slic3r::Config->new; $o->set_default_config($self->{settings_override_config}); @@ -569,30 +578,14 @@ sub _on_select_preset { my $o_config = $self->{settings_override_config}; my $o_panel = $self->{settings_override_panel}; - if ($changed) { - # Preserve current options if re-selecting the same preset - $o_config->clear; - } - my $shortcuts = $config->get('shortcuts'); - # Add/remove options (we do it this way for preserving current options) - foreach my $opt_key (@{$o_config->get_keys}, @$shortcuts) { - # Populate option with the default value taken from configuration - # (re-set the override always, because if we here it means user - # switched to this preset or opened/closed the editor, so he expects - # the new values set in the editor to be used). - # Do this for both the current options and the configured shortcuts - # to make sure everything gets updated. + # Re-populate the override panel with the configured shortcuts + # and the dirty options. + $o_config->clear; + foreach my $opt_key (@$shortcuts, $presets[0]->dirty_options) { $o_config->set($opt_key, $config->get($opt_key)); } - foreach my $opt_key (@{$o_config->get_keys}) { - # Keep options listed among shortcuts and options added on the fly - if ((none { $_ eq $opt_key } @$shortcuts) - && (any { $_ eq $opt_key } $o_panel->fixed_options)) { - $o_config->erase($opt_key); - } - } $o_panel->set_default_config($config); $o_panel->set_fixed_options(\@$shortcuts); diff --git a/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm b/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm index 9e91a7a56..0402dfdb4 100644 --- a/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm +++ b/lib/Slic3r/GUI/Plater/OverrideSettingsPanel.pm @@ -34,7 +34,8 @@ sub new { $self->{default_config} = Slic3r::Config->new; $self->{config} = Slic3r::Config->new; $self->{on_change} = $params{on_change}; - $self->{editable} = 1; + $self->{can_add} = 1; + $self->{can_delete} = 1; $self->{fixed_options} = {}; $self->{sizer} = Wx::BoxSizer->new(wxVERTICAL); @@ -141,7 +142,7 @@ sub update_optgroup { $self->{options_sizer}->Clear(1); return if !defined $self->{config}; - $self->{btn_add}->Show($self->{editable}); + $self->{btn_add}->Show($self->{can_add}); my %categories = (); foreach my $opt_key (@{$self->{config}->get_keys}) { @@ -170,7 +171,7 @@ sub update_optgroup { my ($opt_key, $opt_index) = @{ $optgroup->_opt_map->{$opt_id} }; # disallow deleting fixed options - return undef if $self->{fixed_options}{$opt_key} || !$self->{editable}; + return undef if $self->{fixed_options}{$opt_key} || !$self->{can_delete}; my $btn = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new($Slic3r::var->("delete.png"), wxBITMAP_TYPE_PNG), wxDefaultPosition, wxDefaultSize, Wx::wxBORDER_NONE); @@ -207,11 +208,27 @@ sub disable { $self->Disable; } -# Shows or hides the Add button. +# Shows or hides the Add/Delete buttons. sub set_editable { my ($self, $editable) = @_; - $self->{editable} = $editable; + $self->{can_add} = $self->{can_delete} = $editable; +} + +# Shows or hides the Add button. +sub can_add { + my ($self, $can) = @_; + + $self->{can_add} = $can if defined $can; + return $can; +} + +# Shows or hides the Delete button. +sub can_delete { + my ($self, $can) = @_; + + $self->{can_delete} = $can if defined $can; + return $can; } 1; From 9d1d5ccee96f1bfa7c4e303e89ea89bc2db3283a Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 21 May 2017 00:06:28 +0200 Subject: [PATCH 06/14] Minor fixes about config and presets --- lib/Slic3r/GUI/Controller.pm | 24 +++++++++++------------ lib/Slic3r/GUI/Controller/PrinterPanel.pm | 8 ++++---- lib/Slic3r/GUI/Plater.pm | 2 ++ xs/src/libslic3r/PrintConfig.cpp | 2 +- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/Slic3r/GUI/Controller.pm b/lib/Slic3r/GUI/Controller.pm index 4e8e42578..dfb328149 100644 --- a/lib/Slic3r/GUI/Controller.pm +++ b/lib/Slic3r/GUI/Controller.pm @@ -47,13 +47,13 @@ sub new { delete $presets{$_} for map $_->printer_name, @panels; foreach my $preset_name (sort keys %presets) { - my $config = $presets{$preset_name}->dirty_config; - next if !$config->serial_port; + my $preset = $presets{$preset_name}; + next if !$preset->dirty_config->serial_port; my $id = &Wx::NewId(); $menu->Append($id, $preset_name); EVT_MENU($menu, $id, sub { - $self->add_printer($preset_name, $config); + $self->add_printer($preset); }); } $self->PopupMenu($menu, $btn->GetPosition); @@ -100,10 +100,10 @@ sub OnActivate { # get all available presets my %presets = (); - { - my %all = map { $_->name => $_ } @{wxTheApp->presets->{printer}}; - my %configs = map { my $name = $_; $name => $all{$name}->load_config } keys %all; - %presets = map { $_ => $configs{$_} } grep $configs{$_}->serial_port, keys %all; + foreach my $preset (@{wxTheApp->presets->{printer}}) { + $preset->load_config; + next if !$preset->dirty_config->serial_port; + $presets{$preset->name} = $preset; } # decide which ones we want to keep @@ -124,7 +124,7 @@ sub OnActivate { # enable printers whose port is available my %ports = map { $_ => 1 } wxTheApp->scan_serial_ports; $active{$_} = 1 - for grep exists $ports{$presets{$_}->serial_port}, keys %presets; + for grep exists $ports{$presets{$_}->dirty_config->serial_port}, keys %presets; } if (!%active && $self->_selected_printer_preset) { # enable currently selected printer if it is configured @@ -140,7 +140,7 @@ sub OnActivate { $self->{sizer}->DetachWindow($panel); $panel->Destroy; } - $self->add_printer($_, $presets{$_}) for sort keys %active; + $self->add_printer($presets{$_}) for sort keys %active; # show/hide the warning about no printers $self->{text_no_printers}->Show(!%presets); @@ -156,16 +156,16 @@ sub OnActivate { } sub add_printer { - my ($self, $printer_name, $config) = @_; + my ($self, $preset) = @_; # check that printer doesn't exist already foreach my $panel ($self->print_panels) { - if ($panel->printer_name eq $printer_name) { + if ($panel->printer_name eq $preset->name) { return $panel; } } - my $printer_panel = Slic3r::GUI::Controller::PrinterPanel->new($self, $printer_name, $config); + my $printer_panel = Slic3r::GUI::Controller::PrinterPanel->new($self, $preset->name, $preset); $self->{sizer}->Prepend($printer_panel, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 10); $self->Layout; diff --git a/lib/Slic3r/GUI/Controller/PrinterPanel.pm b/lib/Slic3r/GUI/Controller/PrinterPanel.pm index 9e2dc211d..7d9e8a296 100644 --- a/lib/Slic3r/GUI/Controller/PrinterPanel.pm +++ b/lib/Slic3r/GUI/Controller/PrinterPanel.pm @@ -16,11 +16,11 @@ use constant STATUS_TIMER_INTERVAL => 1000; # milliseconds use constant TEMP_TIMER_INTERVAL => 5000; # milliseconds sub new { - my ($class, $parent, $printer_name, $config) = @_; + my ($class, $parent, $printer_name, $preset) = @_; my $self = $class->SUPER::new($parent, -1, wxDefaultPosition, [500, 250]); $self->printer_name($printer_name || 'Printer'); - $self->config($config); + $self->config($preset->dirty_config); $self->manual_control_config({ xy_travel_speed => 130, z_travel_speed => 10, @@ -103,7 +103,7 @@ sub new { } my $serial_port_sizer = Wx::BoxSizer->new(wxHORIZONTAL); { - $self->{serial_port_combobox} = Wx::ComboBox->new($self, -1, $config->serial_port, wxDefaultPosition, wxDefaultSize, []); + $self->{serial_port_combobox} = Wx::ComboBox->new($self, -1, $self->config->serial_port, wxDefaultPosition, wxDefaultSize, []); $self->{serial_port_combobox}->SetFont($Slic3r::GUI::small_font); $self->update_serial_ports; $serial_port_sizer->Add($self->{serial_port_combobox}, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, 1); @@ -125,7 +125,7 @@ sub new { } my $serial_speed_sizer = Wx::BoxSizer->new(wxHORIZONTAL); { - $self->{serial_speed_combobox} = Wx::ComboBox->new($self, -1, $config->serial_speed, wxDefaultPosition, wxDefaultSize, + $self->{serial_speed_combobox} = Wx::ComboBox->new($self, -1, $self->config->serial_speed, wxDefaultPosition, wxDefaultSize, ["57600", "115200", "250000"]); $self->{serial_speed_combobox}->SetFont($Slic3r::GUI::small_font); $serial_speed_sizer->Add($self->{serial_speed_combobox}, 0, wxALIGN_CENTER_VERTICAL, 0); diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index ef65c47a1..ba19b8ee1 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -584,6 +584,8 @@ sub _on_select_preset { # and the dirty options. $o_config->clear; foreach my $opt_key (@$shortcuts, $presets[0]->dirty_options) { + # Don't add shortcut for shortcuts! + next if $opt_key eq 'shortcuts'; $o_config->set($opt_key, $config->get($opt_key)); } diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index b2437506b..ce149a8fc 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1384,7 +1384,7 @@ PrintConfigDef::PrintConfigDef() def = this->add("support_material_interface_speed", coFloatOrPercent); def->label = "↳ interface"; - def->category = "Support material interface speed"; + def->full_label = "Support material interface speed"; def->gui_type = "f_enum_open"; def->category = "Support material"; def->tooltip = "Speed for printing support material interface layers. If expressed as percentage (for example 50%) it will be calculated over support material speed."; From ae88f843b55649e05bcd0315ce6f1fdad7746c2d Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 21 May 2017 00:10:19 +0200 Subject: [PATCH 07/14] Perform background processing when changing settings in the preset editor. #3835 #3853 --- lib/Slic3r/GUI/Plater.pm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index ba19b8ee1..e2a06d905 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -751,6 +751,9 @@ sub show_preset_editor { my @presets = $self->selected_presets($group); $dlg->preset_editor->select_preset_by_name($presets[$i // 0]->name); + $dlg->preset_editor->on_value_change(sub { + $self->config_changed; + }); $dlg->ShowModal; # Re-load the presets as they might have changed. From a3ddac06dd9e13a5d696535c30f6d9ba087a7919 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 21 May 2017 00:28:36 +0200 Subject: [PATCH 08/14] Save shortcut options instantly --- lib/Slic3r/GUI/Plater.pm | 6 +++++ lib/Slic3r/GUI/Preset.pm | 43 ++++++++++++++++++++++------------ lib/Slic3r/GUI/PresetEditor.pm | 2 +- 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index e2a06d905..efbbeb973 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -378,6 +378,12 @@ sub new { } else { # Apply the overrides to the current Print preset, potentially making it dirty $preset->_dirty_config->apply($self->{settings_override_config}); + + # If this is a configured shortcut (and not just a dirty option), + # save it now. + if (any { $_ eq $opt_key } @{$preset->dirty_config->shortcuts}) { + $preset->save([$opt_key]); + } } $self->load_presets; diff --git a/lib/Slic3r/GUI/Preset.pm b/lib/Slic3r/GUI/Preset.pm index 03de04467..2d0021937 100644 --- a/lib/Slic3r/GUI/Preset.pm +++ b/lib/Slic3r/GUI/Preset.pm @@ -94,7 +94,7 @@ sub prompt_unsaved_changes { if ($res == wxID_CANCEL) { return 0; } elsif ($res == wxID_YES) { - return $self->save($self->default ? undef : $self->name); + return $self->default ? $self->save_prompt($parent) : $self->save; } elsif ($res == wxID_NO) { $self->dismiss_changes; return 1; @@ -104,20 +104,29 @@ sub prompt_unsaved_changes { return 1; } +sub save_prompt { + my ($self, $parent) = @_; + + my $default_name = $self->default ? 'Untitled' : $self->name; + $default_name =~ s/\.ini$//i; + + my $dlg = Slic3r::GUI::SavePresetWindow->new($parent, + default => $default_name, + values => [ map $_->name, grep !$_->default && !$_->external, @{wxTheApp->presets->{$self->name}} ], + ); + return 0 unless $dlg->ShowModal == wxID_OK; + + $self->save_as($dlg->get_name); +} + sub save { - my ($self, $name, $parent) = @_; + my ($self, $opt_keys) = @_; - if (!$name) { - my $default_name = $self->default ? 'Untitled' : $self->name; - $default_name =~ s/\.ini$//i; - - my $dlg = Slic3r::GUI::SavePresetWindow->new($parent, - default => $default_name, - values => [ map $_->name, grep !$_->default && !$_->external, @{wxTheApp->presets->{$self->name}} ], - ); - return 0 unless $dlg->ShowModal == wxID_OK; - $name = $dlg->get_name; - } + return $self->save_as($self->name, $opt_keys); +} + +sub save_as { + my ($self, $name, $opt_keys) = @_; $self->rename($name); @@ -125,8 +134,12 @@ sub save { die "Calling save() without setting filename"; } - $self->_config->clear; - $self->_config->apply($self->_dirty_config); + if ($opt_keys) { + $self->_config->apply_only($self->_dirty_config, $opt_keys); + } else { + $self->_config->clear; + $self->_config->apply($self->_dirty_config); + } $self->_config->save($self->file); wxTheApp->load_presets; diff --git a/lib/Slic3r/GUI/PresetEditor.pm b/lib/Slic3r/GUI/PresetEditor.pm index 0cccf9982..e84a000b7 100644 --- a/lib/Slic3r/GUI/PresetEditor.pm +++ b/lib/Slic3r/GUI/PresetEditor.pm @@ -123,7 +123,7 @@ sub save_preset { $self->{treectrl}->SetFocus; my $preset = $self->current_preset; - $preset->save(undef, $self); + $preset->save_prompt($self); $self->load_presets; $self->select_preset_by_name($preset->name); From 060187ad1703f70c8e2c2847829216c38e889403 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 21 May 2017 18:48:08 +0200 Subject: [PATCH 09/14] Add preference option for displaying preset editors in dialogs or tabs --- lib/Slic3r/GUI.pm | 1 + lib/Slic3r/GUI/MainFrame.pm | 25 ++++++++++++---- lib/Slic3r/GUI/Plater.pm | 52 +++++++++++++++++++++++++++------- lib/Slic3r/GUI/Preferences.pm | 7 +++++ lib/Slic3r/GUI/PresetEditor.pm | 13 +++++++-- 5 files changed, 79 insertions(+), 19 deletions(-) diff --git a/lib/Slic3r/GUI.pm b/lib/Slic3r/GUI.pm index 16875b6b4..a402dc0c3 100644 --- a/lib/Slic3r/GUI.pm +++ b/lib/Slic3r/GUI.pm @@ -88,6 +88,7 @@ our $Settings = { no_controller => 0, threads => $Slic3r::Config::Options->{threads}{default}, color_toolpaths_by => 'role', + tabbed_preset_editors => 1, }, }; diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index fc7aef322..631d2a141 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -8,9 +8,10 @@ use utf8; use File::Basename qw(basename dirname); use List::Util qw(min); use Slic3r::Geometry qw(X Y Z); -use Wx qw(:frame :bitmap :id :misc :notebook :panel :sizer :menu :dialog :filedialog - :font :icon wxTheApp); -use Wx::Event qw(EVT_CLOSE EVT_NOTEBOOK_PAGE_CHANGED); +use Wx qw(:frame :bitmap :id :misc :panel :sizer :menu :dialog :filedialog + :font :icon :aui wxTheApp); +use Wx::AUI; +use Wx::Event qw(EVT_CLOSE EVT_AUINOTEBOOK_PAGE_CHANGED EVT_AUINOTEBOOK_PAGE_CLOSE); use base 'Wx::Frame'; our $qs_last_input_file; @@ -28,6 +29,7 @@ sub new { } $self->{loaded} = 0; + $self->{preset_editor_tabs} = {}; # group => panel # initialize tabpanel and menubar $self->_init_tabpanel; @@ -92,10 +94,21 @@ sub new { sub _init_tabpanel { my ($self) = @_; - $self->{tabpanel} = my $panel = Wx::Notebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL); - EVT_NOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub { - my $panel = $self->{tabpanel}->GetCurrentPage; + $self->{tabpanel} = my $panel = Wx::AuiNotebook->new($self, -1, wxDefaultPosition, wxDefaultSize, wxAUI_NB_TOP); + EVT_AUINOTEBOOK_PAGE_CHANGED($self, $self->{tabpanel}, sub { + my $panel = $self->{tabpanel}->GetPage($self->{tabpanel}->GetSelection); $panel->OnActivate if $panel->can('OnActivate'); + if ($self->{tabpanel}->GetSelection > 1) { + $self->{tabpanel}->SetWindowStyle($self->{tabpanel}->GetWindowStyleFlag | wxAUI_NB_CLOSE_ON_ACTIVE_TAB); + } else { + $self->{tabpanel}->SetWindowStyle($self->{tabpanel}->GetWindowStyleFlag & ~wxAUI_NB_CLOSE_ON_ACTIVE_TAB); + } + }); + EVT_AUINOTEBOOK_PAGE_CLOSE($self, $self->{tabpanel}, sub { + my $panel = $self->{tabpanel}->GetPage($self->{tabpanel}->GetSelection); + if ($panel->isa('Slic3r::GUI::PresetEditor')) { + delete $self->{preset_editor_tabs}{$panel->name}; + } }); $panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), "Plater"); diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 2cd8e52af..37a36fef0 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -534,6 +534,14 @@ sub _on_change_combobox { return 0 if !$self->prompt_unsaved_changes; } wxTheApp->CallAfter(sub { + # Close the preset editor tab if any + if (exists $self->GetFrame->{preset_editor_tabs}{$group}) { + my $tabpanel = $self->GetFrame->{tabpanel}; + $tabpanel->DeletePage($tabpanel->GetPageIndex($self->GetFrame->{preset_editor_tabs}{$group})); + delete $self->GetFrame->{preset_editor_tabs}{$group}; + $tabpanel->SetSelection(0); # without this, a newly created tab will not be selected by wx + } + $self->_on_select_preset($group); # This will remove the "(modified)" mark from any dirty preset handled here. @@ -742,19 +750,43 @@ sub selected_presets { sub show_preset_editor { my ($self, $group, $i) = @_; - my $class = "Slic3r::GUI::PresetEditorDialog::" . ucfirst($group); - my $dlg = $class->new($self); - my @presets = $self->selected_presets($group); - $dlg->preset_editor->select_preset_by_name($presets[$i // 0]->name); - $dlg->ShowModal; - # Re-load the presets as they might have changed. - $self->load_presets; + my $preset_editor; + my $dlg; + my $mainframe = $self->GetFrame; + my $tabpanel = $mainframe->{tabpanel}; + if (exists $mainframe->{preset_editor_tabs}{$group}) { + # we already have an open editor + $tabpanel->SetSelection($tabpanel->GetPageIndex($mainframe->{preset_editor_tabs}{$group})); + return; + } elsif ($Slic3r::GUI::Settings->{_}{tabbed_preset_editors}) { + my $class = "Slic3r::GUI::PresetEditor::" . ucfirst($group); + $mainframe->{preset_editor_tabs}{$group} = $preset_editor = $class->new($self->GetFrame); + $tabpanel->AddPage($preset_editor, ucfirst($group) . " Settings", 1); + } else { + my $class = "Slic3r::GUI::PresetEditorDialog::" . ucfirst($group); + $dlg = $class->new($self); + $preset_editor = $dlg->preset_editor; + } - # Select the preset that was last selected in the editor. - $self->select_preset_by_name - ($dlg->preset_editor->current_preset->name, $group, $i, 1); + $preset_editor->select_preset_by_name($presets[$i // 0]->name); + $preset_editor->on_value_change(sub { + $self->config_changed; + }); + $preset_editor->on_select_preset(sub { + my ($group, $preset) = @_; + + # Re-load the presets as they might have changed. + $self->load_presets; + + # Select the preset in plater too + $self->select_preset_by_name($preset->name, $group, $i, 1); + }); + + if ($dlg) { + $dlg->ShowModal; + } } # Returns the current config by merging the selected presets and the overrides. diff --git a/lib/Slic3r/GUI/Preferences.pm b/lib/Slic3r/GUI/Preferences.pm index 9c96efa3a..d4495d77b 100644 --- a/lib/Slic3r/GUI/Preferences.pm +++ b/lib/Slic3r/GUI/Preferences.pm @@ -71,6 +71,13 @@ sub new { 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}, )); + $optgroup->append_single_option_line(Slic3r::GUI::OptionsGroup::Option->new( + opt_id => 'tabbed_preset_editors', + type => 'bool', + label => 'Display profile editors as tabs', + tooltip => 'When opening a profile editor, it will be shown in a dialog or in a tab according to this option.', + default => $Slic3r::GUI::Settings->{_}{tabbed_preset_editors}, + )); my $sizer = Wx::BoxSizer->new(wxVERTICAL); $sizer->Add($optgroup->sizer, 0, wxEXPAND | wxBOTTOM | wxLEFT | wxRIGHT, 10); diff --git a/lib/Slic3r/GUI/PresetEditor.pm b/lib/Slic3r/GUI/PresetEditor.pm index aa78bb895..5558bbb99 100644 --- a/lib/Slic3r/GUI/PresetEditor.pm +++ b/lib/Slic3r/GUI/PresetEditor.pm @@ -87,7 +87,7 @@ sub new { }); EVT_CHOICE($parent, $self->{presets_choice}, sub { - $self->on_select_preset; + $self->_on_select_preset; }); EVT_BUTTON($self, $self->{btn_save_preset}, sub { $self->save_preset }); @@ -155,7 +155,7 @@ sub select_preset { my ($self, $i, $force) = @_; $self->{presets_choice}->SetSelection($i); - $self->on_select_preset($force); + $self->_on_select_preset($force); } sub select_preset_by_name { @@ -164,7 +164,7 @@ sub select_preset_by_name { my $presets = wxTheApp->presets->{$self->name}; my $i = first { $presets->[$_]->name eq $name } 0..$#$presets; $self->{presets_choice}->SetSelection($i); - $self->on_select_preset($force); + $self->_on_select_preset($force); } sub prompt_unsaved_changes { @@ -175,6 +175,11 @@ sub prompt_unsaved_changes { } sub on_select_preset { + my ($self, $cb) = @_; + $self->{on_select_preset} = $cb; +} + +sub _on_select_preset { my ($self, $force) = @_; # This method is called: @@ -221,6 +226,8 @@ sub on_select_preset { $@ = "I was unable to load the selected config file: $@"; Slic3r::GUI::catch_error($self); } + + $self->{on_select_preset}->($self->name, $preset) if $self->{on_select_preset}; } sub add_options_page { From 7255db01f92d3a06d6e01b71cf1af2fb2eb7faf7 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 21 May 2017 20:15:09 +0200 Subject: [PATCH 10/14] Go back to the Plater tab when closing a preset editor tab --- lib/Slic3r/GUI/MainFrame.pm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 631d2a141..83f53b916 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -109,6 +109,9 @@ sub _init_tabpanel { if ($panel->isa('Slic3r::GUI::PresetEditor')) { delete $self->{preset_editor_tabs}{$panel->name}; } + wxTheApp->CallAfter(sub { + $self->{tabpanel}->SetSelection(0); + }); }); $panel->AddPage($self->{plater} = Slic3r::GUI::Plater->new($panel), "Plater"); From ce68851a7cd26b731bd79b1ecf4711f0fd67152e Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 22 May 2017 00:10:07 +0200 Subject: [PATCH 11/14] Fixed regression in placeholders with preset names. #3960 --- lib/Slic3r/GUI/Plater.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 1c495c720..280837299 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -717,7 +717,7 @@ sub load_presets { } } - $self->{print}->placeholder_parser->set("${group}_preset", [ @preset_names ]); + $self->{print}->placeholder_parser->set_multiple("${group}_preset", [ @preset_names ]); } } From 846478520f5b05df5b8bd2dbbd95e21f4e207be3 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Wed, 24 May 2017 13:19:57 +0200 Subject: [PATCH 12/14] Fix some compilation warnings --- xs/Build.PL | 6 ++++++ xs/MANIFEST | 16 ++++++++++++++++ xs/src/libslic3r/TriangleMesh.cpp | 4 ++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/xs/Build.PL b/xs/Build.PL index 8b622b5c3..2633b8870 100644 --- a/xs/Build.PL +++ b/xs/Build.PL @@ -11,6 +11,9 @@ use Module::Build::WithXSpp; my $cpp_guess = ExtUtils::CppGuess->new; my $mswin = $^O eq 'MSWin32'; +# prevent an annoying concatenation warning by Devel::CheckLib +$ENV{LD_RUN_PATH} //= ""; + # _GLIBCXX_USE_C99 : to get the long long type for g++ # HAS_BOOL : stops Perl/lib/CORE/handy.h from doing "# define bool char" for MSVC # NOGDI : prevents inclusion of wingdi.h which defines functions Polygon() and Polyline() in global namespace @@ -199,6 +202,9 @@ if ($cpp_guess->is_gcc) { # https://svn.boost.org/trac/boost/ticket/8695 push @cflags, qw(-fno-inline-small-functions); } + + # our templated XS bindings cause undefined-var-template warnings + push @cflags, qw(-Wno-undefined-var-template); } my $build = Module::Build::WithXSpp->new( diff --git a/xs/MANIFEST b/xs/MANIFEST index 5b2925f2c..b9e98e0a6 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -1,5 +1,6 @@ Build.PL lib/Slic3r/XS.pm +libslic3r.doxygen MANIFEST This list of files src/admesh/connect.c src/admesh/normals.c @@ -8,6 +9,21 @@ src/admesh/stl.h src/admesh/stl_io.c src/admesh/stlinit.c src/admesh/util.c +src/boost/nowide/args.hpp +src/boost/nowide/cenv.hpp +src/boost/nowide/config.hpp +src/boost/nowide/convert.hpp +src/boost/nowide/cstdio.hpp +src/boost/nowide/cstdlib.hpp +src/boost/nowide/filebuf.hpp +src/boost/nowide/fstream.hpp +src/boost/nowide/integration/filesystem.hpp +src/boost/nowide/iostream.cpp +src/boost/nowide/iostream.hpp +src/boost/nowide/stackstring.hpp +src/boost/nowide/system.hpp +src/boost/nowide/utf8_codecvt.hpp +src/boost/nowide/windows.hpp src/clipper.cpp src/clipper.hpp src/expat/ascii.h diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/xs/src/libslic3r/TriangleMesh.cpp index 9e3c8bf1a..5a3a5a1ef 100644 --- a/xs/src/libslic3r/TriangleMesh.cpp +++ b/xs/src/libslic3r/TriangleMesh.cpp @@ -684,7 +684,7 @@ TriangleMesh::make_sphere(double rho, double fa) { // Fixed scaling const double z = -rho + increment*rho*2.0; // radius of the circle for this step. - const double r = sqrt(abs(rho*rho - z*z)); + const double r = sqrt(std::abs(rho*rho - z*z)); Pointf3 b(0, r, z); b.rotate(ring[i], Pointf3(0,0,z)); vertices.push_back(b); @@ -699,7 +699,7 @@ TriangleMesh::make_sphere(double rho, double fa) { // General case: insert and form facets for each step, joining it to the ring below it. for (size_t s = 2; s < steps - 1; s++) { const double z = -rho + increment*(double)s*2.0*rho; - const double r = sqrt(abs(rho*rho - z*z)); + const double r = sqrt(std::abs(rho*rho - z*z)); for (size_t i = 0; i < ring.size(); i++) { Pointf3 b(0, r, z); From a1b024671060c47fec1554fe9f2cd4dc50008212 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 26 May 2017 19:04:51 +0200 Subject: [PATCH 13/14] Fixed regression in dirty settings --- lib/Slic3r/GUI/Plater.pm | 13 +++++++++++++ lib/Slic3r/GUI/PresetEditor.pm | 14 ++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 280837299..a5a410402 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -388,6 +388,12 @@ sub new { $self->load_presets; $self->config_changed; + + # Reload the open tab if any + if (my $print_tab = $self->GetFrame->{preset_editor_tabs}{print}) { + $print_tab->load_presets; + $print_tab->reload_preset; + } }); $o->can_add(0); $o->can_delete(1); @@ -782,6 +788,13 @@ sub show_preset_editor { $preset_editor->select_preset_by_name($presets[$i // 0]->name); $preset_editor->on_value_change(sub { + # Re-load the presets in order to toggle the (modified) suffix + $self->load_presets; + + # Update shortcuts + $self->_on_select_preset($group); + + # Use the new config wherever we actually use its contents $self->config_changed; }); $preset_editor->on_select_preset(sub { diff --git a/lib/Slic3r/GUI/PresetEditor.pm b/lib/Slic3r/GUI/PresetEditor.pm index b566671f9..788c98eed 100644 --- a/lib/Slic3r/GUI/PresetEditor.pm +++ b/lib/Slic3r/GUI/PresetEditor.pm @@ -208,9 +208,7 @@ sub _on_select_preset { # prompted and chose to discard changes. $self->load_presets; - $preset->load_config if !$preset->_loaded; - $self->config->clear; - $self->config->apply($preset->dirty_config); + $self->reload_preset; eval { local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); @@ -220,7 +218,6 @@ sub _on_select_preset { $self->_update; $self->on_preset_loaded; - $self->reload_config; }; if ($@) { $@ = "I was unable to load the selected config file: $@"; @@ -247,6 +244,15 @@ sub add_options_page { return $page; } +sub reload_preset { + my ($self) = @_; + + $self->current_preset->load_config if !$self->current_preset->_loaded; + $self->config->clear; + $self->config->apply($self->current_preset->dirty_config); + $self->reload_config; +} + sub reload_config { my $self = shift; From 4ab483111002bd02959020b95ad34b9d652d051d Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 29 May 2017 18:50:00 +0200 Subject: [PATCH 14/14] Fixed behavior of dirty settings not being correctly updated in the plater --- lib/Slic3r/GUI/Plater.pm | 82 ++++++++++++++++++---------------- lib/Slic3r/GUI/Preset.pm | 3 ++ lib/Slic3r/GUI/PresetEditor.pm | 29 +++++++++--- 3 files changed, 68 insertions(+), 46 deletions(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index a5a410402..aa294ad54 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -766,50 +766,54 @@ sub selected_presets { sub show_preset_editor { my ($self, $group, $i) = @_; - my @presets = $self->selected_presets($group); + wxTheApp->CallAfter(sub { + my @presets = $self->selected_presets($group); - my $preset_editor; - my $dlg; - my $mainframe = $self->GetFrame; - my $tabpanel = $mainframe->{tabpanel}; - if (exists $mainframe->{preset_editor_tabs}{$group}) { - # we already have an open editor - $tabpanel->SetSelection($tabpanel->GetPageIndex($mainframe->{preset_editor_tabs}{$group})); - return; - } elsif ($Slic3r::GUI::Settings->{_}{tabbed_preset_editors}) { - my $class = "Slic3r::GUI::PresetEditor::" . ucfirst($group); - $mainframe->{preset_editor_tabs}{$group} = $preset_editor = $class->new($self->GetFrame); - $tabpanel->AddPage($preset_editor, ucfirst($group) . " Settings", 1); - } else { - my $class = "Slic3r::GUI::PresetEditorDialog::" . ucfirst($group); - $dlg = $class->new($self); - $preset_editor = $dlg->preset_editor; - } + my $preset_editor; + my $dlg; + my $mainframe = $self->GetFrame; + my $tabpanel = $mainframe->{tabpanel}; + if (exists $mainframe->{preset_editor_tabs}{$group}) { + # we already have an open editor + $tabpanel->SetSelection($tabpanel->GetPageIndex($mainframe->{preset_editor_tabs}{$group})); + return; + } elsif ($Slic3r::GUI::Settings->{_}{tabbed_preset_editors}) { + my $class = "Slic3r::GUI::PresetEditor::" . ucfirst($group); + $mainframe->{preset_editor_tabs}{$group} = $preset_editor = $class->new($self->GetFrame); + $tabpanel->AddPage($preset_editor, ucfirst($group) . " Settings", 1); + } else { + my $class = "Slic3r::GUI::PresetEditorDialog::" . ucfirst($group); + $dlg = $class->new($self); + $preset_editor = $dlg->preset_editor; + } - $preset_editor->select_preset_by_name($presets[$i // 0]->name); - $preset_editor->on_value_change(sub { - # Re-load the presets in order to toggle the (modified) suffix - $self->load_presets; + $preset_editor->select_preset_by_name($presets[$i // 0]->name); + $preset_editor->on_value_change(sub { + # Re-load the presets in order to toggle the (modified) suffix + $self->load_presets; - # Update shortcuts - $self->_on_select_preset($group); + # Update shortcuts + $self->_on_select_preset($group); - # Use the new config wherever we actually use its contents - $self->config_changed; + # Use the new config wherever we actually use its contents + $self->config_changed; + }); + my $cb = sub { + my ($group, $preset) = @_; + + # Re-load the presets as they might have changed. + $self->load_presets; + + # Select the preset in plater too + $self->select_preset_by_name($preset->name, $group, $i, 1); + }; + $preset_editor->on_select_preset($cb); + $preset_editor->on_save_preset($cb); + + if ($dlg) { + $dlg->ShowModal; + } }); - $preset_editor->on_select_preset(sub { - my ($group, $preset) = @_; - - # Re-load the presets as they might have changed. - $self->load_presets; - - # Select the preset in plater too - $self->select_preset_by_name($preset->name, $group, $i, 1); - }); - - if ($dlg) { - $dlg->ShowModal; - } } # Returns the current config by merging the selected presets and the overrides. diff --git a/lib/Slic3r/GUI/Preset.pm b/lib/Slic3r/GUI/Preset.pm index 2d0021937..0dfc33df8 100644 --- a/lib/Slic3r/GUI/Preset.pm +++ b/lib/Slic3r/GUI/Preset.pm @@ -140,6 +140,9 @@ sub save_as { $self->_config->clear; $self->_config->apply($self->_dirty_config); } + + # unlink the file first to avoid problems on case-insensitive file systems + unlink Slic3r::encode_path($self->file); $self->_config->save($self->file); wxTheApp->load_presets; diff --git a/lib/Slic3r/GUI/PresetEditor.pm b/lib/Slic3r/GUI/PresetEditor.pm index 788c98eed..8bd6e0db0 100644 --- a/lib/Slic3r/GUI/PresetEditor.pm +++ b/lib/Slic3r/GUI/PresetEditor.pm @@ -127,9 +127,16 @@ sub save_preset { $self->load_presets; $self->select_preset_by_name($preset->name); + $self->{on_save_preset}->($self->name, $preset) if $self->{on_save_preset}; + return 1; } +sub on_save_preset { + my ($self, $cb) = @_; + $self->{on_save_preset} = $cb; +} + sub on_value_change { my ($self, $cb) = @_; $self->{on_value_change} = $cb; @@ -141,10 +148,12 @@ sub on_value_change { sub _on_value_change { my ($self, $opt_key) = @_; - $self->current_preset->_dirty_config->apply($self->config); - $self->{on_value_change}->($opt_key) if $self->{on_value_change}; - $self->load_presets; - $self->_update; + wxTheApp->CallAfter(sub { + $self->current_preset->_dirty_config->apply($self->config); + $self->{on_value_change}->($opt_key) if $self->{on_value_change}; + $self->load_presets; + $self->_update; + }); } sub _update {} @@ -163,6 +172,10 @@ sub select_preset_by_name { my $presets = wxTheApp->presets->{$self->name}; my $i = first { $presets->[$_]->name eq $name } 0..$#$presets; + if (!defined $i) { + warn "No preset named $name"; + return 0; + } $self->{presets_choice}->SetSelection($i); $self->_on_select_preset($force); } @@ -190,9 +203,6 @@ sub _on_select_preset { # Get the selected name. my $preset = wxTheApp->presets->{$self->name}->[$self->{presets_choice}->GetSelection]; - # If selection didn't change, do nothing. - return if defined $self->current_preset && $preset->name eq $self->current_preset->name; - # If we have unsaved changes, prompt user. if (!$force && !$self->prompt_unsaved_changes) { # User decided not to save the current changes, so we restore the previous selection. @@ -204,6 +214,11 @@ sub _on_select_preset { $self->current_preset($preset); + # If selection didn't change, do nothing. + # Only after resetting current_preset because it might contain an older object of the + # current preset. + return if defined $self->current_preset && $preset->name eq $self->current_preset->name; + # We reload presets in order to remove the "(modified)" suffix in case user was # prompted and chose to discard changes. $self->load_presets;