Fix extruder assignment and tests

This commit is contained in:
Alessandro Ranellucci 2014-03-27 00:01:33 +01:00
parent 10bf334a58
commit 071097d3f1
10 changed files with 109 additions and 186 deletions

View file

@ -1,7 +1,7 @@
package Slic3r::GCode;
use Moo;
use List::Util qw(min first);
use List::Util qw(min max first);
use Slic3r::ExtrusionPath ':roles';
use Slic3r::Flow ':roles';
use Slic3r::Geometry qw(epsilon scale unscale scaled_epsilon points_coincide PI X Y B);
@ -27,6 +27,7 @@ has 'speed' => (is => 'rw');
has '_extrusion_axis' => (is => 'rw');
has '_retract_lift' => (is => 'rw');
has 'extruders' => (is => 'ro', default => sub {{}});
has 'multiple_extruders' => (is => 'rw', default => sub {0});
has 'extruder' => (is => 'rw');
has 'speeds' => (is => 'lazy'); # mm/min
has 'external_mp' => (is => 'rw');
@ -55,6 +56,11 @@ sub set_extruders {
$self->extruders->{$i} = my $e = Slic3r::Extruder->new_from_config($self->print_config, $i);
$self->enable_wipe(1) if $e->wipe;
}
# we enable support for multiple extruder if any extruder greater than 0 is used
# (even if prints only uses that one) since we need to output Tx commands
# first extruder has index 0
$self->multiple_extruders(max(@$extruder_ids) > 0);
}
sub _build_speeds {
@ -81,11 +87,6 @@ my %role_speeds = (
&EXTR_ROLE_GAPFILL => 'gap_fill',
);
sub multiple_extruders {
my $self = shift;
return (keys %{$self->extruders}) > 1;
}
sub set_shift {
my ($self, @shift) = @_;

View file

@ -162,7 +162,7 @@ sub selection_changed {
$material //= $volume->assign_unique_material;
$self->{staticbox}->SetLabel('Part Settings');
$self->{settings_panel}->enable;
$self->{settings_panel}->set_opt_keys(Slic3r::Config::PrintRegion->new->get_keys);
$self->{settings_panel}->set_opt_keys([ 'extruder', @{Slic3r::Config::PrintRegion->new->get_keys} ]);
$self->{settings_panel}->set_config($material->config);
} elsif ($itemData->{type} eq 'object') {
# select all object volumes in 3D preview
@ -174,7 +174,7 @@ sub selection_changed {
$self->{staticbox}->SetLabel('Object Settings');
$self->{settings_panel}->enable;
$self->{settings_panel}->set_opt_keys(
[ map @{$_->get_keys}, Slic3r::Config::PrintObject->new, Slic3r::Config::PrintRegion->new ]
[ 'extruder', map @{$_->get_keys}, Slic3r::Config::PrintObject->new, Slic3r::Config::PrintRegion->new ]
);
$self->{settings_panel}->set_config($self->{model_object}->config);
}

View file

@ -528,7 +528,7 @@ sub build {
$self->add_options_page('Multiple Extruders', 'funnel.png', optgroups => [
{
title => 'Override extruders',
title => 'Extruders',
options => [qw(perimeter_extruder infill_extruder support_material_extruder support_material_interface_extruder)],
},
{

View file

@ -32,6 +32,9 @@ has 'brim' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->n
sub apply_config {
my ($self, $config) = @_;
$config = $config->clone;
$config->normalize;
# apply variables to placeholder parser
$self->placeholder_parser->apply_config($config);
@ -52,7 +55,9 @@ sub apply_config {
my $new = $self->default_object_config->clone;
# we override the new config with object-specific options
$new->apply_dynamic($object->model_object->config);
my $model_object_config = $object->model_object->config->clone;
$model_object_config->normalize;
$new->apply_dynamic($model_object_config);
# check whether the new config is different from the current one
my $diff = $object->config->diff($new);
@ -66,55 +71,42 @@ sub apply_config {
# handle changes to regions config defaults
$self->default_region_config->apply_dynamic($config);
# check whether after applying the new region config defaults to all existing regions
# they still have distinct configs; if not we need to re-add objects in order to
# merge the now-equal regions
# first compute the transformed region configs
my @new_region_configs = ();
foreach my $region_id (0..$#{$self->regions}) {
my $new = $self->default_region_config->clone;
# 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}) {
foreach my $object (@{$self->objects}) {
foreach my $volume_id (@{ $object->region_volumes->[$region_id] }) {
my $volume = $object->model_object->volumes->[$volume_id];
next if !defined $volume->material_id;
my $material = $object->model_object->model->materials->{$volume->material_id};
$new->apply_dynamic($material->config);
push @new_region_configs, $new;
my $new = $self->default_region_config->clone;
{
my $model_object_config = $object->model_object->config->clone;
$model_object_config->normalize;
$new->apply_dynamic($model_object_config);
}
if (defined $volume->material_id) {
my $material_config = $object->model_object->model->materials->{$volume->material_id}->config->clone;
$material_config->normalize;
$new->apply_dynamic($material_config);
}
if (!$new->equals($self->regions->[$region_id]->config)) {
$rearrange_regions = 1;
last REGION;
}
}
}
}
# then find the first pair of identical configs
my $have_identical_configs = 0;
my $region_diff = [];
for my $i (0..$#new_region_configs) {
for my $j (($i+1)..$#new_region_configs) {
if ($new_region_configs[$i]->equals($new_region_configs[$j])) {
$have_identical_configs = 1;
}
}
my $diff = $self->regions->[$i]->config->diff($new_region_configs[$i]);
push @$region_diff, @$diff;
}
if ($have_identical_configs) {
# okay, the current subdivision of regions does not make sense anymore.
# Some optimization is possible: if the volumes-regions mappings don't change
# but still region configs are changed somehow, we could just apply the diff
# and invalidate the affected steps.
if ($rearrange_regions) {
# the current subdivision of regions does not make sense anymore.
# we need to remove all objects and re-add them
my @model_objects = map $_->model_object, @{$self->objects};
$self->delete_all_objects;
$self->add_model_object($_) for @model_objects;
} elsif (@$region_diff > 0) {
# if there are no identical regions even after applying the change in
# region config defaults, but at least one region config option changed,
# store the new region configs and invalidate
# the affected step(s)
foreach my $region_id (0..$#{$self->regions}) {
$self->regions->[$region_id]->config->apply($new_region_configs[$region_id]);
}
# TODO: only invalidate changed steps
$_->_state->invalidate_all for @{$self->objects};
}
}
@ -131,6 +123,9 @@ sub add_model_object {
my $self = shift;
my ($object, $obj_idx) = @_;
my $object_config = $object->config->clone;
$object_config->normalize;
my %volumes = (); # region_id => [ volume_id, ... ]
foreach my $volume_id (0..$#{$object->volumes}) {
my $volume = $object->volumes->[$volume_id];
@ -140,10 +135,11 @@ sub add_model_object {
$config->apply($self->default_region_config);
# override the defaults with per-object config and then with per-material config
$config->apply_dynamic($object->config);
$config->apply_dynamic($object_config);
if (defined $volume->material_id) {
my $material_config = $object->model->materials->{ $volume->material_id }->config;
my $material_config = $object->model->materials->{ $volume->material_id }->config->clone;
$material_config->normalize;
$config->apply_dynamic($material_config);
}
@ -182,7 +178,7 @@ sub add_model_object {
# apply config to print object
$o->config->apply($self->default_object_config);
$o->config->apply_dynamic($object->config);
$o->config->apply_dynamic($object_config);
# store print object at the given position
if (defined $obj_idx) {
@ -1102,6 +1098,9 @@ sub invalidate_step {
sub auto_assign_extruders {
my ($self, $model_object) = @_;
# only assign extruders if object has more than one volume
return if @{$model_object->volumes} == 1;
my $extruders = scalar @{ $self->config->nozzle_diameter };
foreach my $i (0..$#{$model_object->volumes}) {
my $volume = $model_object->volumes->[$i];

View file

@ -108,7 +108,8 @@ sub model {
my $model = Slic3r::Model->new;
my $object = $model->add_object(input_file => "${model_name}.stl");
$object->add_volume(mesh => mesh($model_name, %params));
$model->set_material($model_name);
$object->add_volume(mesh => mesh($model_name, %params), material_id => $model_name);
$object->add_instance(
offset => [0,0],
rotation => $params{rotation} // 0,
@ -134,7 +135,10 @@ sub init_print {
}
$model->arrange_objects($print->config->min_object_distance);
$model->center_instances_around_point($print->config->print_center);
$print->add_model_object($_) for @{$model->objects};
foreach my $model_object (@{$model->objects}) {
$print->auto_assign_extruders($model_object);
$print->add_model_object($model_object);
}
}
$print->validate;