Ported some methods including add_model_object() and apply_config() to XS

This commit is contained in:
Alessandro Ranellucci 2014-11-09 12:25:59 +01:00
parent 6b4015f9ac
commit 3e4c572164
14 changed files with 312 additions and 254 deletions

View file

@ -174,19 +174,6 @@ sub _handle_legacy {
return ($opt_key, $value);
}
sub set_ifndef {
my $self = shift;
my ($opt_key, $value, $deserialize) = @_;
if (!$self->has($opt_key)) {
if ($deserialize) {
$self->set_deserialize($opt_key, $value);
} else {
$self->set($opt_key, $value);
}
}
}
sub as_ini {
my ($self) = @_;
@ -213,23 +200,6 @@ sub setenv {
}
}
sub equals {
my ($self, $other) = @_;
return @{ $self->diff($other) } == 0;
}
# this will *ignore* options not present in both configs
sub diff {
my ($self, $other) = @_;
my @diff = ();
foreach my $opt_key (sort @{$self->get_keys}) {
push @diff, $opt_key
if $other->has($opt_key) && $other->serialize($opt_key) ne $self->serialize($opt_key);
}
return [@diff];
}
# this method is idempotent by design and only applies to ::DynamicConfig or ::Full
# objects because it performs cross checks
sub validate {

View file

@ -34,189 +34,6 @@ sub status_cb {
return $status_cb // sub {};
}
sub apply_config {
my ($self, $config) = @_;
$config = $config->clone;
$config->normalize;
# apply variables to placeholder parser
$self->placeholder_parser->apply_config($config);
my $invalidated = 0;
# handle changes to print config
my $print_diff = $self->config->diff($config);
if (@$print_diff) {
$self->config->apply_dynamic($config);
$invalidated = 1
if $self->invalidate_state_by_config_options($print_diff);
}
# handle changes to object config defaults
$self->default_object_config->apply_dynamic($config);
foreach my $object (@{$self->objects}) {
# we don't assume that $config contains a full ObjectConfig,
# so we base it on the current print-wise default
my $new = $self->default_object_config->clone;
$new->apply_dynamic($config);
# we override the new config with object-specific options
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);
if (@$diff) {
$object->config->apply($new);
$invalidated = 1
if $object->invalidate_state_by_config_options($diff);
}
}
# handle changes to regions config defaults
$self->default_region_config->apply_dynamic($config);
# All regions now have distinct settings.
# Check whether applying the new region config defaults we'd get different regions.
my $rearrange_regions = 0;
my @other_region_configs = ();
REGION: foreach my $region_id (0..($self->region_count - 1)) {
my $region = $self->regions->[$region_id];
my @this_region_configs = ();
foreach my $object (@{$self->objects}) {
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;
foreach my $other_config ($object->model_object->config, $volume->config) {
my $other_config = $other_config->clone;
$other_config->normalize;
$new->apply_dynamic($other_config);
}
if ($volume->material_id ne '') {
my $material_config = $object->model_object->model->get_material($volume->material_id)->config->clone;
$material_config->normalize;
$new->apply_dynamic($material_config);
}
if (defined first { !$_->equals($new) } @this_region_configs) {
# if the new config for this volume differs from the other
# volume configs currently associated to this region, it means
# the region subdivision does not make sense anymore
$rearrange_regions = 1;
last REGION;
}
push @this_region_configs, $new;
if (defined first { $_->equals($new) } @other_region_configs) {
# if the new config for this volume equals any of the other
# volume configs that are not currently associated to this
# region, it means the region subdivision does not make
# sense anymore
$rearrange_regions = 1;
last REGION;
}
# if we're here and the new region config is different from the old
# one, we need to apply the new config and invalidate all objects
# (possible optimization: only invalidate objects using this region)
my $region_config_diff = $region->config->diff($new);
if (@$region_config_diff) {
$region->config->apply($new);
foreach my $o (@{$self->objects}) {
$invalidated = 1
if $o->invalidate_state_by_config_options($region_config_diff);
}
}
}
}
push @other_region_configs, @this_region_configs;
}
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->clear_objects;
$self->add_model_object($_) for @model_objects;
$invalidated = 1;
}
return $invalidated;
}
# caller is responsible for supplying models whose objects don't collide
# and have explicit instance positions
sub add_model_object {
my $self = shift;
my ($object, $obj_idx) = @_;
my $object_config = $object->config->clone;
$object_config->normalize;
# 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->raw_bounding_box);
} else {
$o = $self->add_object($object, $object->raw_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];
# get the config applied to this volume: start from our global defaults
my $config = Slic3r::Config::PrintRegion->new;
$config->apply($self->default_region_config);
# override the defaults with per-object config and then with per-volume and per-material configs
foreach my $other_config ($object_config, $volume->config) {
my $other_config = $other_config->clone;
$other_config->normalize;
$config->apply_dynamic($other_config);
}
if ($volume->material_id ne '') {
my $material_config = $volume->material->config->clone;
$material_config->normalize;
$config->apply_dynamic($material_config);
}
# find an existing print region with the same config
my $region_id;
foreach my $i (0..($self->region_count - 1)) {
my $region = $self->regions->[$i];
if ($config->equals($region->config)) {
$region_id = $i;
last;
}
}
# if no region exists with the same config, create a new one
if (!defined $region_id) {
my $r = $self->add_region();
$r->config->apply($config);
$region_id = $self->region_count - 1;
}
# assign volume to region
$o->add_region_volume($region_id, $volume_id);
}
# apply config to print object
$o->config->apply($self->default_object_config);
$o->config->apply_dynamic($object_config);
}
sub reload_object {
my ($self, $obj_idx) = @_;

View file

@ -32,34 +32,12 @@ sub support_layers {
return [ map $self->get_support_layer($_), 0..($self->support_layer_count - 1) ];
}
# TODO: translate to C++, then call it from constructor (see also
# Print->add_model_object)
sub _trigger_copies {
my $self = shift;
# TODO: should this mean point is 0,0?
return if !defined $self->_copies_shift;
# order copies with a nearest neighbor search and translate them by _copies_shift
$self->set_shifted_copies([
map {
my $c = $_->clone;
$c->translate(@{ $self->_copies_shift });
$c;
} @{$self->copies}[@{chained_path($self->copies)}]
]);
$self->print->invalidate_step(STEP_SKIRT);
$self->print->invalidate_step(STEP_BRIM);
}
# in unscaled coordinates
sub add_copy {
my ($self, $x, $y) = @_;
my @copies = @{$self->copies};
push @copies, Slic3r::Point->new_scale($x, $y);
$self->set_copies(\@copies);
$self->_trigger_copies;
}
sub delete_last_copy {
@ -67,13 +45,11 @@ sub delete_last_copy {
my @copies = $self->copies;
pop @copies;
$self->set_copies(\@copies);
$self->_trigger_copies;
}
sub delete_all_copies {
my ($self) = @_;
$self->set_copies([]);
$self->_trigger_copies;
}
# this is the *total* layer count (including support layers)