mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 12:11:15 -06:00 
			
		
		
		
	Move Print object storage to C++. (along with its subobjects)
This commit is contained in:
		
							parent
							
								
									3df2488eca
								
							
						
					
					
						commit
						8da0bded1d
					
				
					 25 changed files with 1221 additions and 273 deletions
				
			
		|  | @ -1,5 +1,4 @@ | |||
| package Slic3r::Print; | ||||
| use Moo; | ||||
| 
 | ||||
| use File::Basename qw(basename fileparse); | ||||
| use File::Spec; | ||||
|  | @ -12,22 +11,27 @@ use Slic3r::Geometry::Clipper qw(diff_ex union_ex union_pt intersection_ex inter | |||
|     offset2 union union_pt_chained JT_ROUND JT_SQUARE); | ||||
| use Slic3r::Print::State ':steps'; | ||||
| 
 | ||||
| has 'config'                 => (is => 'ro', default => sub { Slic3r::Config::Print->new }); | ||||
| has 'default_object_config'  => (is => 'ro', default => sub { Slic3r::Config::PrintObject->new }); | ||||
| has 'default_region_config'  => (is => 'ro', default => sub { Slic3r::Config::PrintRegion->new }); | ||||
| has 'placeholder_parser'     => (is => 'rw', default => sub { Slic3r::GCode::PlaceholderParser->new }); | ||||
| has 'objects'                => (is => 'rw', default => sub {[]}); | ||||
| has 'status_cb'              => (is => 'rw'); | ||||
| has 'regions'                => (is => 'rw', default => sub {[]}); | ||||
| has 'total_used_filament'    => (is => 'rw'); | ||||
| has 'total_extruded_volume'  => (is => 'rw'); | ||||
| has '_state'                 => (is => 'ro', default => sub { Slic3r::Print::State->new }); | ||||
| 
 | ||||
| # ordered collection of extrusion paths to build skirt loops | ||||
| has 'skirt' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new }); | ||||
| our $status_cb; | ||||
| 
 | ||||
| # ordered collection of extrusion paths to build a brim | ||||
| has 'brim' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new }); | ||||
| sub new { | ||||
|     # TODO: port PlaceholderParser methods to C++, then its own constructor | ||||
|         # can call them and no need for this new() method at all | ||||
|     my ($class) = @_; | ||||
|     my $self = $class->_new; | ||||
|     $self->placeholder_parser->apply_env_variables; | ||||
|     $self->placeholder_parser->update_timestamp; | ||||
|     return $self; | ||||
| } | ||||
| 
 | ||||
| sub set_status_cb { | ||||
|     my ($class, $cb) = @_; | ||||
|     $status_cb = $cb; | ||||
| } | ||||
| 
 | ||||
| sub status_cb { | ||||
|     return $status_cb; | ||||
| } | ||||
| 
 | ||||
| sub apply_config { | ||||
|     my ($self, $config) = @_; | ||||
|  | @ -74,9 +78,9 @@ sub apply_config { | |||
|     # All regions now have distinct settings. | ||||
|     # Check whether applying the new region config defaults we'd get different regions. | ||||
|     my $rearrange_regions = 0; | ||||
|     REGION: foreach my $region_id (0..$#{$self->regions}) { | ||||
|     REGION: foreach my $region_id (0..($self->region_count - 1)) { | ||||
|         foreach my $object (@{$self->objects}) { | ||||
|             foreach my $volume_id (@{ $object->region_volumes->[$region_id] }) { | ||||
|             foreach my $volume_id (@{ $object->get_region_volumes($region_id) }) { | ||||
|                 my $volume = $object->model_object->volumes->[$volume_id]; | ||||
|                  | ||||
|                 my $new = $self->default_region_config->clone; | ||||
|  | @ -125,8 +129,22 @@ sub add_model_object { | |||
|      | ||||
|     my $object_config = $object->config->clone; | ||||
|     $object_config->normalize; | ||||
|      | ||||
|     my %volumes = ();           # region_id => [ volume_id, ... ] | ||||
| 
 | ||||
|     # initialize print object and store it at the given position | ||||
|     my $o; | ||||
|     if (defined $obj_idx) { | ||||
|         $o = $self->set_new_object($obj_idx, $object, $object->bounding_box); | ||||
|     } else { | ||||
|         $o = $self->add_object($object, $object->bounding_box); | ||||
|     } | ||||
| 
 | ||||
|     $o->set_copies([ map Slic3r::Point->new_scale(@{ $_->offset }), @{ $object->instances } ]); | ||||
|     $o->set_layer_height_ranges($object->layer_height_ranges); | ||||
| 
 | ||||
|     # TODO: translate _trigger_copies to C++, then this can be done by | ||||
|         # PrintObject constructor | ||||
|     $o->_trigger_copies; | ||||
| 
 | ||||
|     foreach my $volume_id (0..$#{$object->volumes}) { | ||||
|         my $volume = $object->volumes->[$volume_id]; | ||||
|          | ||||
|  | @ -145,7 +163,7 @@ sub add_model_object { | |||
|          | ||||
|         # find an existing print region with the same config | ||||
|         my $region_id; | ||||
|         foreach my $i (0..$#{$self->regions}) { | ||||
|         foreach my $i (0..($self->region_count - 1)) { | ||||
|             my $region = $self->regions->[$i]; | ||||
|             if ($config->equals($region->config)) { | ||||
|                 $region_id = $i; | ||||
|  | @ -155,58 +173,19 @@ sub add_model_object { | |||
|          | ||||
|         # if no region exists with the same config, create a new one | ||||
|         if (!defined $region_id) { | ||||
|             push @{$self->regions}, my $r = Slic3r::Print::Region->new( | ||||
|                 print  => $self, | ||||
|             ); | ||||
|             my $r = $self->add_region(); | ||||
|             $r->config->apply($config); | ||||
|             $region_id = $#{$self->regions}; | ||||
|             $region_id = $self->region_count - 1; | ||||
|         } | ||||
|          | ||||
|         # assign volume to region | ||||
|         $volumes{$region_id} //= []; | ||||
|         push @{ $volumes{$region_id} }, $volume_id; | ||||
|         $o->add_region_volume($region_id, $volume_id); | ||||
|     } | ||||
|      | ||||
|     # initialize print object | ||||
|     my $o = Slic3r::Print::Object->new( | ||||
|         print               => $self, | ||||
|         model_object        => $object, | ||||
|         region_volumes      => [ map $volumes{$_}, 0..$#{$self->regions} ], | ||||
|         copies              => [ map Slic3r::Point->new_scale(@{ $_->offset }), @{ $object->instances } ], | ||||
|         layer_height_ranges => $object->layer_height_ranges, | ||||
|     ); | ||||
|      | ||||
| 
 | ||||
|     # apply config to print object | ||||
|     $o->config->apply($self->default_object_config); | ||||
|     $o->config->apply_dynamic($object_config); | ||||
|      | ||||
|     # store print object at the given position | ||||
|     if (defined $obj_idx) { | ||||
|         splice @{$self->objects}, $obj_idx, 0, $o; | ||||
|     } else { | ||||
|         push @{$self->objects}, $o; | ||||
|     } | ||||
|      | ||||
|     $self->_state->invalidate(STEP_SKIRT); | ||||
|     $self->_state->invalidate(STEP_BRIM); | ||||
| } | ||||
| 
 | ||||
| sub delete_object { | ||||
|     my ($self, $obj_idx) = @_; | ||||
|      | ||||
|     splice @{$self->objects}, $obj_idx, 1; | ||||
|     # TODO: purge unused regions | ||||
|      | ||||
|     $self->_state->invalidate(STEP_SKIRT); | ||||
|     $self->_state->invalidate(STEP_BRIM); | ||||
| } | ||||
| 
 | ||||
| sub clear_objects { | ||||
|     my ($self) = @_; | ||||
|      | ||||
|     @{$self->objects} = (); | ||||
|     @{$self->regions} = (); | ||||
|      | ||||
|     $self->_state->invalidate(STEP_SKIRT); | ||||
|     $self->_state->invalidate(STEP_BRIM); | ||||
| } | ||||
|  | @ -325,9 +304,9 @@ sub init_extruders { | |||
| 
 | ||||
| # this value is not supposed to be compared with $layer->id | ||||
| # since they have different semantics | ||||
| sub layer_count { | ||||
| sub total_layer_count { | ||||
|     my $self = shift; | ||||
|     return max(map $_->layer_count, @{$self->objects}); | ||||
|     return max(map $_->total_layer_count, @{$self->objects}); | ||||
| } | ||||
| 
 | ||||
| sub regions_count { | ||||
|  | @ -380,7 +359,7 @@ sub process { | |||
|     }; | ||||
|     my $object_step = sub { | ||||
|         my ($step, $cb) = @_; | ||||
|         for my $obj_idx (0..$#{$self->objects}) { | ||||
|         for my $obj_idx (0..($self->object_count - 1)) { | ||||
|             my $object = $self->objects->[$obj_idx]; | ||||
|             if (!$object->_state->done($step)) { | ||||
|                 $object->_state->set_started($step); | ||||
|  | @ -454,7 +433,7 @@ sub process { | |||
|             items => sub { | ||||
|                 my @items = ();  # [layer_id, region_id] | ||||
|                 for my $region_id (0 .. ($self->regions_count-1)) { | ||||
|                     push @items, map [$_, $region_id], 0..$#{$object->layers}; | ||||
|                     push @items, map [$_, $region_id], 0..($object->layer_count - 1); | ||||
|                 } | ||||
|                 @items; | ||||
|             }, | ||||
|  | @ -760,7 +739,7 @@ sub make_brim { | |||
|      | ||||
|     my $grow_distance = $flow->scaled_width / 2; | ||||
|     my @islands = (); # array of polygons | ||||
|     foreach my $obj_idx (0 .. $#{$self->objects}) { | ||||
|     foreach my $obj_idx (0 .. ($self->object_count - 1)) { | ||||
|         my $object = $self->objects->[$obj_idx]; | ||||
|         my $layer0 = $object->layers->[0]; | ||||
|         my @object_islands = ( | ||||
|  | @ -834,7 +813,7 @@ sub write_gcode { | |||
|      | ||||
|     my $first_object = $self->objects->[0]; | ||||
|     my $layer_height = $first_object->config->layer_height; | ||||
|     for my $region_id (0..$#{$self->regions}) { | ||||
|     for my $region_id (0..($self->region_count - 1)) { | ||||
|         printf $fh "; perimeters extrusion width = %.2fmm\n", | ||||
|             $self->regions->[$region_id]->flow(FLOW_ROLE_PERIMETER, $layer_height, 0, 0, undef, $first_object)->width; | ||||
|         printf $fh "; infill extrusion width = %.2fmm\n", | ||||
|  | @ -858,7 +837,7 @@ sub write_gcode { | |||
|     # set up our helper object | ||||
|     my $gcodegen = Slic3r::GCode->new( | ||||
|         placeholder_parser  => $self->placeholder_parser, | ||||
|         layer_count         => $self->layer_count, | ||||
|         layer_count         => $self->total_layer_count, | ||||
|     ); | ||||
|     $gcodegen->config->apply_print_config($self->config); | ||||
|     $gcodegen->set_extruders($self->extruders, $self->config); | ||||
|  | @ -902,7 +881,7 @@ sub write_gcode { | |||
|         my $distance_from_objects = 1; | ||||
|         # compute the offsetted convex hull for each object and repeat it for each copy. | ||||
|         my @islands = (); | ||||
|         foreach my $obj_idx (0 .. $#{$self->objects}) { | ||||
|         foreach my $obj_idx (0 .. ($self->object_count - 1)) { | ||||
|             my $convex_hull = convex_hull([ | ||||
|                 map @{$_->contour}, map @{$_->slices}, @{$self->objects->[$obj_idx]->layers}, | ||||
|             ]); | ||||
|  | @ -949,7 +928,7 @@ sub write_gcode { | |||
|     if ($self->config->complete_objects) { | ||||
|         # print objects from the smallest to the tallest to avoid collisions | ||||
|         # when moving onto next object starting point | ||||
|         my @obj_idx = sort { $self->objects->[$a]->size->[Z] <=> $self->objects->[$b]->size->[Z] } 0..$#{$self->objects}; | ||||
|         my @obj_idx = sort { $self->objects->[$a]->size->[Z] <=> $self->objects->[$b]->size->[Z] } 0..($self->object_count - 1); | ||||
|          | ||||
|         my $finished_objects = 0; | ||||
|         for my $obj_idx (@obj_idx) { | ||||
|  | @ -996,7 +975,7 @@ sub write_gcode { | |||
|          | ||||
|         # sort layers by Z | ||||
|         my %layers = ();  # print_z => [ [layers], [layers], [layers] ]  by obj_idx | ||||
|         foreach my $obj_idx (0 .. $#{$self->objects}) { | ||||
|         foreach my $obj_idx (0 .. ($self->object_count - 1)) { | ||||
|             my $object = $self->objects->[$obj_idx]; | ||||
|             foreach my $layer (@{$object->layers}, @{$object->support_layers}) { | ||||
|                 $layers{ $layer->print_z } ||= []; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Y. Sapir
						Y. Sapir