2011-10-03 09:55:32 +00:00
package Slic3r::GUI::SkeinPanel ;
use strict ;
use warnings ;
2011-10-03 11:08:43 +00:00
use utf8 ;
2011-10-03 09:55:32 +00:00
2011-12-09 13:07:50 +00:00
use File::Basename qw( basename dirname ) ;
2012-04-11 13:58:09 +00:00
use Slic3r::Geometry qw( X Y ) ;
2012-02-05 15:43:44 +00:00
use Wx qw( :sizer :progressdialog wxOK wxICON_INFORMATION wxICON_WARNING wxICON_ERROR wxICON_QUESTION
wxOK wxCANCEL wxID_OK wxFD_OPEN wxFD_SAVE wxDEFAULT wxNORMAL ) ;
2011-10-03 09:55:32 +00:00
use Wx::Event qw( EVT_BUTTON ) ;
use base 'Wx::Panel' ;
2012-02-03 18:57:49 +00:00
my $ last_skein_dir ;
my $ last_config_dir ;
2012-03-12 17:52:23 +00:00
my $ last_input_file ;
my $ last_output_file ;
2011-12-26 18:45:01 +00:00
our $ last_config ;
2011-12-09 13:07:50 +00:00
2011-10-03 09:55:32 +00:00
sub new {
my $ class = shift ;
my ( $ parent ) = @ _ ;
my $ self = $ class - > SUPER:: new ( $ parent , - 1 ) ;
my % panels = (
2011-11-13 21:22:34 +00:00
printer = > {
2011-10-03 09:55:32 +00:00
title = > 'Printer' ,
2012-03-03 20:37:10 +00:00
options = > [ qw( nozzle_diameter print_center z_offset gcode_flavor use_relative_e_distances ) ] ,
2011-11-13 21:22:34 +00:00
} ,
filament = > {
2011-10-03 09:55:32 +00:00
title = > 'Filament' ,
2012-03-03 22:14:40 +00:00
options = > [ qw( filament_diameter extrusion_multiplier temperature first_layer_temperature bed_temperature first_layer_bed_temperature ) ] ,
2011-11-13 21:22:34 +00:00
} ,
2011-11-28 18:11:26 +00:00
print_speed = > {
title = > 'Print speed' ,
2011-12-04 19:50:03 +00:00
options = > [ qw( perimeter_speed small_perimeter_speed infill_speed solid_infill_speed bridge_speed ) ] ,
2011-11-28 18:11:26 +00:00
} ,
2011-11-13 21:22:34 +00:00
speed = > {
2011-11-28 18:11:26 +00:00
title = > 'Other speed settings' ,
2011-12-01 21:03:13 +00:00
options = > [ qw( travel_speed bottom_layer_speed_ratio ) ] ,
2011-11-13 21:22:34 +00:00
} ,
accuracy = > {
2011-10-03 09:55:32 +00:00
title = > 'Accuracy' ,
2011-12-04 18:17:42 +00:00
options = > [ qw( layer_height first_layer_height_ratio infill_every_layers ) ] ,
2011-11-13 21:22:34 +00:00
} ,
print = > {
2011-10-03 09:55:32 +00:00
title = > 'Print settings' ,
2012-02-19 16:02:49 +00:00
options = > [ qw( perimeters solid_layers fill_density fill_angle fill_pattern solid_fill_pattern support_material support_material_tool ) ] ,
2011-11-13 21:22:34 +00:00
} ,
retract = > {
2011-10-03 09:55:32 +00:00
title = > 'Retraction' ,
2011-11-07 14:58:47 +00:00
options = > [ qw( retract_length retract_lift retract_speed retract_restart_extra retract_before_travel ) ] ,
2011-11-13 21:22:34 +00:00
} ,
2012-02-25 20:01:00 +00:00
cooling = > {
title = > 'Cooling' ,
2012-03-03 21:21:30 +00:00
options = > [ qw( cooling min_fan_speed max_fan_speed bridge_fan_speed fan_below_layer_time slowdown_below_layer_time min_print_speed disable_fan_first_layers fan_always_on ) ] ,
2012-02-25 20:01:00 +00:00
label_width = > 300 ,
} ,
2011-11-13 21:22:34 +00:00
skirt = > {
2011-10-03 09:55:32 +00:00
title = > 'Skirt' ,
2011-11-13 17:41:12 +00:00
options = > [ qw( skirts skirt_distance skirt_height ) ] ,
2011-11-13 21:22:34 +00:00
} ,
transform = > {
2011-10-03 09:55:32 +00:00
title = > 'Transform' ,
2012-04-11 14:30:58 +00:00
options = > [ qw( scale rotate duplicate bed_size duplicate_grid duplicate_distance ) ] ,
2011-11-13 21:22:34 +00:00
} ,
2011-11-13 21:48:21 +00:00
gcode = > {
2012-03-26 20:33:43 +00:00
title = > 'Custom G-code' ,
2012-03-26 10:14:15 +00:00
options = > [ qw( start_gcode end_gcode layer_gcode gcode_comments post_process ) ] ,
2011-11-13 21:48:21 +00:00
} ,
2011-11-25 09:58:13 +00:00
extrusion = > {
title = > 'Extrusion' ,
2012-01-30 13:51:05 +00:00
options = > [ qw( extrusion_width_ratio bridge_flow_ratio ) ] ,
2011-11-25 09:58:13 +00:00
} ,
2011-12-26 09:20:45 +00:00
output = > {
title = > 'Output' ,
options = > [ qw( output_filename_format ) ] ,
} ,
2012-02-05 19:55:17 +00:00
notes = > {
title = > 'Notes' ,
options = > [ qw( notes ) ] ,
} ,
2011-10-03 09:55:32 +00:00
) ;
2011-10-05 16:13:47 +00:00
$ self - > { panels } = \ % panels ;
2012-02-02 23:30:35 +00:00
if ( eval "use Growl::GNTP; 1" ) {
# register growl notifications
2012-02-26 18:29:25 +00:00
eval {
2012-04-07 18:45:02 +00:00
$ self - > { growler } = Growl::GNTP - > new ( AppName = > 'Slic3r' , AppIcon = > "$FindBin::Bin/var/icon.png" ) ;
2012-02-26 18:29:25 +00:00
$ self - > { growler } - > register ( [ { Name = > 'SKEIN_DONE' , DisplayName = > 'Slicing Done' } ] ) ;
} ;
2012-02-02 23:30:35 +00:00
}
2011-10-03 09:55:32 +00:00
2011-11-13 21:22:34 +00:00
my $ tabpanel = Wx::Notebook - > new ( $ self , - 1 , Wx:: wxDefaultPosition , Wx:: wxDefaultSize , & Wx:: wxNB_TOP ) ;
my $ make_tab = sub {
my @ cols = @ _ ;
my $ tab = Wx::Panel - > new ( $ tabpanel , - 1 ) ;
my $ sizer = Wx::BoxSizer - > new ( wxHORIZONTAL ) ;
foreach my $ col ( @ cols ) {
my $ vertical_sizer = Wx::BoxSizer - > new ( wxVERTICAL ) ;
for my $ optgroup ( @$ col ) {
my $ optpanel = Slic3r::GUI::OptionsGroup - > new ( $ tab , % { $ panels { $ optgroup } } ) ;
$ vertical_sizer - > Add ( $ optpanel , 0 , wxEXPAND | wxALL , 10 ) ;
}
$ sizer - > Add ( $ vertical_sizer ) ;
}
$ tab - > SetSizer ( $ sizer ) ;
return $ tab ;
} ;
2011-10-03 09:55:32 +00:00
2011-11-25 09:58:13 +00:00
my @ tabs = (
$ make_tab - > ( [ qw( transform accuracy skirt ) ] , [ qw( print retract ) ] ) ,
2012-02-25 20:01:00 +00:00
$ make_tab - > ( [ qw( cooling ) ] ) ,
2012-02-19 11:27:44 +00:00
$ make_tab - > ( [ qw( printer filament ) ] , [ qw( print_speed speed ) ] ) ,
2011-11-25 09:58:13 +00:00
$ make_tab - > ( [ qw( gcode ) ] ) ,
2012-03-03 21:50:08 +00:00
$ make_tab - > ( [ qw( notes ) ] ) ,
$ make_tab - > ( [ qw( extrusion ) ] , [ qw( output ) ] ) ,
2011-11-25 09:58:13 +00:00
) ;
2011-10-03 09:55:32 +00:00
2012-03-03 21:50:08 +00:00
$ tabpanel - > AddPage ( $ tabs [ 0 ] , "Print Settings" ) ;
2012-02-25 20:01:00 +00:00
$ tabpanel - > AddPage ( $ tabs [ 1 ] , "Cooling" ) ;
2012-03-03 20:25:26 +00:00
$ tabpanel - > AddPage ( $ tabs [ 2 ] , "Printer and Filament" ) ;
2012-03-26 20:33:43 +00:00
$ tabpanel - > AddPage ( $ tabs [ 3 ] , "Custom G-code" ) ;
2012-03-03 21:50:08 +00:00
$ tabpanel - > AddPage ( $ tabs [ 4 ] , "Notes" ) ;
$ tabpanel - > AddPage ( $ tabs [ 5 ] , "Advanced" ) ;
2011-11-13 21:22:34 +00:00
my $ buttons_sizer ;
2011-10-05 16:13:47 +00:00
{
2011-11-13 21:22:34 +00:00
$ buttons_sizer = Wx::BoxSizer - > new ( wxHORIZONTAL ) ;
2012-03-03 21:50:08 +00:00
my $ slice_button = Wx::Button - > new ( $ self , - 1 , "Slice..." ) ;
$ slice_button - > SetDefault ( ) ;
2012-03-03 21:53:12 +00:00
$ buttons_sizer - > Add ( $ slice_button , 0 , wxRIGHT , 20 ) ;
2012-03-03 21:50:08 +00:00
EVT_BUTTON ( $ self , $ slice_button , sub { $ self - > do_slice } ) ;
2011-10-05 16:13:47 +00:00
2012-03-03 21:53:12 +00:00
my $ save_button = Wx::Button - > new ( $ self , - 1 , "Save config..." ) ;
2012-03-03 21:50:08 +00:00
$ buttons_sizer - > Add ( $ save_button , 0 ) ;
2011-12-22 16:38:37 +00:00
EVT_BUTTON ( $ self , $ save_button , sub { $ self - > save_config } ) ;
2011-10-05 16:13:47 +00:00
2012-03-03 21:53:12 +00:00
my $ load_button = Wx::Button - > new ( $ self , - 1 , "Load config..." ) ;
2012-03-03 21:50:08 +00:00
$ buttons_sizer - > Add ( $ load_button , 0 ) ;
2011-12-22 16:38:37 +00:00
EVT_BUTTON ( $ self , $ load_button , sub { $ self - > load_config } ) ;
2011-10-05 16:13:47 +00:00
2012-03-03 21:50:08 +00:00
my $ text = Wx::StaticText - > new ( $ self , - 1 , "Remember to check for updates at http://slic3r.org/\nVersion: $Slic3r::VERSION" , Wx:: wxDefaultPosition , Wx:: wxDefaultSize , wxALIGN_RIGHT ) ;
2011-10-05 16:13:47 +00:00
my $ font = Wx::Font - > new ( 10 , wxDEFAULT , wxNORMAL , wxNORMAL ) ;
2012-03-03 21:50:08 +00:00
$ text - > SetFont ( $ font ) ;
$ buttons_sizer - > Add ( $ text , 1 , wxEXPAND | wxALIGN_RIGHT ) ;
2011-10-03 09:55:32 +00:00
}
2011-10-05 16:13:47 +00:00
my $ sizer = Wx::BoxSizer - > new ( wxVERTICAL ) ;
2012-03-03 21:50:08 +00:00
$ sizer - > Add ( $ buttons_sizer , 0 , wxEXPAND | wxALL , 10 ) ;
2011-11-13 21:22:34 +00:00
$ sizer - > Add ( $ tabpanel ) ;
2011-10-05 16:13:47 +00:00
2011-10-03 09:55:32 +00:00
$ sizer - > SetSizeHints ( $ self ) ;
$ self - > SetSizer ( $ sizer ) ;
2011-10-03 11:08:43 +00:00
$ self - > Layout ;
2011-10-03 09:55:32 +00:00
return $ self ;
}
2012-02-19 14:14:54 +00:00
my $ model_wildcard = "STL files (*.stl)|*.stl;*.STL|AMF files (*.amf)|*.amf;*.AMF;*.xml;*.XML" ;
2011-12-22 16:38:37 +00:00
my $ ini_wildcard = "INI files *.ini|*.ini;*.INI" ;
2012-03-26 20:33:43 +00:00
my $ gcode_wildcard = "G-code files *.gcode|*.gcode;*.GCODE" ;
2011-12-22 16:38:37 +00:00
2011-10-03 09:55:32 +00:00
sub do_slice {
my $ self = shift ;
2011-12-22 16:38:37 +00:00
my % params = @ _ ;
2011-10-03 09:55:32 +00:00
2011-10-03 15:41:45 +00:00
my $ process_dialog ;
2011-10-03 09:55:32 +00:00
eval {
# validate configuration
Slic3r::Config - > validate ;
2012-02-05 15:43:44 +00:00
# confirm slicing of more than one copies
2012-04-11 13:58:09 +00:00
my $ copies = $ Slic3r:: duplicate_grid - > [ X ] * $ Slic3r:: duplicate_grid - > [ Y ] ;
$ copies = $ Slic3r:: duplicate if $ Slic3r:: duplicate > 1 ;
2012-02-05 15:43:44 +00:00
if ( $ copies > 1 ) {
my $ confirmation = Wx::MessageDialog - > new ( $ self , "Are you sure you want to slice $copies copies?" ,
'Confirm' , wxICON_QUESTION | wxOK | wxCANCEL ) ;
return unless $ confirmation - > ShowModal == wxID_OK ;
}
2011-10-03 09:55:32 +00:00
# select input file
2012-02-03 19:22:45 +00:00
my $ dir = $ last_skein_dir || $ last_config_dir || "" ;
2012-03-12 17:52:23 +00:00
my $ input_file ;
if ( ! $ params { reslice } ) {
my $ dialog = Wx::FileDialog - > new ( $ self , 'Choose a STL or AMF file to slice:' , $ dir , "" , $ model_wildcard , wxFD_OPEN ) ;
return unless $ dialog - > ShowModal == wxID_OK ;
$ input_file = $ dialog - > GetPaths ;
$ last_input_file = $ input_file ;
} else {
if ( ! defined $ last_input_file ) {
Wx::MessageDialog - > new ( $ self , "No previously sliced file" ,
'Confirm' , wxICON_ERROR | wxOK ) - > ShowModal ( ) ;
return ;
}
if ( ! - e $ last_input_file ) {
Wx::MessageDialog - > new ( $ self , "Cannot find previously sliced file!" ,
'Confirm' , wxICON_ERROR | wxOK ) - > ShowModal ( ) ;
return ;
}
$ input_file = $ last_input_file ;
}
2011-10-03 09:55:32 +00:00
my $ input_file_basename = basename ( $ input_file ) ;
2012-02-03 18:57:49 +00:00
$ last_skein_dir = dirname ( $ input_file ) ;
2011-10-03 09:55:32 +00:00
2011-12-26 09:20:45 +00:00
my $ skein = Slic3r::Skein - > new (
input_file = > $ input_file ,
2011-12-26 16:20:26 +00:00
output_file = > $ main:: opt { output } ,
2011-12-26 09:20:45 +00:00
status_cb = > sub {
my ( $ percent , $ message ) = @ _ ;
if ( & Wx:: wxVERSION_STRING =~ / 2\.(8\.|9\.[2-9])/ ) {
2012-02-20 11:50:05 +00:00
$ process_dialog - > Update ( $ percent , "$message..." ) ;
2011-12-26 09:20:45 +00:00
}
} ,
) ;
2011-12-22 16:38:37 +00:00
# select output file
2012-03-12 17:52:23 +00:00
if ( $ params { reslice } ) {
if ( defined $ last_output_file ) {
$ skein - > output_file ( $ last_output_file ) ;
}
} elsif ( $ params { save_as } ) {
2011-12-26 16:20:26 +00:00
my $ output_file = $ skein - > expanded_output_filepath ;
2012-03-26 15:57:54 +00:00
$ output_file =~ s/\.gcode$/.svg/i if $ params { export_svg } ;
my $ dlg = Wx::FileDialog - > new ( $ self , 'Save ' . ( $ params { export_svg } ? 'SVG' : 'G-code' ) . ' file as:' , dirname ( $ output_file ) ,
2011-12-22 16:38:37 +00:00
basename ( $ output_file ) , $ gcode_wildcard , wxFD_SAVE ) ;
return if $ dlg - > ShowModal != wxID_OK ;
2011-12-26 09:20:45 +00:00
$ skein - > output_file ( $ dlg - > GetPath ) ;
2012-03-12 17:52:23 +00:00
$ last_output_file = $ dlg - > GetPath ;
2011-12-22 16:38:37 +00:00
}
2011-10-03 09:55:32 +00:00
# show processbar dialog
2011-10-03 15:41:45 +00:00
$ process_dialog = Wx::ProgressDialog - > new ( 'Slicing...' , "Processing $input_file_basename..." ,
2012-02-05 13:23:15 +00:00
100 , $ self , 0 ) ;
2011-10-03 09:55:32 +00:00
$ process_dialog - > Pulse ;
2011-11-26 15:52:10 +00:00
2011-11-27 10:40:03 +00:00
{
2011-12-18 12:43:31 +00:00
my @ warnings = ( ) ;
local $ SIG { __WARN__ } = sub { push @ warnings , $ _ [ 0 ] } ;
2012-03-26 15:57:54 +00:00
if ( $ params { export_svg } ) {
$ skein - > export_svg ;
} else {
$ skein - > go ;
}
2011-12-18 12:43:31 +00:00
$ self - > catch_warning - > ( $ _ ) for @ warnings ;
2011-11-27 10:40:03 +00:00
}
2011-10-03 09:55:32 +00:00
$ process_dialog - > Destroy ;
2011-10-03 15:41:45 +00:00
undef $ process_dialog ;
2011-10-03 09:55:32 +00:00
2012-03-26 15:57:54 +00:00
my $ message = "$input_file_basename was successfully sliced" ;
$ message . = sprintf " in %d minutes and %.3f seconds" ,
int ( $ skein - > processing_time / 60 ) ,
$ skein - > processing_time - int ( $ skein - > processing_time / 60 ) * 60
if $ skein - > processing_time ;
$ message . = "." ;
2012-02-26 18:44:07 +00:00
eval {
$ self - > { growler } - > notify ( Event = > 'SKEIN_DONE' , Title = > 'Slicing Done!' , Message = > $ message )
if ( $ self - > { growler } ) ;
} ;
2012-02-16 21:52:57 +00:00
Wx::MessageDialog - > new ( $ self , $ message , 'Done!' ,
wxOK | wxICON_INFORMATION ) - > ShowModal ;
2011-10-03 09:55:32 +00:00
} ;
2011-10-05 16:13:47 +00:00
$ self - > catch_error ( sub { $ process_dialog - > Destroy if $ process_dialog } ) ;
}
sub save_config {
my $ self = shift ;
2012-02-06 15:52:11 +00:00
my $ process_dialog ;
eval {
# validate configuration
Slic3r::Config - > validate ;
} ;
$ self - > catch_error ( sub { $ process_dialog - > Destroy if $ process_dialog } ) and return ;
2012-02-03 19:22:45 +00:00
my $ dir = $ last_config ? dirname ( $ last_config ) : $ last_config_dir || $ last_skein_dir || "" ;
2011-12-26 18:06:57 +00:00
my $ filename = $ last_config ? basename ( $ last_config ) : "config.ini" ;
my $ dlg = Wx::FileDialog - > new ( $ self , 'Save configuration as:' , $ dir , $ filename ,
2011-10-05 16:13:47 +00:00
$ ini_wildcard , wxFD_SAVE ) ;
if ( $ dlg - > ShowModal == wxID_OK ) {
2011-12-09 13:07:50 +00:00
my $ file = $ dlg - > GetPath ;
2012-02-03 18:57:49 +00:00
$ last_config_dir = dirname ( $ file ) ;
2011-12-26 18:06:57 +00:00
$ last_config = $ file ;
2011-12-09 13:07:50 +00:00
Slic3r::Config - > save ( $ file ) ;
2011-10-05 16:13:47 +00:00
}
}
sub load_config {
my $ self = shift ;
2011-10-03 09:55:32 +00:00
2012-02-03 19:22:45 +00:00
my $ dir = $ last_config ? dirname ( $ last_config ) : $ last_config_dir || $ last_skein_dir || "" ;
2012-02-03 18:57:49 +00:00
my $ dlg = Wx::FileDialog - > new ( $ self , 'Select configuration to load:' , $ dir , "config.ini" ,
2011-10-05 16:13:47 +00:00
$ ini_wildcard , wxFD_OPEN ) ;
if ( $ dlg - > ShowModal == wxID_OK ) {
my ( $ file ) = $ dlg - > GetPaths ;
2012-02-03 18:57:49 +00:00
$ last_config_dir = dirname ( $ file ) ;
2011-12-26 18:06:57 +00:00
$ last_config = $ file ;
2011-10-05 16:13:47 +00:00
eval {
2011-12-10 09:39:07 +00:00
local $ SIG { __WARN__ } = $ self - > catch_warning ;
2011-10-05 16:13:47 +00:00
Slic3r::Config - > load ( $ file ) ;
} ;
$ self - > catch_error ( ) ;
$ _ - > ( ) for @ Slic3r:: GUI:: OptionsGroup:: reload_callbacks ;
}
}
sub catch_error {
my ( $ self , $ cb ) = @ _ ;
2011-10-03 09:55:32 +00:00
if ( my $ err = $@ ) {
2011-10-05 16:13:47 +00:00
$ cb - > ( ) if $ cb ;
2011-10-03 09:55:32 +00:00
Wx::MessageDialog - > new ( $ self , $ err , 'Error' , wxOK | wxICON_ERROR ) - > ShowModal ;
2012-02-06 15:52:11 +00:00
return 1 ;
2011-10-03 09:55:32 +00:00
}
2012-02-06 15:52:11 +00:00
return 0 ;
2011-10-03 09:55:32 +00:00
}
2011-12-10 09:39:07 +00:00
sub catch_warning {
my ( $ self ) = @ _ ;
return sub {
my $ message = shift ;
Wx::MessageDialog - > new ( $ self , $ message , 'Warning' , wxOK | wxICON_WARNING ) - > ShowModal ;
} ;
} ;
2011-10-03 09:55:32 +00:00
1 ;