Browse Source

Another step towards C++ presets.

bubnikv 7 years ago
parent
commit
ee645007f2

+ 3 - 2
lib/Slic3r.pm

@@ -50,8 +50,9 @@ warn "Running Slic3r under Perl 5.16 is neither supported nor recommended\n"
     if $^V == v5.16;
 
 use FindBin;
-# Path to the images.
-our $var = sub { decode_path($FindBin::Bin) . "/var/" . $_[0] };
+
+# Let the XS module know where the GUI resources reside.
+set_var_dir(decode_path($FindBin::Bin) . "/var");
 
 use Moo 1.003001;
 

+ 0 - 174
lib/Slic3r/Config.pm

@@ -111,16 +111,6 @@ sub load {
     }
 }
 
-# Deserialize a perl hash into the underlying C++ Slic3r::DynamicConfig class,
-# convert legacy configuration names.
-# Used to load a config bundle.
-sub load_ini_hash {
-    my ($class, $ini_hash) = @_;    
-    my $config = $class->new;
-    $config->set_deserialize($_, $ini_hash->{$_}) for keys %$ini_hash;
-    return $config;
-}
-
 sub clone {
     my $self = shift;
     my $new = (ref $self)->new;
@@ -135,170 +125,6 @@ sub get_value {
         : $self->get($opt_key);
 }
 
-# Create a hash of hashes from the underlying C++ Slic3r::DynamicPrintConfig.
-# The first hash key is '_' meaning no category.
-# Used to create a config bundle.
-sub as_ini {
-    my ($self) = @_;
-    my $ini = { _ => {} };
-    foreach my $opt_key (sort @{$self->get_keys}) {
-        next if $Options->{$opt_key}{shortcut};
-        $ini->{_}{$opt_key} = $self->serialize($opt_key);
-    }
-    return $ini;
-}
-
-# this method is idempotent by design and only applies to ::DynamicConfig or ::Full
-# objects because it performs cross checks
-sub validate {
-    my $self = shift;
-    
-    # -j, --threads
-    die "Invalid value for --threads\n"
-        if $self->threads < 1;
-
-    # --layer-height
-    die "Invalid value for --layer-height\n"
-        if $self->layer_height <= 0;
-    die "--layer-height must be a multiple of print resolution\n"
-        if $self->layer_height / &Slic3r::SCALING_FACTOR % 1 != 0;
-    
-    # --first-layer-height
-    die "Invalid value for --first-layer-height\n"
-        if $self->first_layer_height !~ /^(?:\d*(?:\.\d+)?)%?$/;
-    die "Invalid value for --first-layer-height\n"
-        if $self->get_value('first_layer_height') <= 0;
-    
-    # --filament-diameter
-    die "Invalid value for --filament-diameter\n"
-        if grep $_ < 1, @{$self->filament_diameter};
-    
-    # --nozzle-diameter
-    die "Invalid value for --nozzle-diameter\n"
-        if grep $_ < 0, @{$self->nozzle_diameter};
-    
-    # --perimeters
-    die "Invalid value for --perimeters\n"
-        if $self->perimeters < 0;
-    
-    # --solid-layers
-    die "Invalid value for --solid-layers\n" if defined $self->solid_layers && $self->solid_layers < 0;
-    die "Invalid value for --top-solid-layers\n"    if $self->top_solid_layers      < 0;
-    die "Invalid value for --bottom-solid-layers\n" if $self->bottom_solid_layers   < 0;
-    
-    # --gcode-flavor
-    die "Invalid value for --gcode-flavor\n"
-        if !first { $_ eq $self->gcode_flavor } @{$Options->{gcode_flavor}{values}};
-    
-    die "--use-firmware-retraction is only supported by Marlin, Smoothie, Repetier and Machinekit firmware\n"
-        if $self->use_firmware_retraction && $self->gcode_flavor ne 'smoothie' 
-        && $self->gcode_flavor ne 'reprap' 
-        && $self->gcode_flavor ne 'machinekit' 
-        && $self->gcode_flavor ne 'repetier';
-    
-    die "--use-firmware-retraction is not compatible with --wipe\n"
-        if $self->use_firmware_retraction && first {$_} @{$self->wipe};
-    
-    # --fill-pattern
-    die "Invalid value for --fill-pattern\n"
-        if !first { $_ eq $self->fill_pattern } @{$Options->{fill_pattern}{values}};
-    
-    # --external-fill-pattern
-    die "Invalid value for --external-fill-pattern\n"
-        if !first { $_ eq $self->external_fill_pattern } @{$Options->{external_fill_pattern}{values}};
-    
-    # --fill-density
-    die "The selected fill pattern is not supposed to work at 100% density\n"
-        if $self->fill_density == 100
-            && !first { $_ eq $self->fill_pattern } @{$Options->{external_fill_pattern}{values}};
-    
-    # --infill-every-layers
-    die "Invalid value for --infill-every-layers\n"
-        if $self->infill_every_layers !~ /^\d+$/ || $self->infill_every_layers < 1;
-    
-    # --skirt-height
-    die "Invalid value for --skirt-height\n"
-        if $self->skirt_height < -1;  # -1 means as tall as the object
-    
-    # --bridge-flow-ratio
-    die "Invalid value for --bridge-flow-ratio\n"
-        if $self->bridge_flow_ratio <= 0;
-    
-    # extruder clearance
-    die "Invalid value for --extruder-clearance-radius\n"
-        if $self->extruder_clearance_radius <= 0;
-    die "Invalid value for --extruder-clearance-height\n"
-        if $self->extruder_clearance_height <= 0;
-    
-    # --extrusion-multiplier
-    die "Invalid value for --extrusion-multiplier\n"
-        if defined first { $_ <= 0 } @{$self->extrusion_multiplier};
-    
-    # --default-acceleration
-    die "Invalid zero value for --default-acceleration when using other acceleration settings\n"
-        if ($self->perimeter_acceleration || $self->infill_acceleration || $self->bridge_acceleration || $self->first_layer_acceleration)
-            && !$self->default_acceleration;
-    
-    # --spiral-vase
-    if ($self->spiral_vase) {
-        # Note that we might want to have more than one perimeter on the bottom
-        # solid layers.
-        die "Can't make more than one perimeter when spiral vase mode is enabled\n"
-            if $self->perimeters > 1;
-        
-        die "Can't make less than one perimeter when spiral vase mode is enabled\n"
-            if $self->perimeters < 1;
-        
-        die "Spiral vase mode can only print hollow objects, so you need to set Fill density to 0\n"
-            if $self->fill_density > 0;
-        
-        die "Spiral vase mode is not compatible with top solid layers\n"
-            if $self->top_solid_layers > 0;
-        
-        die "Spiral vase mode is not compatible with support material\n"
-            if $self->support_material || $self->support_material_enforce_layers > 0;
-    }
-    
-    # extrusion widths
-    {
-        my $max_nozzle_diameter = max(@{ $self->nozzle_diameter });
-        die "Invalid extrusion width (too large)\n"
-            if defined first { $_ > 10 * $max_nozzle_diameter }
-                map $self->get_abs_value_over("${_}_extrusion_width", $max_nozzle_diameter),
-                qw(perimeter infill solid_infill top_infill support_material first_layer);
-    }
-    
-    # general validation, quick and dirty
-    foreach my $opt_key (@{$self->get_keys}) {
-        my $opt = $Options->{$opt_key};
-        next unless defined $self->$opt_key;
-        next unless defined $opt->{cli} && $opt->{cli} =~ /=(.+)$/;
-        my $type = $1;
-        my @values = ();
-        if ($type =~ s/\@$//) {
-            die "Invalid value for $opt_key\n" if ref($self->$opt_key) ne 'ARRAY';
-            @values = @{ $self->$opt_key };
-        } else {
-            @values = ($self->$opt_key);
-        }
-        foreach my $value (@values) {
-            if ($type eq 'i' || $type eq 'f' || $opt->{type} eq 'percent') {
-                $value =~ s/%$// if $opt->{type} eq 'percent';
-                die "Invalid value for $opt_key\n"
-                    if ($type eq 'i' && $value !~ /^-?\d+$/)
-                    || (($type eq 'f' || $opt->{type} eq 'percent') && $value !~ /^-?(?:\d+|\d*\.\d+)$/)
-                    || (defined $opt->{min} && $value < $opt->{min})
-                    || (defined $opt->{max} && $value > $opt->{max});
-            } elsif ($type eq 's' && $opt->{type} eq 'select') {
-                die "Invalid value for $opt_key\n"
-                    unless first { $_ eq $value } @{ $opt->{values} };
-            }
-        }
-    }
-    
-    return 1;
-}
-
 # CLASS METHODS:
 
 # Write a "Windows" style ini file with categories enclosed in squre brackets.

+ 27 - 73
lib/Slic3r/GUI.pm

@@ -52,7 +52,6 @@ use constant FILE_WILDCARDS => {
 };
 use constant MODEL_WILDCARD => join '|', @{&FILE_WILDCARDS}{qw(known stl obj amf prusa)};
 
-our $datadir;
 # If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden.
 our $no_controller;
 our $no_plater;
@@ -84,8 +83,6 @@ our $grey = Wx::Colour->new(200,200,200);
 
 #our $VERSION_CHECK_EVENT : shared = Wx::NewEventType;
 
-our $DLP_projection_screen;
-
 sub OnInit {
     my ($self) = @_;
     
@@ -95,17 +92,11 @@ sub OnInit {
     
     $self->{notifier} = Slic3r::GUI::Notifier->new;
     $self->{preset_bundle} = Slic3r::GUI::PresetBundle->new;
-
-    # locate or create data directory
-    # Unix: ~/.Slic3r
-    # Windows: "C:\Users\username\AppData\Roaming\Slic3r" or "C:\Documents and Settings\username\Application Data\Slic3r"
-    # Mac: "~/Library/Application Support/Slic3r"
-    $datadir ||= Wx::StandardPaths::Get->GetUserDataDir;
-    my $enc_datadir = Slic3r::encode_path($datadir);
-    Slic3r::debugf "Data directory: %s\n", $datadir;
     
-    # just checking for existence of $datadir is not enough: it may be an empty directory
+    # just checking for existence of Slic3r::data_dir is not enough: it may be an empty directory
     # supplied as argument to --datadir; in that case we should still run the wizard
+    my $enc_datadir = Slic3r::encode_path(Slic3r::data_dir);
+    Slic3r::debugf "Data directory: %s\n", $enc_datadir;
     my $run_wizard = (-d $enc_datadir && -e "$enc_datadir/slic3r.ini") ? 0 : 1;
     foreach my $dir ($enc_datadir, "$enc_datadir/print", "$enc_datadir/filament", "$enc_datadir/printer") {
         next if -d $dir;
@@ -119,7 +110,7 @@ sub OnInit {
     # load settings
     my $last_version;
     if (-f "$enc_datadir/slic3r.ini") {
-        my $ini = eval { Slic3r::Config->read_ini("$datadir/slic3r.ini") };
+        my $ini = eval { Slic3r::Config->read_ini(Slic3r::data_dir . "/slic3r.ini") };
         $Settings = $ini if $ini;
         $last_version = $Settings->{_}{version};
         $Settings->{_}{autocenter} //= 1;
@@ -131,6 +122,8 @@ sub OnInit {
     }
     $Settings->{_}{version} = $Slic3r::VERSION;
     $self->save_settings;
+
+    eval { $self->{preset_bundle}->load_presets(Slic3r::data_dir) };
     
     # application frame
     Wx::Image::AddHandler(Wx::PNGHandler->new);
@@ -142,20 +135,21 @@ sub OnInit {
     $self->SetTopWindow($frame);
     
     # load init bundle
-    {
-        my @dirs = ($FindBin::Bin);
-        if (&Wx::wxMAC) {
-            push @dirs, qw();
-        } elsif (&Wx::wxMSW) {
-            push @dirs, qw();
-        }
-        my $init_bundle = first { -e $_ } map "$_/.init_bundle.ini", @dirs;
-        if ($init_bundle) {
-            Slic3r::debugf "Loading config bundle from %s\n", $init_bundle;
-            $self->{mainframe}->load_configbundle($init_bundle, 1);
-            $run_wizard = 0;
-        }
-    }
+    #FIXME this is undocumented and the use case is unclear.
+#    {
+#        my @dirs = ($FindBin::Bin);
+#        if (&Wx::wxMAC) {
+#            push @dirs, qw();
+#        } elsif (&Wx::wxMSW) {
+#            push @dirs, qw();
+#        }
+#        my $init_bundle = first { -e $_ } map "$_/.init_bundle.ini", @dirs;
+#        if ($init_bundle) {
+#            Slic3r::debugf "Loading config bundle from %s\n", $init_bundle;
+#            $self->{mainframe}->load_configbundle($init_bundle, 1);
+#            $run_wizard = 0;
+#        }
+#    }
     
     if (!$run_wizard && (!defined $last_version || $last_version ne $Slic3r::VERSION)) {
         # user was running another Slic3r version on this computer
@@ -171,8 +165,10 @@ sub OnInit {
                 . "to Print Settings and click the \"Set\" button next to \"Bed Shape\".", "Bed Shape");
         }
     }
-    $self->{mainframe}->config_wizard if $run_wizard;
-    eval { $self->{preset_bundle}->load_presets($datadir) };
+    if ($run_wizard) {
+        $self->{mainframe}->config_wizard;
+        eval { $self->{preset_bundle}->load_presets(Slic3r::data_dir) };
+    }
     
 #    $self->check_version
 #        if $self->have_version_check
@@ -297,7 +293,7 @@ sub notify {
 
 sub save_settings {
     my ($self) = @_;
-    Slic3r::Config->write_ini("$datadir/slic3r.ini", $Settings);
+    Slic3r::Config->write_ini(Slic3r::data_dir . "/slic3r.ini", $Settings);
 }
 
 # Called after the Preferences dialog is closed and the program settings are saved.
@@ -307,48 +303,6 @@ sub update_ui_from_settings {
     $self->{mainframe}->update_ui_from_settings;
 }
 
-sub presets {
-    my ($self, $section) = @_;
-    
-    my %presets = ();
-    opendir my $dh, Slic3r::encode_path("$Slic3r::GUI::datadir/$section")
-        or die "Failed to read directory $Slic3r::GUI::datadir/$section (errno: $!)\n";
-    # Instead of using the /i modifier for case-insensitive matching, the case insensitivity is expressed
-    # explicitely to avoid having to bundle the UTF8 Perl library.
-    foreach my $file (grep /\.[iI][nN][iI]$/, readdir $dh) {
-        $file = Slic3r::decode_path($file);
-        my $name = basename($file);
-        $name =~ s/\.ini$//;
-        $presets{$name} = "$Slic3r::GUI::datadir/$section/$file";
-    }
-    closedir $dh;
-    
-    return %presets;
-}
-
-#sub have_version_check {
-#    my ($self) = @_;
-#    
-#    # return an explicit 0
-#    return ($Slic3r::have_threads && $Slic3r::build && $have_LWP) || 0;
-#}
-
-#sub check_version {
-#    my ($self, $manual_check) = @_;
-#    
-#    Slic3r::debugf "Checking for updates...\n";
-#    
-#    @_ = ();
-#    threads->create(sub {
-#        my $ua = LWP::UserAgent->new;
-#        $ua->timeout(10);
-#        my $response = $ua->get('http://slic3r.org/updatecheck');
-#        Wx::PostEvent($self, Wx::PlThreadEvent->new(-1, $VERSION_CHECK_EVENT,
-#            threads::shared::shared_clone([ $response->is_success, $response->decoded_content, $manual_check ])));
-#        Slic3r::thread_cleanup();
-#    })->detach;
-#}
-
 sub output_path {
     my ($self, $dir) = @_;
     
@@ -434,7 +388,7 @@ sub set_menu_item_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));
     }
 }
 

+ 1 - 1
lib/Slic3r/GUI/3DScene.pm

@@ -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);

+ 1 - 1
lib/Slic3r/GUI/AboutDialog.pm

@@ -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);

+ 4 - 4
lib/Slic3r/GUI/ConfigWizard.pm

@@ -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);

+ 9 - 10
lib/Slic3r/GUI/Controller.pm

@@ -32,21 +32,21 @@ 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 $presets = wxTheApp->{preset_bundle}->printer->presets_hash;
             
             # remove printers that already exist
             my @panels = $self->print_panels;
-            delete $presets{$_} for map $_->printer_name, @panels;
+            delete $presets->{$_} for map $_->printer_name, @panels;
             
-            foreach my $preset_name (sort keys %presets) {
-                my $config = Slic3r::Config->load($presets{$preset_name});
+            foreach my $preset_name (sort keys %{$presets}) {
+                my $config = Slic3r::Config->load($presets->{$preset_name});
                 next if !$config->serial_port;
                 
                 my $id = &Wx::NewId();
@@ -100,9 +100,9 @@ sub OnActivate {
     # 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 $all = wxTheApp->{preset_bundle}->printer->presets_hash;
+        my %configs = map { my $name = $_; $name => Slic3r::Config->load($all->{$name}) } keys %{$all};
+        %presets = map { $_ => $configs{$_} } grep $configs{$_}->serial_port, keys %{$all};
     }
     
     # decide which ones we want to keep
@@ -183,8 +183,7 @@ sub print_panels {
 #       Slic3r::GUI::Tab::Printer::_on_presets_changed
 # when the presets are loaded or the user select another preset.
 sub update_presets {
-    my $self = shift;
-    my ($group, $presets, $default_suppressed, $selected, $is_dirty) = @_;
+    my ($self, $group, $presets, $default_suppressed, $selected, $is_dirty) = @_;
     
     # update configs of currently loaded print panels
     foreach my $panel ($self->print_panels) {

+ 1 - 1
lib/Slic3r/GUI/Controller/ManualControlDialog.pm

@@ -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);

+ 13 - 13
lib/Slic3r/GUI/Controller/PrinterPanel.pm

@@ -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 {
@@ -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 {

+ 23 - 78
lib/Slic3r/GUI/MainFrame.pm

@@ -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
@@ -22,12 +23,12 @@ sub new {
     
     my $self = $class->SUPER::new(undef, -1, $Slic3r::FORK_NAME . ' - ' . $Slic3r::VERSION, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE);
     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
@@ -112,7 +113,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,7 +127,7 @@ 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);
+                $self->{plater}->on_config_change($tab->{presets}->get_current_preset->config);
                 if ($self->{controller}) {
                     $self->{controller}->update_presets($tab_name, @_);
                 }
@@ -143,7 +144,7 @@ sub _init_tabpanel {
         });
         
         # load initial config
-        $self->{plater}->on_config_change($self->config);
+        $self->{plater}->on_config_change(wxTheApp->{preset_bundle}->full_config);
     }
 }
 
@@ -495,7 +496,7 @@ sub repair_stl {
 sub extra_variables {
     my $self = shift;
     my %extra_variables = ();
-    $extra_variables{"${_}_preset"} = $self->{options_tabs}{$_}->get_current_preset->name
+    $extra_variables{"${_}_preset"} = wxTheApp->{preset_bundle}->{$_}->get_current_preset_name
         for qw(print filament printer);
     return { %extra_variables };
 }
@@ -569,9 +570,9 @@ sub export_configbundle {
         $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});
+            my $presets = wxTheApp->{preset_bundle}->$section->presets_hash;
+            foreach my $preset_name (keys %{$presets}) {
+                my $config = Slic3r::Config->load($presets->{$preset_name});
                 $ini->{"$section:$preset_name"} = $config->as_ini->{_};
             }
         }
@@ -616,15 +617,15 @@ sub load_configbundle {
         next if $skip_no_id && !$config->get($section . "_settings_id");
         
         {
-            my %current_presets = Slic3r::GUI->presets($section);
+            my $current_presets = wxTheApp->{preset_bundle}->$section->presets_hash;
             my %current_ids = map { $_ => 1 }
                 grep $_,
                 map Slic3r::Config->load($_)->get($section . "_settings_id"),
-                values %current_presets;
+                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);
+        $config->save(sprintf Slic3r::data_dir . "/%s/%s.ini", $section, $preset_name);
         Slic3r::debugf "Imported %s preset %s\n", $section, $preset_name;
         $imported++;
     }
@@ -658,7 +659,8 @@ sub config_wizard {
     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;
+            # Select the first visible preset.
+            $tab->select_preset(undef);
         }
         $self->load_config($config);
         for my $tab (values %{$self->{options_tabs}}) {
@@ -667,84 +669,27 @@ sub config_wizard {
     }
 }
 
-=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,
+    return map $self->{options_tabs}{filament}->{presets}->preset($_)->name,
         $self->{plater}->filament_presets;
 }
 
+# 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;
@@ -779,7 +724,7 @@ sub _set_menu_item_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));
     }
 }
 

Some files were not shown because too many files changed in this diff