mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-07 05:54:03 -06:00
Ported some methods including add_model_object() and apply_config() to XS
This commit is contained in:
parent
6b4015f9ac
commit
3e4c572164
14 changed files with 312 additions and 254 deletions
|
@ -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 {
|
||||
|
|
|
@ -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) = @_;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue