mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	Refactoring: new Slic3r::Print::Simple class for non-interactive slicing (used in CLI and Quick Slice)
This commit is contained in:
		
							parent
							
								
									5bf0942f45
								
							
						
					
					
						commit
						385e0e0974
					
				
					 5 changed files with 151 additions and 88 deletions
				
			
		|  | @ -68,6 +68,7 @@ use Slic3r::Polyline; | |||
| use Slic3r::Print; | ||||
| use Slic3r::Print::Object; | ||||
| use Slic3r::Print::Region; | ||||
| use Slic3r::Print::Simple; | ||||
| use Slic3r::Print::SupportMaterial; | ||||
| use Slic3r::Surface; | ||||
| use Slic3r::TriangleMesh; | ||||
|  |  | |||
|  | @ -88,25 +88,15 @@ sub quick_slice { | |||
|     my $self = shift; | ||||
|     my %params = @_; | ||||
|      | ||||
|     my $process_dialog; | ||||
|     my $progress_dialog; | ||||
|     eval { | ||||
|         # validate configuration | ||||
|         my $config = $self->config; | ||||
|         $config->validate; | ||||
|          | ||||
|         # confirm slicing of more than one copies | ||||
|         my $copies = $config->duplicate_grid->[X] * $config->duplicate_grid->[Y]; | ||||
|         $copies = $config->duplicate if $config->duplicate > 1; | ||||
|         if ($copies > 1) { | ||||
|             my $confirmation = Wx::MessageDialog->new($self, "Are you sure you want to slice $copies copies?", | ||||
|                                                       'Multiple Copies', wxICON_QUESTION | wxOK | wxCANCEL); | ||||
|             return unless $confirmation->ShowModal == wxID_OK; | ||||
|         } | ||||
|          | ||||
|         # select input file | ||||
|         my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || ''; | ||||
| 
 | ||||
|         my $input_file; | ||||
|         my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || ''; | ||||
|         if (!$params{reslice}) { | ||||
|             my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF):', $dir, "", MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST); | ||||
|             if ($dialog->ShowModal != wxID_OK) { | ||||
|  | @ -133,31 +123,23 @@ sub quick_slice { | |||
|         $Slic3r::GUI::Settings->{recent}{skein_directory} = dirname($input_file); | ||||
|         Slic3r::GUI->save_settings; | ||||
|          | ||||
|         my $print = $self->init_print; | ||||
|         my $model = eval { Slic3r::Model->read_from_file($input_file) }; | ||||
|         Slic3r::GUI::show_error($self, $@) if $@; | ||||
|         my $sprint = Slic3r::Print::Simple->new( | ||||
|             status_cb       => sub { | ||||
|                 my ($percent, $message) = @_; | ||||
|                 return if &Wx::wxVERSION_STRING !~ / 2\.(8\.|9\.[2-9])/; | ||||
|                 $progress_dialog->Update($percent, "$message…"); | ||||
|             }, | ||||
|         ); | ||||
|          | ||||
|         if ($model->has_objects_with_no_instances) { | ||||
|             # apply a default position to all objects not having one | ||||
|             foreach my $object (@{$model->objects}) { | ||||
|                 $object->add_instance(offset => [0,0]) if !defined $object->instances; | ||||
|             } | ||||
|             $model->arrange_objects($config->min_object_distance); | ||||
|         } | ||||
|         $model->center_instances_around_point($config->print_center); | ||||
|          | ||||
|         foreach my $model_object (@{$model->objects}) { | ||||
|             $print->auto_assign_extruders($model_object); | ||||
|             $print->add_model_object($model_object); | ||||
|         } | ||||
|         $print->validate; | ||||
|         $sprint->apply_config($config); | ||||
|         $sprint->set_model(Slic3r::Model->read_from_file($input_file)); | ||||
|          | ||||
|         # select output file | ||||
|         my $output_file = $main::opt{output}; | ||||
|         my $output_file; | ||||
|         if ($params{reslice}) { | ||||
|             $output_file = $last_output_file if defined $last_output_file; | ||||
|         } elsif ($params{save_as}) { | ||||
|             $output_file = $print->expanded_output_filepath($output_file); | ||||
|             $output_file = $sprint->expanded_output_filepath; | ||||
|             $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:', | ||||
|                 Slic3r::GUI->output_path(dirname($output_file)), | ||||
|  | @ -174,40 +156,32 @@ sub quick_slice { | |||
|         } | ||||
|          | ||||
|         # show processbar dialog | ||||
|         $process_dialog = Wx::ProgressDialog->new('Slicing…', "Processing $input_file_basename…",  | ||||
|         $progress_dialog = Wx::ProgressDialog->new('Slicing…', "Processing $input_file_basename…",  | ||||
|             100, $self, 0); | ||||
|         $process_dialog->Pulse; | ||||
|         $progress_dialog->Pulse; | ||||
|          | ||||
|         { | ||||
|             my @warnings = (); | ||||
|             local $SIG{__WARN__} = sub { push @warnings, $_[0] }; | ||||
|             my %export_params = ( | ||||
|                 output_file => $output_file, | ||||
|             ); | ||||
|             $print->status_cb(sub { | ||||
|                 my ($percent, $message) = @_; | ||||
|                 if (&Wx::wxVERSION_STRING =~ / 2\.(8\.|9\.[2-9])/) { | ||||
|                     $process_dialog->Update($percent, "$message…"); | ||||
|                 } | ||||
|             }); | ||||
|              | ||||
|             $sprint->output_file($output_file); | ||||
|             if ($params{export_svg}) { | ||||
|                 $print->export_svg(%export_params); | ||||
|                 $sprint->export_svg; | ||||
|             } else { | ||||
|                 $print->process; | ||||
|                 $print->export_gcode(%export_params); | ||||
|                 $sprint->export_gcode; | ||||
|             } | ||||
|             $print->status_cb(undef); | ||||
|             $sprint->status_cb(undef); | ||||
|             Slic3r::GUI::warning_catcher($self)->($_) for @warnings; | ||||
|         } | ||||
|         $process_dialog->Destroy; | ||||
|         undef $process_dialog; | ||||
|         $progress_dialog->Destroy; | ||||
|         undef $progress_dialog; | ||||
|          | ||||
|         my $message = "$input_file_basename was successfully sliced."; | ||||
|         &Wx::wxTheApp->notify($message); | ||||
|         Wx::MessageDialog->new($self, $message, 'Slicing Done!',  | ||||
|             wxOK | wxICON_INFORMATION)->ShowModal; | ||||
|     }; | ||||
|     Slic3r::GUI::catch_error($self, sub { $process_dialog->Destroy if $process_dialog }); | ||||
|     Slic3r::GUI::catch_error($self, sub { $progress_dialog->Destroy if $progress_dialog }); | ||||
| } | ||||
| 
 | ||||
| sub repair_stl { | ||||
|  |  | |||
							
								
								
									
										112
									
								
								lib/Slic3r/Print/Simple.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								lib/Slic3r/Print/Simple.pm
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| package Slic3r::Print::Simple; | ||||
| use Moo; | ||||
| 
 | ||||
| use Slic3r::Geometry qw(X Y); | ||||
| 
 | ||||
| has '_print' => ( | ||||
|     is      => 'ro', | ||||
|     default => sub { Slic3r::Print->new }, | ||||
|     handles => [qw(apply_config extruders expanded_output_filepath)], | ||||
| ); | ||||
| 
 | ||||
| has 'duplicate' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { 1 }, | ||||
| ); | ||||
| 
 | ||||
| has 'scale' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { 1 }, | ||||
| ); | ||||
| 
 | ||||
| has 'rotate' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { 0 }, | ||||
| ); | ||||
| 
 | ||||
| has 'duplicate_grid' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { [1,1] }, | ||||
| ); | ||||
| 
 | ||||
| has 'status_cb' => ( | ||||
|     is      => 'rw', | ||||
|     default => sub { sub {} }, | ||||
| ); | ||||
| 
 | ||||
| has 'output_file' => ( | ||||
|     is      => 'rw', | ||||
| ); | ||||
| 
 | ||||
| sub set_model { | ||||
|     my ($self, $model) = @_; | ||||
|      | ||||
|     # make method idempotent so that the object is reusable | ||||
|     $self->_print->delete_all_objects; | ||||
|      | ||||
|     my $need_arrange = $model->has_objects_with_no_instances; | ||||
|     if ($need_arrange) { | ||||
|         # apply a default position to all objects not having one | ||||
|         foreach my $object (@{$model->objects}) { | ||||
|             $object->add_instance(offset => [0,0]) if !defined $object->instances; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     # apply scaling and rotation supplied from command line if any | ||||
|     foreach my $instance (map @{$_->instances}, @{$model->objects}) { | ||||
|         $instance->scaling_factor($instance->scaling_factor * $self->scale); | ||||
|         $instance->rotation($instance->rotation + $self->rotate); | ||||
|     } | ||||
|     # TODO: --scale --rotate, --duplicate* shouldn't be stored in config | ||||
|      | ||||
|     if ($self->duplicate_grid->[X] > 1 || $self->duplicate_grid->[Y] > 1) { | ||||
|         $model->duplicate_objects_grid($self->duplicate_grid, $self->_print->config->duplicate_distance); | ||||
|     } elsif ($need_arrange) { | ||||
|         $model->duplicate_objects($self->duplicate, $self->_print->config->min_object_distance); | ||||
|     } elsif ($self->duplicate > 1) { | ||||
|         # if all input objects have defined position(s) apply duplication to the whole model | ||||
|         $model->duplicate($self->duplicate, $self->_print->config->min_object_distance); | ||||
|     } | ||||
|     $model->center_instances_around_point($self->_print->config->print_center); | ||||
|      | ||||
|     foreach my $model_object (@{$model->objects}) { | ||||
|         $self->_print->auto_assign_extruders($model_object); | ||||
|         $self->_print->add_model_object($model_object); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| sub _before_export { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     $self->_print->status_cb($self->status_cb); | ||||
|     $self->_print->validate; | ||||
| } | ||||
| 
 | ||||
| sub _after_export { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     $self->_print->status_cb(undef); | ||||
| } | ||||
| 
 | ||||
| sub export_gcode { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     $self->_before_export; | ||||
|      | ||||
|     $self->_print->process; | ||||
|     $self->_print->export_gcode(output_file => $self->output_file); | ||||
|      | ||||
|     $self->_after_export; | ||||
| } | ||||
| 
 | ||||
| sub export_svg { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     $self->_before_export; | ||||
|      | ||||
|     $self->_print->export_svg(output_file => $self->output_file); | ||||
|      | ||||
|     $self->_after_export; | ||||
| } | ||||
| 
 | ||||
| 1; | ||||
|  | @ -107,7 +107,7 @@ sub contact_area { | |||
|         } else { | ||||
|             my $lower_layer = $object->layers->[$layer_id-1]; | ||||
|             foreach my $layerm (@{$layer->regions}) { | ||||
|                 my $fw = $layerm->perimeter_flow->scaled_width; | ||||
|                 my $fw = $layerm->flow(FLOW_ROLE_PERIMETER)->scaled_width; | ||||
|                 my $diff; | ||||
|              | ||||
|                 # If a threshold angle was specified, use a different logic for detecting overhangs. | ||||
|  |  | |||
							
								
								
									
										52
									
								
								slic3r.pl
									
										
									
									
									
								
							
							
						
						
									
										52
									
								
								slic3r.pl
									
										
									
									
									
								
							|  | @ -12,7 +12,6 @@ use Getopt::Long qw(:config no_auto_abbrev); | |||
| use List::Util qw(first); | ||||
| use POSIX qw(setlocale LC_NUMERIC); | ||||
| use Slic3r; | ||||
| use Slic3r::Geometry qw(X Y); | ||||
| use Time::HiRes qw(gettimeofday tv_interval); | ||||
| $|++; | ||||
| 
 | ||||
|  | @ -122,55 +121,32 @@ if (@ARGV) {  # slicing from command line | |||
|             $model = Slic3r::Model->read_from_file($input_file); | ||||
|         } | ||||
|          | ||||
|         my $need_arrange = $model->has_objects_with_no_instances; | ||||
|         if ($need_arrange) { | ||||
|             # apply a default position to all objects not having one | ||||
|             foreach my $object (@{$model->objects}) { | ||||
|                 $object->add_instance(offset => [0,0]) if !defined $object->instances; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         # apply scaling and rotation supplied from command line if any | ||||
|         foreach my $instance (map @{$_->instances}, @{$model->objects}) { | ||||
|             $instance->scaling_factor($instance->scaling_factor * $config->scale); | ||||
|             $instance->rotation($instance->rotation + $config->rotate); | ||||
|         } | ||||
|         # TODO: --scale --rotate, --duplicate* shouldn't be stored in config | ||||
|          | ||||
|         if ($config->duplicate_grid->[X] > 1 || $config->duplicate_grid->[Y] > 1) { | ||||
|             $model->duplicate_objects_grid($config->duplicate_grid, $config->duplicate_distance); | ||||
|         } elsif ($need_arrange) { | ||||
|             $model->duplicate_objects($config->duplicate, $config->min_object_distance); | ||||
|         } elsif ($config->duplicate > 1) { | ||||
|             # if all input objects have defined position(s) apply duplication to the whole model | ||||
|             $model->duplicate($config->duplicate, $config->min_object_distance); | ||||
|         } | ||||
|         $model->center_instances_around_point($config->print_center); | ||||
|          | ||||
|         if ($opt{info}) { | ||||
|             $model->print_info; | ||||
|             next; | ||||
|         } | ||||
|          | ||||
|         my $print = Slic3r::Print->new( | ||||
|             status_cb   => sub { | ||||
|         my $sprint = Slic3r::Print::Simple->new( | ||||
|             scale           => $config->scale, | ||||
|             rotate          => $config->rotate, | ||||
|             duplicate       => $config->duplicate, | ||||
|             duplicate_grid  => $config->duplicate_grid, | ||||
|             status_cb       => sub { | ||||
|                 my ($percent, $message) = @_; | ||||
|                 printf "=> %s\n", $message; | ||||
|             }, | ||||
|             output_file     => $opt{output}, | ||||
|         ); | ||||
|         $print->apply_config($config); | ||||
|         foreach my $model_object (@{$model->objects}) { | ||||
|             $print->auto_assign_extruders($model_object); | ||||
|             $print->add_model_object($model_object); | ||||
|         } | ||||
|          | ||||
|         $sprint->apply_config($config); | ||||
|         $sprint->set_model($model); | ||||
|         undef $model;  # free memory | ||||
|         $print->validate; | ||||
|          | ||||
|         if ($opt{export_svg}) { | ||||
|             $print->export_svg(output_file => $opt{output}); | ||||
|             $sprint->export_svg; | ||||
|         } else { | ||||
|             my $t0 = [gettimeofday]; | ||||
|             $print->process; | ||||
|             $print->export_gcode(output_file => $opt{output}); | ||||
|             $sprint->export_gcode; | ||||
|              | ||||
|             # output some statistics | ||||
|             { | ||||
|  | @ -180,7 +156,7 @@ if (@ARGV) {  # slicing from command line | |||
|             } | ||||
|             print map sprintf("Filament required: %.1fmm (%.1fcm3)\n", | ||||
|                 $_->absolute_E, $_->extruded_volume/1000), | ||||
|                 @{$print->extruders}; | ||||
|                 @{$sprint->extruders}; | ||||
|         } | ||||
|     } | ||||
| } else { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci