diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 33385daf3..dddc1461f 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -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 { diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 443a36715..58fbe0ca8 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -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) = @_; diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index af07f3488..3948f1ca6 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -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) diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index 417054e18..b3fe6b877 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -27,6 +27,27 @@ ConfigBase::apply(const ConfigBase &other, bool ignore_nonexistent) { } } +bool +ConfigBase::equals(ConfigBase &other) { + return this->diff(other).empty(); +} + +// this will *ignore* options not present in both configs +t_config_option_keys +ConfigBase::diff(ConfigBase &other) { + t_config_option_keys diff; + + t_config_option_keys my_keys; + this->keys(&my_keys); + for (t_config_option_keys::const_iterator opt_key = my_keys.begin(); opt_key != my_keys.end(); ++opt_key) { + if (other.has(*opt_key) && other.serialize(*opt_key) != this->serialize(*opt_key)) { + diff.push_back(*opt_key); + } + } + + return diff; +} + std::string ConfigBase::serialize(const t_config_option_key opt_key) { ConfigOption* opt = this->option(opt_key); @@ -248,6 +269,18 @@ ConfigBase::set_deserialize(const t_config_option_key opt_key, SV* str) { return this->set_deserialize(opt_key, value); } + +void +ConfigBase::set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize) +{ + if (!this->has(opt_key)) { + if (deserialize) { + this->set_deserialize(opt_key, value); + } else { + this->set(opt_key, value); + } + } +} #endif DynamicConfig& DynamicConfig::operator= (DynamicConfig other) diff --git a/xs/src/libslic3r/Config.hpp b/xs/src/libslic3r/Config.hpp index 437e45ea1..0d86294a3 100644 --- a/xs/src/libslic3r/Config.hpp +++ b/xs/src/libslic3r/Config.hpp @@ -464,8 +464,11 @@ class ConfigBase virtual const ConfigOption* option(const t_config_option_key opt_key) const = 0; virtual void keys(t_config_option_keys *keys) const = 0; void apply(const ConfigBase &other, bool ignore_nonexistent = false); + bool equals(ConfigBase &other); + t_config_option_keys diff(ConfigBase &other); std::string serialize(const t_config_option_key opt_key); bool set_deserialize(const t_config_option_key opt_key, std::string str); + void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false); double get_abs_value(const t_config_option_key opt_key); double get_abs_value(const t_config_option_key opt_key, double ratio_over); diff --git a/xs/src/libslic3r/Geometry.cpp b/xs/src/libslic3r/Geometry.cpp index 8e083360b..002f11f46 100644 --- a/xs/src/libslic3r/Geometry.cpp +++ b/xs/src/libslic3r/Geometry.cpp @@ -25,7 +25,7 @@ sort_points (Point a, Point b) /* This implementation is based on Andrew's monotone chain 2D convex hull algorithm */ void -convex_hull(Points &points, Polygon* hull) +convex_hull(Points points, Polygon* hull) { assert(points.size() >= 3); // sort input points @@ -55,12 +55,12 @@ convex_hull(Points &points, Polygon* hull) /* accepts an arrayref of points and returns a list of indices according to a nearest-neighbor walk */ void -chained_path(Points &points, std::vector<Points::size_type> &retval, Point start_near) +chained_path(const Points &points, std::vector<Points::size_type> &retval, Point start_near) { - PointPtrs my_points; - std::map<Point*,Points::size_type> indices; + PointConstPtrs my_points; + std::map<const Point*,Points::size_type> indices; my_points.reserve(points.size()); - for (Points::iterator it = points.begin(); it != points.end(); ++it) { + for (Points::const_iterator it = points.begin(); it != points.end(); ++it) { my_points.push_back(&*it); indices[&*it] = it - points.begin(); } @@ -75,7 +75,7 @@ chained_path(Points &points, std::vector<Points::size_type> &retval, Point start } void -chained_path(Points &points, std::vector<Points::size_type> &retval) +chained_path(const Points &points, std::vector<Points::size_type> &retval) { if (points.empty()) return; // can't call front() on empty vector chained_path(points, retval, points.front()); diff --git a/xs/src/libslic3r/Geometry.hpp b/xs/src/libslic3r/Geometry.hpp index 2dc183f82..31e29816d 100644 --- a/xs/src/libslic3r/Geometry.hpp +++ b/xs/src/libslic3r/Geometry.hpp @@ -11,9 +11,9 @@ using boost::polygon::voronoi_diagram; namespace Slic3r { namespace Geometry { -void convex_hull(Points &points, Polygon* hull); -void chained_path(Points &points, std::vector<Points::size_type> &retval, Point start_near); -void chained_path(Points &points, std::vector<Points::size_type> &retval); +void convex_hull(Points points, Polygon* hull); +void chained_path(const Points &points, std::vector<Points::size_type> &retval, Point start_near); +void chained_path(const Points &points, std::vector<Points::size_type> &retval); template<class T> void chained_path_items(Points &points, T &items, T &retval); bool directions_parallel(double angle1, double angle2, double max_diff = 0); diff --git a/xs/src/libslic3r/Point.cpp b/xs/src/libslic3r/Point.cpp index ec13eb951..9debe9e8e 100644 --- a/xs/src/libslic3r/Point.cpp +++ b/xs/src/libslic3r/Point.cpp @@ -40,6 +40,12 @@ Point::translate(double x, double y) this->y += y; } +void +Point::translate(const Point &vector) +{ + this->translate(vector.x, vector.y); +} + void Point::rotate(double angle, const Point ¢er) { diff --git a/xs/src/libslic3r/Point.hpp b/xs/src/libslic3r/Point.hpp index d70a14093..3af5b36d0 100644 --- a/xs/src/libslic3r/Point.hpp +++ b/xs/src/libslic3r/Point.hpp @@ -27,10 +27,14 @@ class Point Point(int _x, int _y): x(_x), y(_y) {}; Point(long long _x, long long _y): x(_x), y(_y) {}; // for Clipper Point(double x, double y); + static Point new_scale(coordf_t x, coordf_t y) { + return Point(scale_(x), scale_(y)); + }; bool operator==(const Point& rhs) const; std::string wkt() const; void scale(double factor); void translate(double x, double y); + void translate(const Point &vector); void rotate(double angle, const Point ¢er); bool coincides_with(const Point &point) const; bool coincides_with_epsilon(const Point &point) const; diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index d0ec15cb5..54ad73bcf 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -308,6 +308,189 @@ Print::max_allowed_layer_height() const return *std::max_element(nozzle_diameter.begin(), nozzle_diameter.end()); } +/* Caller is responsible for supplying models whose objects don't collide + and have explicit instance positions */ +void +Print::add_model_object(ModelObject* model_object, int idx) +{ + DynamicPrintConfig object_config = model_object->config; // clone + object_config.normalize(); + + // initialize print object and store it at the given position + PrintObject* o; + { + BoundingBoxf3 bb; + model_object->raw_bounding_box(&bb); + o = (idx != -1) + ? this->set_new_object(idx, model_object, bb) + : this->add_object(model_object, bb); + } + + { + Points copies; + for (ModelInstancePtrs::const_iterator i = model_object->instances.begin(); i != model_object->instances.end(); ++i) { + copies.push_back(Point::new_scale((*i)->offset.x, (*i)->offset.y)); + } + o->set_copies(copies); + } + o->layer_height_ranges = model_object->layer_height_ranges; + + for (ModelVolumePtrs::const_iterator v_i = model_object->volumes.begin(); v_i != model_object->volumes.end(); ++v_i) { + size_t volume_id = v_i - model_object->volumes.begin(); + ModelVolume* volume = *v_i; + + // get the config applied to this volume + PrintRegionConfig config = this->_region_config_from_model_volume(*volume); + + // find an existing print region with the same config + int region_id = -1; + for (PrintRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region) { + if (config.equals((*region)->config)) { + region_id = region - this->regions.begin(); + break; + } + } + + // if no region exists with the same config, create a new one + if (region_id == -1) { + PrintRegion* r = this->add_region(); + r->config.apply(config); + region_id = this->regions.size() - 1; + } + + // assign volume to region + o->add_region_volume(region_id, volume_id); + } + + // apply config to print object + o->config.apply(this->default_object_config); + o->config.apply(object_config, true); +} + +bool +Print::apply_config(DynamicPrintConfig config) +{ + // we get a copy of the config object so we can modify it safely + config.normalize(); + + // apply variables to placeholder parser + this->placeholder_parser.apply_config(config); + + bool invalidated = false; + + // handle changes to print config + t_config_option_keys print_diff = this->config.diff(config); + if (!print_diff.empty()) { + this->config.apply(config, true); + + if (this->invalidate_state_by_config_options(print_diff)) + invalidated = true; + } + + // handle changes to object config defaults + this->default_object_config.apply(config, true); + FOREACH_OBJECT(this, obj_ptr) { + // we don't assume that config contains a full ObjectConfig, + // so we base it on the current print-wise default + PrintObjectConfig new_config = this->default_object_config; + new_config.apply(config, true); + + // we override the new config with object-specific options + { + DynamicPrintConfig model_object_config = (*obj_ptr)->model_object()->config; + model_object_config.normalize(); + new_config.apply(model_object_config, true); + } + + // check whether the new config is different from the current one + t_config_option_keys diff = (*obj_ptr)->config.diff(new_config); + if (!diff.empty()) { + (*obj_ptr)->config.apply(new_config, true); + + if ((*obj_ptr)->invalidate_state_by_config_options(diff)) + invalidated = true; + } + } + + // handle changes to regions config defaults + this->default_region_config.apply(config, true); + + // All regions now have distinct settings. + // Check whether applying the new region config defaults we'd get different regions. + bool rearrange_regions = false; + std::vector<PrintRegionConfig> other_region_configs; + FOREACH_REGION(this, it_r) { + size_t region_id = it_r - this->regions.begin(); + PrintRegion* region = *it_r; + + std::vector<PrintRegionConfig> this_region_configs; + FOREACH_OBJECT(this, it_o) { + PrintObject* object = *it_o; + + std::vector<int> ®ion_volumes = object->region_volumes[region_id]; + for (std::vector<int>::const_iterator volume_id = region_volumes.begin(); volume_id != region_volumes.end(); ++volume_id) { + ModelVolume* volume = object->model_object()->volumes[*volume_id]; + + PrintRegionConfig new_config = this->_region_config_from_model_volume(*volume); + + for (std::vector<PrintRegionConfig>::iterator it = this_region_configs.begin(); it != this_region_configs.end(); ++it) { + // 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 + if (!it->equals(new_config)) { + rearrange_regions = true; + goto NEXT_REGION; + } + } + this_region_configs.push_back(new_config); + + for (std::vector<PrintRegionConfig>::iterator it = other_region_configs.begin(); it != other_region_configs.end(); ++it) { + // 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 + if (it->equals(new_config)) { + rearrange_regions = true; + goto NEXT_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) + t_config_option_keys region_config_diff = region->config.diff(new_config); + if (!region_config_diff.empty()) { + region->config.apply(new_config); + FOREACH_OBJECT(this, o) { + if ((*o)->invalidate_state_by_config_options(region_config_diff)) + invalidated = true; + } + } + } + } + other_region_configs.insert(other_region_configs.end(), this_region_configs.begin(), this_region_configs.end()); + + NEXT_REGION: + continue; + } + + if (rearrange_regions) { + // the current subdivision of regions does not make sense anymore. + // we need to remove all objects and re-add them + ModelObjectPtrs model_objects; + FOREACH_OBJECT(this, o) { + model_objects.push_back((*o)->model_object()); + } + this->clear_objects(); + for (ModelObjectPtrs::iterator it = model_objects.begin(); it != model_objects.end(); ++it) { + this->add_model_object(*it); + } + invalidated = true; + } + + return invalidated; +} + void Print::init_extruders() { @@ -324,6 +507,28 @@ Print::init_extruders() this->state.set_done(psInitExtruders); } +PrintRegionConfig +Print::_region_config_from_model_volume(const ModelVolume &volume) +{ + PrintRegionConfig config = this->default_region_config; + { + DynamicPrintConfig other_config = volume.get_object()->config; + other_config.normalize(); + config.apply(other_config, true); + } + { + DynamicPrintConfig other_config = volume.config; + other_config.normalize(); + config.apply(other_config, true); + } + if (!volume.material_id().empty()) { + DynamicPrintConfig material_config = volume.material()->config; + material_config.normalize(); + config.apply(material_config, true); + } + return config; +} + bool Print::has_support_material() const { diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index 8b2a45044..9436d590e 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -8,6 +8,7 @@ #include "PrintConfig.hpp" #include "Point.hpp" #include "Layer.hpp" +#include "Model.hpp" #include "PlaceholderParser.hpp" @@ -70,7 +71,6 @@ class PrintObject public: // vector of (vectors of volume ids), indexed by region_id std::vector<std::vector<int> > region_volumes; - Points copies; // Slic3r::Point objects in scaled G-code coordinates PrintObjectConfig config; t_layer_height_ranges layer_height_ranges; @@ -95,7 +95,10 @@ class PrintObject Print* print(); ModelObject* model_object(); - + + Points copies() const; + void set_copies(const Points &points); + // adds region_id, too, if necessary void add_region_volume(int region_id, int volume_id); @@ -119,6 +122,7 @@ class PrintObject private: Print* _print; ModelObject* _model_object; + Points _copies; // Slic3r::Point objects in scaled G-code coordinates // TODO: call model_object->get_bounding_box() instead of accepting // parameter @@ -164,6 +168,8 @@ class Print bool invalidate_step(PrintStep step); bool invalidate_all_steps(); + void add_model_object(ModelObject* model_object, int idx = -1); + bool apply_config(DynamicPrintConfig config); void init_extruders(); std::set<size_t> extruders() const; @@ -174,6 +180,7 @@ class Print private: void clear_regions(); void delete_region(size_t idx); + PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume); }; #define FOREACH_BASE(type, container, iterator) for (type::const_iterator iterator = (container).begin(); iterator != (container).end(); ++iterator) diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 15fa0f0ba..5f1fd19ee 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -1,5 +1,6 @@ #include "Print.hpp" #include "BoundingBox.hpp" +#include "Geometry.hpp" namespace Slic3r { @@ -21,8 +22,6 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, const Bounding this->_copies_shift = Point( scale_(modobj_bbox.min.x), scale_(modobj_bbox.min.y)); - // TODO: $self->_trigger_copies; - // Scale the object size and store it Pointf3 size = modobj_bbox.size(); this->size = Point3(scale_(size.x), scale_(size.y), scale_(size.z)); @@ -45,6 +44,35 @@ PrintObject::model_object() return this->_model_object; } +Points +PrintObject::copies() const +{ + return this->_copies; +} + +void +PrintObject::set_copies(const Points &points) +{ + this->_copies = points; + + // order copies with a nearest neighbor search and translate them by _copies_shift + this->_shifted_copies.clear(); + this->_shifted_copies.reserve(points.size()); + + // order copies with a nearest-neighbor search + std::vector<Points::size_type> ordered_copies; + Slic3r::Geometry::chained_path(points, ordered_copies); + + for (std::vector<Points::size_type>::const_iterator it = ordered_copies.begin(); it != ordered_copies.end(); ++it) { + Point copy = points[*it]; + copy.translate(this->_copies_shift); + this->_shifted_copies.push_back(copy); + } + + this->_print->invalidate_step(psSkirt); + this->_print->invalidate_step(psBrim); +} + void PrintObject::add_region_volume(int region_id, int volume_id) { diff --git a/xs/xsp/Config.xsp b/xs/xsp/Config.xsp index b11533e36..1d410062b 100644 --- a/xs/xsp/Config.xsp +++ b/xs/xsp/Config.xsp @@ -14,12 +14,15 @@ SV* get_at(t_config_option_key opt_key, int i); bool set(t_config_option_key opt_key, SV* value); bool set_deserialize(t_config_option_key opt_key, SV* str); + void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false); std::string serialize(t_config_option_key opt_key); double get_abs_value(t_config_option_key opt_key); %name{get_abs_value_over} double get_abs_value(t_config_option_key opt_key, double ratio_over); void apply(DynamicPrintConfig* other) %code{% THIS->apply(*other, true); %}; + std::vector<std::string> diff(DynamicPrintConfig* other) + %code{% RETVAL = THIS->diff(*other); %}; void apply_static(FullPrintConfig* other) %code{% THIS->apply(*other, true); %}; std::vector<std::string> get_keys() @@ -37,6 +40,7 @@ SV* get_at(t_config_option_key opt_key, int i); bool set(t_config_option_key opt_key, SV* value); bool set_deserialize(t_config_option_key opt_key, SV* str); + void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false); std::string serialize(t_config_option_key opt_key); double get_abs_value(t_config_option_key opt_key); %name{get_abs_value_over} @@ -58,6 +62,7 @@ SV* get_at(t_config_option_key opt_key, int i); bool set(t_config_option_key opt_key, SV* value); bool set_deserialize(t_config_option_key opt_key, SV* str); + void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false); std::string serialize(t_config_option_key opt_key); double get_abs_value(t_config_option_key opt_key); %name{get_abs_value_over} @@ -77,6 +82,7 @@ SV* get_at(t_config_option_key opt_key, int i); bool set(t_config_option_key opt_key, SV* value); bool set_deserialize(t_config_option_key opt_key, SV* str); + void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false); std::string serialize(t_config_option_key opt_key); double get_abs_value(t_config_option_key opt_key); %name{get_abs_value_over} @@ -98,6 +104,7 @@ SV* get_at(t_config_option_key opt_key, int i); bool set(t_config_option_key opt_key, SV* value); bool set_deserialize(t_config_option_key opt_key, SV* str); + void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false); std::string serialize(t_config_option_key opt_key); double get_abs_value(t_config_option_key opt_key); %name{get_abs_value_over} @@ -119,6 +126,7 @@ SV* get_at(t_config_option_key opt_key, int i); bool set(t_config_option_key opt_key, SV* value); bool set_deserialize(t_config_option_key opt_key, SV* str); + void set_ifndef(t_config_option_key opt_key, SV* value, bool deserialize = false); std::string serialize(t_config_option_key opt_key); double get_abs_value(t_config_option_key opt_key); %name{get_abs_value_over} diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 330bc6b9a..4a32255fc 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -56,8 +56,7 @@ _constant() Ref<ModelObject> model_object(); Ref<PrintObjectConfig> config() %code%{ RETVAL = &THIS->config; %}; - Points copies() - %code%{ RETVAL = THIS->copies; %}; + Points copies(); t_layer_height_ranges layer_height_ranges() %code%{ RETVAL = THIS->layer_height_ranges; %}; Ref<Point3> size() @@ -75,8 +74,7 @@ _constant() void set_shifted_copies(Points value) %code%{ THIS->_shifted_copies = value; %}; - void set_copies(Points copies) - %code%{ THIS->copies = copies; %}; + void set_copies(Points copies); void set_layer_height_ranges(t_layer_height_ranges layer_height_ranges) %code%{ THIS->layer_height_ranges = layer_height_ranges; %}; @@ -169,6 +167,9 @@ _constant() double max_allowed_layer_height() const; bool has_support_material() const; + void add_model_object(ModelObject* model_object, int idx = -1); + bool apply_config(DynamicPrintConfig* config) + %code%{ RETVAL = THIS->apply_config(*config); %}; void init_extruders(); %{