mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Proper handling of interlaced layers in toolpaths preview
This commit is contained in:
		
							parent
							
								
									2632b2b30e
								
							
						
					
					
						commit
						f0a57a83fd
					
				
					 3 changed files with 110 additions and 49 deletions
				
			
		|  | @ -238,7 +238,7 @@ sub make_fill { | ||||||
|                             : EXTR_ROLE_FILL), |                             : EXTR_ROLE_FILL), | ||||||
|                 mm3_per_mm  => $mm3_per_mm, |                 mm3_per_mm  => $mm3_per_mm, | ||||||
|                 width       => $flow->width, |                 width       => $flow->width, | ||||||
|                 height      => $h, |                 height      => ($is_bridge ? $flow->width : $h), | ||||||
|             ), @polylines, |             ), @polylines, | ||||||
|         ); |         ); | ||||||
|         push @fills_ordering_points, $polylines[0]->first_point; |         push @fills_ordering_points, $polylines[0]->first_point; | ||||||
|  |  | ||||||
|  | @ -5,8 +5,8 @@ use utf8; | ||||||
| 
 | 
 | ||||||
| use List::Util qw(); | use List::Util qw(); | ||||||
| use Slic3r::Geometry qw(); | use Slic3r::Geometry qw(); | ||||||
| use Wx qw(:misc :sizer :slider); | use Wx qw(:misc :sizer :slider :statictext); | ||||||
| use Wx::Event qw(EVT_SLIDER); | use Wx::Event qw(EVT_SLIDER EVT_KEY_DOWN); | ||||||
| use base 'Wx::Panel'; | use base 'Wx::Panel'; | ||||||
| 
 | 
 | ||||||
| sub new { | sub new { | ||||||
|  | @ -17,19 +17,10 @@ sub new { | ||||||
|      |      | ||||||
|     # init print |     # init print | ||||||
|     $self->{print} = $print; |     $self->{print} = $print; | ||||||
|     $self->{layers} = {};  # print_z => [ layer*, layer* ... ] |     $self->reload_print; | ||||||
|     foreach my $object (@{$print->objects}) { |  | ||||||
|         foreach my $layer (@{$object->layers}, @{$object->support_layers}) { |  | ||||||
|             $self->{layers}{$layer->print_z} //= []; |  | ||||||
|             push @{ $self->{layers}{$layer->print_z} }, $layer; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     $self->{layers_z} = [ sort { $a <=> $b } keys %{$self->{layers}} ];   # [ z, z ... ] |  | ||||||
|      |      | ||||||
|     # init GUI elements |     # init GUI elements | ||||||
|     my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); |  | ||||||
|     my $canvas = $self->{canvas} = Slic3r::GUI::Plater::2DToolpaths::Canvas->new($self, $print); |     my $canvas = $self->{canvas} = Slic3r::GUI::Plater::2DToolpaths::Canvas->new($self, $print); | ||||||
|     $sizer->Add($canvas, 1, wxALL | wxEXPAND, 10); |  | ||||||
|     my $slider = $self->{slider} = Wx::Slider->new( |     my $slider = $self->{slider} = Wx::Slider->new( | ||||||
|         $self, -1, |         $self, -1, | ||||||
|         0,                              # default |         0,                              # default | ||||||
|  | @ -39,22 +30,62 @@ sub new { | ||||||
|         wxDefaultSize, |         wxDefaultSize, | ||||||
|         wxVERTICAL | wxSL_INVERSE, |         wxVERTICAL | wxSL_INVERSE, | ||||||
|     ); |     ); | ||||||
|     $sizer->Add($slider, 0, wxALL | wxEXPAND, 10); |     my $z_label = $self->{z_label} = Wx::StaticText->new($self, -1, "", wxDefaultPosition, | ||||||
|  |         [40,-1], wxALIGN_CENTRE_HORIZONTAL); | ||||||
|  |     $z_label->SetFont($Slic3r::GUI::small_font); | ||||||
|  |      | ||||||
|  |     my $vsizer = Wx::BoxSizer->new(wxVERTICAL); | ||||||
|  |     $vsizer->Add($slider, 1, wxALL | wxEXPAND | wxALIGN_CENTER, 3); | ||||||
|  |     $vsizer->Add($z_label, 0, wxALL | wxEXPAND | wxALIGN_CENTER, 3); | ||||||
|  |      | ||||||
|  |     my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); | ||||||
|  |     $sizer->Add($canvas, 1, wxALL | wxEXPAND, 0); | ||||||
|  |     $sizer->Add($vsizer, 0, wxTOP | wxBOTTOM | wxEXPAND, 5); | ||||||
|      |      | ||||||
|     EVT_SLIDER($self, $slider, sub { |     EVT_SLIDER($self, $slider, sub { | ||||||
|         my $z = $self->{layers_z}[$slider->GetValue]; |         $self->set_z($self->{layers_z}[$slider->GetValue]); | ||||||
|         $canvas->set_layers($self->{layers}{$z}); |     }); | ||||||
|  |     EVT_KEY_DOWN($canvas, sub { | ||||||
|  |         my ($s, $event) = @_; | ||||||
|  |          | ||||||
|  |         my $key = $event->GetKeyCode; | ||||||
|  |         if ($key == 85 || $key == 315) { | ||||||
|  |             $slider->SetValue($slider->GetValue + 1); | ||||||
|  |             $self->set_z($self->{layers_z}[$slider->GetValue]); | ||||||
|  |         } elsif ($key == 68 || $key == 317) { | ||||||
|  |             $slider->SetValue($slider->GetValue - 1); | ||||||
|  |             $self->set_z($self->{layers_z}[$slider->GetValue]); | ||||||
|  |         } | ||||||
|     }); |     }); | ||||||
|      |      | ||||||
|     $self->SetSizer($sizer); |     $self->SetSizer($sizer); | ||||||
|     $self->SetMinSize($self->GetSize); |     $self->SetMinSize($self->GetSize); | ||||||
|     $sizer->SetSizeHints($self); |     $sizer->SetSizeHints($self); | ||||||
|      |      | ||||||
|     $canvas->set_layers($self->{layers}{ $self->{layers_z}[0] }); |     $self->set_z($self->{layers_z}[0]); | ||||||
|      |      | ||||||
|     return $self; |     return $self; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | sub reload_print { | ||||||
|  |     my ($self) = @_; | ||||||
|  |      | ||||||
|  |     my %z = ();  # z => 1 | ||||||
|  |     foreach my $object (@{$self->{print}->objects}) { | ||||||
|  |         foreach my $layer (@{$object->layers}, @{$object->support_layers}) { | ||||||
|  |             $z{$layer->print_z} = 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     $self->{layers_z} = [ sort { $a <=> $b } keys %z ]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | sub set_z { | ||||||
|  |     my ($self, $z) = @_; | ||||||
|  |      | ||||||
|  |     $self->{z_label}->SetLabel(sprintf '%.2f', $z); | ||||||
|  |     $self->{canvas}->set_z($z); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| package Slic3r::GUI::Plater::2DToolpaths::Canvas; | package Slic3r::GUI::Plater::2DToolpaths::Canvas; | ||||||
| 
 | 
 | ||||||
|  | @ -62,10 +93,10 @@ use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_MOUSEWHEEL | ||||||
| use OpenGL qw(:glconstants :glfunctions :glufunctions); | use OpenGL qw(:glconstants :glfunctions :glufunctions); | ||||||
| use base qw(Wx::GLCanvas Class::Accessor); | use base qw(Wx::GLCanvas Class::Accessor); | ||||||
| use Wx::GLCanvas qw(:all); | use Wx::GLCanvas qw(:all); | ||||||
| use List::Util qw(min); | use List::Util qw(min first); | ||||||
| use Slic3r::Geometry qw(scale unscale); | use Slic3r::Geometry qw(scale unscale epsilon); | ||||||
| 
 | 
 | ||||||
| __PACKAGE__->mk_accessors(qw(print layers init dirty bb)); | __PACKAGE__->mk_accessors(qw(print z layers color init dirty bb)); | ||||||
| 
 | 
 | ||||||
| # make OpenGL::Array thread-safe | # make OpenGL::Array thread-safe | ||||||
| { | { | ||||||
|  | @ -95,10 +126,32 @@ sub new { | ||||||
|     return $self; |     return $self; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub set_layers { | sub set_z { | ||||||
|     my ($self, $layers) = @_; |     my ($self, $z) = @_; | ||||||
|      |      | ||||||
|     $self->layers($layers); |     my $print = $self->print; | ||||||
|  |      | ||||||
|  |     # can we have interlaced layers? | ||||||
|  |     my $interlaced = (defined first { $_->config->support_material } @{$print->objects}) | ||||||
|  |         || (defined first { $_->config->infill_every_layers > 1 } @{$print->regions}); | ||||||
|  |      | ||||||
|  |     my $max_layer_height = $print->max_layer_height; | ||||||
|  |      | ||||||
|  |     my @layers = (); | ||||||
|  |     foreach my $object (@{$print->objects}) { | ||||||
|  |         foreach my $layer (@{$object->layers}, @{$object->support_layers}) { | ||||||
|  |             if ($interlaced) { | ||||||
|  |                 push @layers, $layer | ||||||
|  |                     if $z > ($layer->print_z - $max_layer_height - epsilon) | ||||||
|  |                         && $z <= $layer->print_z + epsilon; | ||||||
|  |             } else { | ||||||
|  |                 push @layers, $layer if abs($layer->print_z - $z) < epsilon; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     $self->z($z); | ||||||
|  |     $self->layers([ @layers ]); | ||||||
|     $self->dirty(1); |     $self->dirty(1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -136,18 +189,19 @@ sub Render { | ||||||
|      |      | ||||||
|     foreach my $layer (@{$self->layers}) { |     foreach my $layer (@{$self->layers}) { | ||||||
|         my $object = $layer->object; |         my $object = $layer->object; | ||||||
|  |         my $print_z = $layer->print_z; | ||||||
|         foreach my $layerm (@{$layer->regions}) { |         foreach my $layerm (@{$layer->regions}) { | ||||||
|             glColor3f(0.7, 0, 0); |             $self->color([0.7, 0, 0]); | ||||||
|             $self->_draw_extrusionpath($object, $_) for @{$layerm->perimeters}; |             $self->_draw($object, $print_z, $_) for @{$layerm->perimeters}; | ||||||
|              |              | ||||||
|             glColor3f(0, 0, 0.7); |             $self->color([0, 0, 0.7]); | ||||||
|             $self->_draw_extrusionpath($object, $_) for map @$_, @{$layerm->fills}; |             $self->_draw($object, $print_z, $_) for map @$_, @{$layerm->fills}; | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         if ($layer->isa('Slic3r::Layer::Support')) { |         if ($layer->isa('Slic3r::Layer::Support')) { | ||||||
|             glColor3f(0, 0, 0); |             $self->color([0, 0, 0]); | ||||||
|             $self->_draw_extrusionpath($object, $_) for @{$layer->support_fills}; |             $self->_draw($object, $print_z, $_) for @{$layer->support_fills}; | ||||||
|             $self->_draw_extrusionpath($object, $_) for @{$layer->support_interface_fills}; |             $self->_draw($object, $print_z, $_) for @{$layer->support_interface_fills}; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  | @ -155,16 +209,30 @@ sub Render { | ||||||
|     $self->SwapBuffers; |     $self->SwapBuffers; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub _draw_extrusionpath { | sub _draw { | ||||||
|     my ($self, $object, $path) = @_; |     my ($self, $object, $print_z, $path) = @_; | ||||||
|      |      | ||||||
|     my $polyline = $path->isa('Slic3r::ExtrusionLoop') |     my @paths = $path->isa('Slic3r::ExtrusionLoop') | ||||||
|         ? $path->polygon->split_at_first_point |         ? @$path | ||||||
|         : $path->polyline; |         : ($path); | ||||||
|  |      | ||||||
|  |     $self->_draw_path($object, $print_z, $_) for @paths; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | sub _draw_path { | ||||||
|  |     my ($self, $object, $print_z, $path) = @_; | ||||||
|  |      | ||||||
|  |     return if $print_z - $path->height > $self->z - epsilon; | ||||||
|  |      | ||||||
|  |     if (abs($print_z - $self->z) < epsilon) { | ||||||
|  |         glColor3f(@{$self->color}); | ||||||
|  |     } else { | ||||||
|  |         glColor3f(0.8, 0.8, 0.8); | ||||||
|  |     } | ||||||
|      |      | ||||||
|     glLineWidth(1); |     glLineWidth(1); | ||||||
|     foreach my $copy (@{ $object->_shifted_copies }) { |     foreach my $copy (@{ $object->_shifted_copies }) { | ||||||
|         foreach my $line (@{$polyline->lines}) { |         foreach my $line (@{$path->polyline->lines}) { | ||||||
|             $line->translate(@$copy); |             $line->translate(@$copy); | ||||||
|             glBegin(GL_LINES); |             glBegin(GL_LINES); | ||||||
|             glVertex2f(@{$line->a}); |             glVertex2f(@{$line->a}); | ||||||
|  | @ -180,8 +248,6 @@ sub InitGL { | ||||||
|     return if $self->init; |     return if $self->init; | ||||||
|     return unless $self->GetContext; |     return unless $self->GetContext; | ||||||
|     $self->init(1); |     $self->init(1); | ||||||
|      |  | ||||||
|      |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub GetContext { | sub GetContext { | ||||||
|  | @ -211,17 +277,7 @@ sub Resize { | ||||||
|     $self->dirty(0); |     $self->dirty(0); | ||||||
|   |   | ||||||
|     $self->SetCurrent($self->GetContext); |     $self->SetCurrent($self->GetContext); | ||||||
|      |     glViewport(0, 0, $x, $y); | ||||||
|     my ($x1, $y1, $x2, $y2) = (0, 0, $x, $y); |  | ||||||
|     if (0 && $x > $y) { |  | ||||||
|         $x2 = $y; |  | ||||||
|         $x1 = ($x - $y)/2; |  | ||||||
|     } |  | ||||||
|     if (0 && $y > $x) { |  | ||||||
|         $y2 = $x; |  | ||||||
|         $y1 = ($y - $x)/2; |  | ||||||
|     } |  | ||||||
|     glViewport($x1, $y1, $x2, $y2); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| sub line { | sub line { | ||||||
|  |  | ||||||
|  | @ -350,6 +350,11 @@ sub regions_count { | ||||||
|     return scalar @{$self->regions}; |     return scalar @{$self->regions}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | sub max_layer_height { | ||||||
|  |     my ($self) = @_; | ||||||
|  |     return max(@{$self->config->nozzle_diameter}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| sub bounding_box { | sub bounding_box { | ||||||
|     my $self = shift; |     my $self = shift; | ||||||
|      |      | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci