Reworked the Perl unit / integration tests to use the same Print
interface that the application is using. Old interface used just for the integration tests was removed.
This commit is contained in:
parent
8bf6e69851
commit
ac6969c992
@ -50,7 +50,6 @@ use Slic3r::Point;
|
|||||||
use Slic3r::Polygon;
|
use Slic3r::Polygon;
|
||||||
use Slic3r::Polyline;
|
use Slic3r::Polyline;
|
||||||
use Slic3r::Print::Object;
|
use Slic3r::Print::Object;
|
||||||
use Slic3r::Print::Simple;
|
|
||||||
use Slic3r::Surface;
|
use Slic3r::Surface;
|
||||||
our $build = eval "use Slic3r::Build; 1";
|
our $build = eval "use Slic3r::Build; 1";
|
||||||
|
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
# A simple wrapper to quickly print a single model without a GUI.
|
|
||||||
# Used by the command line slic3r.pl, by command line utilities pdf-slic3s.pl and view-toolpaths.pl,
|
|
||||||
# and by the quick slice menu of the Slic3r GUI.
|
|
||||||
#
|
|
||||||
# It creates and owns an instance of Slic3r::Print to perform the slicing
|
|
||||||
# and it accepts an instance of Slic3r::Model from the outside.
|
|
||||||
|
|
||||||
package Slic3r::Print::Simple;
|
|
||||||
use Moo;
|
|
||||||
|
|
||||||
use Slic3r::Geometry qw(X Y);
|
|
||||||
|
|
||||||
has '_print' => (
|
|
||||||
is => 'ro',
|
|
||||||
default => sub { Slic3r::Print->new },
|
|
||||||
handles => [qw(apply_config_perl_tests_only extruders output_filepath
|
|
||||||
total_used_filament total_extruded_volume
|
|
||||||
placeholder_parser process)],
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'duplicate' => (
|
|
||||||
is => 'rw',
|
|
||||||
default => sub { 1 },
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'scale' => (
|
|
||||||
is => 'rw',
|
|
||||||
default => sub { 1 },
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'rotate' => (
|
|
||||||
is => 'rw',
|
|
||||||
default => sub { 0 },
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'duplicate_grid' => (
|
|
||||||
is => 'rw',
|
|
||||||
default => sub { [1,1] },
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'print_center' => (
|
|
||||||
is => 'rw',
|
|
||||||
default => sub { Slic3r::Pointf->new(100,100) },
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'dont_arrange' => (
|
|
||||||
is => 'rw',
|
|
||||||
default => sub { 0 },
|
|
||||||
);
|
|
||||||
|
|
||||||
has 'output_file' => (
|
|
||||||
is => 'rw',
|
|
||||||
);
|
|
||||||
|
|
||||||
sub set_model {
|
|
||||||
# $model is of type Slic3r::Model
|
|
||||||
my ($self, $model) = @_;
|
|
||||||
|
|
||||||
# make method idempotent so that the object is reusable
|
|
||||||
$self->_print->clear_objects;
|
|
||||||
|
|
||||||
# make sure all objects have at least one defined instance
|
|
||||||
my $need_arrange = $model->add_default_instances && ! $self->dont_arrange;
|
|
||||||
|
|
||||||
# apply scaling and rotation supplied from command line if any
|
|
||||||
foreach my $instance (map @{$_->instances}, @{$model->objects}) {
|
|
||||||
$instance->set_scaling_factor($instance->scaling_factor * $self->scale);
|
|
||||||
$instance->set_rotation($instance->rotation + $self->rotate);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($self->duplicate_grid->[X] > 1 || $self->duplicate_grid->[Y] > 1) {
|
|
||||||
$model->duplicate_objects_grid($self->duplicate_grid->[X], $self->duplicate_grid->[Y], $self->_print->config->duplicate_distance);
|
|
||||||
} elsif ($need_arrange) {
|
|
||||||
$model->duplicate_objects($self->duplicate, $self->_print->config->min_object_distance);
|
|
||||||
} elsif ($self->duplicate > 1) {
|
|
||||||
# if all input objects have defined position(s) apply duplication to the whole model
|
|
||||||
$model->duplicate($self->duplicate, $self->_print->config->min_object_distance);
|
|
||||||
}
|
|
||||||
$_->translate(0,0,-$_->bounding_box->z_min) for @{$model->objects};
|
|
||||||
$model->center_instances_around_point($self->print_center) if (! $self->dont_arrange);
|
|
||||||
|
|
||||||
foreach my $model_object (@{$model->objects}) {
|
|
||||||
$self->_print->auto_assign_extruders($model_object);
|
|
||||||
$self->_print->add_model_object($model_object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub export_gcode {
|
|
||||||
my ($self) = @_;
|
|
||||||
$self->_print->validate;
|
|
||||||
$self->_print->export_gcode($self->output_file // '');
|
|
||||||
}
|
|
||||||
|
|
||||||
sub export_png {
|
|
||||||
my ($self) = @_;
|
|
||||||
|
|
||||||
$self->_before_export;
|
|
||||||
|
|
||||||
$self->_print->export_png(output_file => $self->output_file);
|
|
||||||
|
|
||||||
$self->_after_export;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
@ -146,60 +146,66 @@ sub mesh {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub model {
|
sub model {
|
||||||
my ($model_name, %params) = @_;
|
my ($model_names, %params) = @_;
|
||||||
|
$model_names = [ $model_names ] if ! ref($model_names);
|
||||||
my $input_file = "${model_name}.stl";
|
|
||||||
my $mesh = mesh($model_name, %params);
|
|
||||||
# $mesh->write_ascii("out/$input_file");
|
|
||||||
|
|
||||||
my $model = Slic3r::Model->new;
|
my $model = Slic3r::Model->new;
|
||||||
my $object = $model->add_object(input_file => $input_file);
|
|
||||||
$model->set_material($model_name);
|
for my $model_name (@$model_names) {
|
||||||
$object->add_volume(mesh => $mesh, material_id => $model_name);
|
my $input_file = "${model_name}.stl";
|
||||||
$object->add_instance(
|
my $mesh = mesh($model_name, %params);
|
||||||
offset => Slic3r::Pointf->new(0,0),
|
# $mesh->write_ascii("out/$input_file");
|
||||||
# 3D full transform
|
|
||||||
rotation => Slic3r::Pointf3->new(0, 0, $params{rotation} // 0),
|
my $object = $model->add_object(input_file => $input_file);
|
||||||
scaling_factor => Slic3r::Pointf3->new($params{scale} // 1, $params{scale} // 1, $params{scale} // 1),
|
$model->set_material($model_name);
|
||||||
# old transform
|
$object->add_volume(mesh => $mesh, material_id => $model_name);
|
||||||
# rotation => $params{rotation} // 0,
|
$object->add_instance(
|
||||||
# scaling_factor => $params{scale} // 1,
|
offset => Slic3r::Pointf->new(0,0),
|
||||||
);
|
# 3D full transform
|
||||||
|
rotation => Slic3r::Pointf3->new(0, 0, $params{rotation} // 0),
|
||||||
|
scaling_factor => Slic3r::Pointf3->new($params{scale} // 1, $params{scale} // 1, $params{scale} // 1),
|
||||||
|
# old transform
|
||||||
|
# rotation => $params{rotation} // 0,
|
||||||
|
# scaling_factor => $params{scale} // 1,
|
||||||
|
);
|
||||||
|
}
|
||||||
return $model;
|
return $model;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub init_print {
|
sub init_print {
|
||||||
my ($models, %params) = @_;
|
my ($models, %params) = @_;
|
||||||
|
my $model;
|
||||||
|
if (ref($models) eq 'ARRAY') {
|
||||||
|
$model = model($models, %params);
|
||||||
|
} elsif (ref($models)) {
|
||||||
|
$model = $models;
|
||||||
|
} else {
|
||||||
|
$model = model([$models], %params);
|
||||||
|
}
|
||||||
|
|
||||||
my $config = Slic3r::Config->new;
|
my $config = Slic3r::Config->new;
|
||||||
$config->apply($params{config}) if $params{config};
|
$config->apply($params{config}) if $params{config};
|
||||||
$config->set('gcode_comments', 1) if $ENV{SLIC3R_TESTS_GCODE};
|
$config->set('gcode_comments', 1) if $ENV{SLIC3R_TESTS_GCODE};
|
||||||
|
|
||||||
my $print = Slic3r::Print->new;
|
my $print = Slic3r::Print->new;
|
||||||
$print->apply_config_perl_tests_only($config);
|
die "Unknown model in test" if !defined $model;
|
||||||
|
if (defined $params{duplicate} && $params{duplicate} > 1) {
|
||||||
$models = [$models] if ref($models) ne 'ARRAY';
|
$model->duplicate($params{duplicate} // 1, $config->min_object_distance);
|
||||||
$models = [ map { ref($_) ? $_ : model($_, %params) } @$models ];
|
|
||||||
for my $model (@$models) {
|
|
||||||
die "Unknown model in test" if !defined $model;
|
|
||||||
if (defined $params{duplicate} && $params{duplicate} > 1) {
|
|
||||||
$model->duplicate($params{duplicate} // 1, $print->config->min_object_distance);
|
|
||||||
}
|
|
||||||
$model->arrange_objects($print->config->min_object_distance);
|
|
||||||
$model->center_instances_around_point($params{print_center} ? Slic3r::Pointf->new(@{$params{print_center}}) : Slic3r::Pointf->new(100,100));
|
|
||||||
foreach my $model_object (@{$model->objects}) {
|
|
||||||
$print->auto_assign_extruders($model_object);
|
|
||||||
$print->add_model_object($model_object);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
# Call apply_config_perl_tests_only one more time, so that the layer height profiles are updated over all PrintObjects.
|
$model->arrange_objects($config->min_object_distance);
|
||||||
$print->apply_config_perl_tests_only($config);
|
$model->center_instances_around_point($params{print_center} ? Slic3r::Pointf->new(@{$params{print_center}}) : Slic3r::Pointf->new(100,100));
|
||||||
|
foreach my $model_object (@{$model->objects}) {
|
||||||
|
$model_object->ensure_on_bed;
|
||||||
|
$print->auto_assign_extruders($model_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
$print->apply($model, $config);
|
||||||
$print->validate;
|
$print->validate;
|
||||||
|
|
||||||
# We return a proxy object in order to keep $models alive as required by the Print API.
|
# We return a proxy object in order to keep $models alive as required by the Print API.
|
||||||
return Slic3r::Test::Print->new(
|
return Slic3r::Test::Print->new(
|
||||||
print => $print,
|
print => $print,
|
||||||
models => $models,
|
model => $model,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +256,7 @@ sub add_facet {
|
|||||||
package Slic3r::Test::Print;
|
package Slic3r::Test::Print;
|
||||||
use Moo;
|
use Moo;
|
||||||
|
|
||||||
has 'print' => (is => 'ro', required => 1, handles => [qw(process apply_config_perl_tests_only)]);
|
has 'print' => (is => 'ro', required => 1, handles => [qw(process apply)]);
|
||||||
has 'models' => (is => 'ro', required => 1);
|
has 'model' => (is => 'ro', required => 1);
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -597,8 +597,8 @@ public:
|
|||||||
Model() {}
|
Model() {}
|
||||||
~Model() { this->clear_objects(); this->clear_materials(); }
|
~Model() { this->clear_objects(); this->clear_materials(); }
|
||||||
|
|
||||||
/* To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision" */
|
// To be able to return an object from own copy / clone methods. Hopefully the compiler will do the "Copy elision"
|
||||||
/* (Omits copy and move(since C++11) constructors, resulting in zero - copy pass - by - value semantics). */
|
// (Omits copy and move(since C++11) constructors, resulting in zero - copy pass - by - value semantics).
|
||||||
Model(const Model &rhs) : ModelBase(-1) { this->assign_copy(rhs); }
|
Model(const Model &rhs) : ModelBase(-1) { this->assign_copy(rhs); }
|
||||||
explicit Model(Model &&rhs) : ModelBase(-1) { this->assign_copy(std::move(rhs)); }
|
explicit Model(Model &&rhs) : ModelBase(-1) { this->assign_copy(std::move(rhs)); }
|
||||||
Model& operator=(const Model &rhs) { this->assign_copy(rhs); return *this; }
|
Model& operator=(const Model &rhs) { this->assign_copy(rhs); return *this; }
|
||||||
|
@ -328,198 +328,6 @@ double Print::max_allowed_layer_height() const
|
|||||||
return nozzle_diameter_max;
|
return nozzle_diameter_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caller is responsible for supplying models whose objects don't collide
|
|
||||||
// and have explicit instance positions.
|
|
||||||
void Print::add_model_object_perl_tests_only(ModelObject* model_object, int idx)
|
|
||||||
{
|
|
||||||
tbb::mutex::scoped_lock lock(this->state_mutex());
|
|
||||||
// Add a copy of this ModelObject to this Print.
|
|
||||||
m_model.objects.emplace_back(ModelObject::new_copy(*model_object));
|
|
||||||
m_model.objects.back()->set_model(&m_model);
|
|
||||||
// Initialize a new print object and store it at the given position.
|
|
||||||
PrintObject *object = new PrintObject(this, model_object, true);
|
|
||||||
if (idx != -1) {
|
|
||||||
delete m_objects[idx];
|
|
||||||
m_objects[idx] = object;
|
|
||||||
} else
|
|
||||||
m_objects.emplace_back(object);
|
|
||||||
// Invalidate all print steps.
|
|
||||||
this->invalidate_all_steps();
|
|
||||||
|
|
||||||
// Set the transformation matrix without translation from the first instance.
|
|
||||||
if (! model_object->instances.empty()) {
|
|
||||||
// Trafo and bounding box, both in world coordinate system.
|
|
||||||
Transform3d trafo = model_object->instances.front()->get_matrix();
|
|
||||||
BoundingBoxf3 bbox = model_object->instance_bounding_box(0);
|
|
||||||
// Now shift the object up to align it with the print bed.
|
|
||||||
trafo.data()[14] -= bbox.min(2);
|
|
||||||
// and reset the XY translation.
|
|
||||||
trafo.data()[12] = 0;
|
|
||||||
trafo.data()[13] = 0;
|
|
||||||
object->set_trafo(trafo);
|
|
||||||
}
|
|
||||||
|
|
||||||
int volume_id = 0;
|
|
||||||
for (const ModelVolume *volume : model_object->volumes) {
|
|
||||||
if (! volume->is_model_part() && ! volume->is_modifier())
|
|
||||||
continue;
|
|
||||||
// Get the config applied to this volume.
|
|
||||||
PrintRegionConfig config = PrintObject::region_config_from_model_volume(m_default_region_config, nullptr, *volume, 99999);
|
|
||||||
// Find an existing print region with the same config.
|
|
||||||
int region_id = -1;
|
|
||||||
for (int i = 0; i < (int)m_regions.size(); ++ i)
|
|
||||||
if (config.equals(m_regions[i]->config())) {
|
|
||||||
region_id = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// If no region exists with the same config, create a new one.
|
|
||||||
if (region_id == -1) {
|
|
||||||
region_id = (int)m_regions.size();
|
|
||||||
this->add_region(config);
|
|
||||||
}
|
|
||||||
// Assign volume to a region.
|
|
||||||
object->add_region_volume((unsigned int)region_id, volume_id, t_layer_height_range(0, DBL_MAX));
|
|
||||||
++ volume_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply config to print object.
|
|
||||||
object->config_apply(this->default_object_config());
|
|
||||||
{
|
|
||||||
//normalize_and_apply_config(object->config(), model_object->config);
|
|
||||||
DynamicPrintConfig src_normalized(model_object->config);
|
|
||||||
src_normalized.normalize();
|
|
||||||
object->config_apply(src_normalized, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is only called through the Perl-C++ binding from the unit tests, should be
|
|
||||||
// removed when unit tests are rewritten to C++.
|
|
||||||
bool Print::apply_config_perl_tests_only(DynamicPrintConfig config)
|
|
||||||
{
|
|
||||||
tbb::mutex::scoped_lock lock(this->state_mutex());
|
|
||||||
|
|
||||||
|
|
||||||
// Perl unit tests were failing in case the preset was not normalized (e.g. https://github.com/prusa3d/PrusaSlicer/issues/2288 was caused
|
|
||||||
// by too short max_layer_height vector. Calling the necessary function Preset::normalize(...) is not currently possible because there is no
|
|
||||||
// access to preset. This should be solved when the unit tests are rewritten to C++. For now we just copy-pasted code from Preset.cpp
|
|
||||||
// to make sure the unit tests pass (functions set_num_extruders and nozzle_options()).
|
|
||||||
auto *nozzle_diameter = dynamic_cast<const ConfigOptionFloats*>(config.option("nozzle_diameter", true));
|
|
||||||
assert(nozzle_diameter != nullptr);
|
|
||||||
const auto &defaults = FullPrintConfig::defaults();
|
|
||||||
for (const std::string &key : { "nozzle_diameter", "min_layer_height", "max_layer_height", "extruder_offset",
|
|
||||||
"retract_length", "retract_lift", "retract_lift_above", "retract_lift_below", "retract_speed", "deretract_speed",
|
|
||||||
"retract_before_wipe", "retract_restart_extra", "retract_before_travel", "wipe",
|
|
||||||
"retract_layer_change", "retract_length_toolchange", "retract_restart_extra_toolchange", "extruder_colour" })
|
|
||||||
{
|
|
||||||
auto *opt = config.option(key, true);
|
|
||||||
assert(opt != nullptr);
|
|
||||||
assert(opt->is_vector());
|
|
||||||
unsigned int num_extruders = (unsigned int)nozzle_diameter->values.size();
|
|
||||||
static_cast<ConfigOptionVectorBase*>(opt)->resize(num_extruders, defaults.option(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// handle changes to print config
|
|
||||||
t_config_option_keys print_diff = m_config.diff(config);
|
|
||||||
m_config.apply_only(config, print_diff, true);
|
|
||||||
bool invalidated = this->invalidate_state_by_config_options(print_diff);
|
|
||||||
|
|
||||||
// handle changes to object config defaults
|
|
||||||
m_default_object_config.apply(config, true);
|
|
||||||
for (PrintObject *object : m_objects) {
|
|
||||||
// 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();
|
|
||||||
// we override the new config with object-specific options
|
|
||||||
normalize_and_apply_config(new_config, object->model_object()->config);
|
|
||||||
// check whether the new config is different from the current one
|
|
||||||
t_config_option_keys diff = object->config().diff(new_config);
|
|
||||||
object->config_apply_only(new_config, diff, true);
|
|
||||||
invalidated |= object->invalidate_state_by_config_options(diff);
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle changes to regions config defaults
|
|
||||||
m_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;
|
|
||||||
{
|
|
||||||
// Collect the already visited region configs into other_region_configs,
|
|
||||||
// so one may check for duplicates.
|
|
||||||
std::vector<PrintRegionConfig> other_region_configs;
|
|
||||||
for (size_t region_id = 0; region_id < m_regions.size(); ++ region_id) {
|
|
||||||
PrintRegion ®ion = *m_regions[region_id];
|
|
||||||
PrintRegionConfig this_region_config;
|
|
||||||
bool this_region_config_set = false;
|
|
||||||
for (PrintObject *object : m_objects) {
|
|
||||||
if (region_id < object->region_volumes.size()) {
|
|
||||||
for (const std::pair<t_layer_height_range, int> &volume_and_range : object->region_volumes[region_id]) {
|
|
||||||
const ModelVolume &volume = *object->model_object()->volumes[volume_and_range.second];
|
|
||||||
if (this_region_config_set) {
|
|
||||||
// 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 (! this_region_config.equals(PrintObject::region_config_from_model_volume(m_default_region_config, nullptr, volume, 99999))) {
|
|
||||||
rearrange_regions = true;
|
|
||||||
goto exit_for_rearrange_regions;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this_region_config = PrintObject::region_config_from_model_volume(m_default_region_config, nullptr, volume, 99999);
|
|
||||||
this_region_config_set = true;
|
|
||||||
}
|
|
||||||
for (const PrintRegionConfig &cfg : 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.
|
|
||||||
if (cfg.equals(this_region_config)) {
|
|
||||||
rearrange_regions = true;
|
|
||||||
goto exit_for_rearrange_regions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this_region_config_set) {
|
|
||||||
t_config_option_keys diff = region.config().diff(this_region_config);
|
|
||||||
if (! diff.empty()) {
|
|
||||||
region.config_apply_only(this_region_config, diff, false);
|
|
||||||
for (PrintObject *object : m_objects)
|
|
||||||
if (region_id < object->region_volumes.size() && ! object->region_volumes[region_id].empty())
|
|
||||||
invalidated |= object->invalidate_state_by_config_options(diff);
|
|
||||||
}
|
|
||||||
other_region_configs.emplace_back(std::move(this_region_config));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit_for_rearrange_regions:
|
|
||||||
|
|
||||||
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;
|
|
||||||
model_objects.reserve(m_objects.size());
|
|
||||||
for (PrintObject *object : m_objects)
|
|
||||||
model_objects.push_back(object->model_object());
|
|
||||||
this->clear();
|
|
||||||
for (ModelObject *mo : model_objects)
|
|
||||||
this->add_model_object_perl_tests_only(mo);
|
|
||||||
invalidated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (PrintObject *object : m_objects)
|
|
||||||
object->update_slicing_parameters();
|
|
||||||
|
|
||||||
return invalidated;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add or remove support modifier ModelVolumes from model_object_dst to match the ModelVolumes of model_object_new
|
// Add or remove support modifier ModelVolumes from model_object_dst to match the ModelVolumes of model_object_new
|
||||||
// in the exact order and with the same IDs.
|
// in the exact order and with the same IDs.
|
||||||
// It is expected, that the model_object_dst already contains the non-support volumes of model_object_new in the correct order.
|
// It is expected, that the model_object_dst already contains the non-support volumes of model_object_new in the correct order.
|
||||||
@ -1247,7 +1055,7 @@ std::string Print::validate() const
|
|||||||
Geometry::assemble_transform(Vec3d::Zero(), rotation, model_instance0->get_scaling_factor(), model_instance0->get_mirror())),
|
Geometry::assemble_transform(Vec3d::Zero(), rotation, model_instance0->get_scaling_factor(), model_instance0->get_mirror())),
|
||||||
float(scale_(0.5 * m_config.extruder_clearance_radius.value)), jtRound, float(scale_(0.1))).front();
|
float(scale_(0.5 * m_config.extruder_clearance_radius.value)), jtRound, float(scale_(0.1))).front();
|
||||||
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
||||||
for (const Point © : print_object->m_copies) {
|
for (const Point © : print_object->copies()) {
|
||||||
Polygon convex_hull = convex_hull0;
|
Polygon convex_hull = convex_hull0;
|
||||||
convex_hull.translate(copy);
|
convex_hull.translate(copy);
|
||||||
if (! intersection(convex_hulls_other, convex_hull).empty())
|
if (! intersection(convex_hulls_other, convex_hull).empty())
|
||||||
|
@ -294,10 +294,6 @@ public:
|
|||||||
|
|
||||||
ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override;
|
ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override;
|
||||||
|
|
||||||
// The following three methods are used by the Perl tests only. Get rid of them!
|
|
||||||
void add_model_object_perl_tests_only(ModelObject* model_object, int idx = -1);
|
|
||||||
bool apply_config_perl_tests_only(DynamicPrintConfig config);
|
|
||||||
|
|
||||||
void process() override;
|
void process() override;
|
||||||
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
|
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
|
||||||
// If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
|
// If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
|
||||||
|
@ -89,7 +89,7 @@ plan tests => 8;
|
|||||||
|
|
||||||
# we disable combination after infill has been generated
|
# we disable combination after infill has been generated
|
||||||
$config->set('infill_every_layers', 1);
|
$config->set('infill_every_layers', 1);
|
||||||
$print->apply_config_perl_tests_only($config);
|
$print->apply($print->print->model->clone, $config);
|
||||||
$print->process;
|
$print->process;
|
||||||
|
|
||||||
ok !(defined first { @{$_->get_region(0)->fill_surfaces} == 0 }
|
ok !(defined first { @{$_->get_region(0)->fill_surfaces} == 0 }
|
||||||
|
23
t/print.t
23
t/print.t
@ -1,4 +1,4 @@
|
|||||||
use Test::More tests => 2;
|
use Test::More tests => 6;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
@ -31,29 +31,32 @@ use Slic3r::Test;
|
|||||||
ok abs(unscale($center->[Y]) - $print_center->[Y]) < 0.005, 'print is centered around print_center (Y)';
|
ok abs(unscale($center->[Y]) - $print_center->[Y]) < 0.005, 'print is centered around print_center (Y)';
|
||||||
}
|
}
|
||||||
|
|
||||||
# This is really testing a path, which is no more used by the slicer, just by the test cases.
|
|
||||||
if (0)
|
|
||||||
{
|
{
|
||||||
# this represents the aggregate config from presets
|
# this represents the aggregate config from presets
|
||||||
my $config = Slic3r::Config::new_from_defaults;
|
my $config = Slic3r::Config::new_from_defaults;
|
||||||
|
# Define 4 extruders.
|
||||||
|
$config->set('nozzle_diameter', [0.4, 0.4, 0.4, 0.4]);
|
||||||
|
|
||||||
# user adds one object to the plater
|
# user adds one object to the plater
|
||||||
my $print = Slic3r::Test::init_print(my $model = Slic3r::Test::model('20mm_cube'), config => $config);
|
my $print = Slic3r::Test::init_print(my $model = Slic3r::Test::model('20mm_cube'), config => $config);
|
||||||
|
|
||||||
# user sets a per-region option
|
# user sets a per-region option
|
||||||
$print->print->objects->[0]->model_object->config->set('fill_density', 100);
|
my $model2 = $model->clone;
|
||||||
# $print->print->reload_object(0);
|
$model2->get_object(0)->config->set('fill_density', 100);
|
||||||
|
$print->apply($model2, $config);
|
||||||
|
|
||||||
is $print->print->regions->[0]->config->fill_density, 100, 'region config inherits model object config';
|
is $print->print->regions->[0]->config->fill_density, 100, 'region config inherits model object config';
|
||||||
|
|
||||||
# user exports G-code, thus the default config is reapplied
|
# user exports G-code, thus the default config is reapplied
|
||||||
$print->print->apply_config_perl_tests_only($config);
|
$model2->get_object(0)->config->erase('fill_density');
|
||||||
|
$print->apply($model2, $config);
|
||||||
|
|
||||||
is $print->print->regions->[0]->config->fill_density, 100, 'apply_config() does not override per-object settings';
|
is $print->print->regions->[0]->config->fill_density, 20, 'region config is resetted';
|
||||||
|
|
||||||
# user assigns object extruders
|
# user assigns object extruders
|
||||||
$print->print->objects->[0]->model_object->config->set('extruder', 3);
|
$model2->get_object(0)->config->set('extruder', 3);
|
||||||
$print->print->objects->[0]->model_object->config->set('perimeter_extruder', 2);
|
$model2->get_object(0)->config->set('perimeter_extruder', 2);
|
||||||
# $print->print->reload_object(0);
|
$print->apply($model2, $config);
|
||||||
|
|
||||||
is $print->print->regions->[0]->config->infill_extruder, 3, 'extruder setting is correctly expanded';
|
is $print->print->regions->[0]->config->infill_extruder, 3, 'extruder setting is correctly expanded';
|
||||||
is $print->print->regions->[0]->config->perimeter_extruder, 2, 'extruder setting does not override explicitely specified extruders';
|
is $print->print->regions->[0]->config->perimeter_extruder, 2, 'extruder setting does not override explicitely specified extruders';
|
||||||
|
@ -91,6 +91,8 @@ use Slic3r::Test;
|
|||||||
|
|
||||||
{
|
{
|
||||||
my $config = Slic3r::Config::new_from_defaults;
|
my $config = Slic3r::Config::new_from_defaults;
|
||||||
|
# Define 4 extruders.
|
||||||
|
$config->set('nozzle_diameter', [0.4, 0.4, 0.4, 0.4]);
|
||||||
$config->set('layer_height', 0.4);
|
$config->set('layer_height', 0.4);
|
||||||
$config->set('first_layer_height', 0.4);
|
$config->set('first_layer_height', 0.4);
|
||||||
$config->set('skirts', 1);
|
$config->set('skirts', 1);
|
||||||
@ -106,7 +108,7 @@ use Slic3r::Test;
|
|||||||
|
|
||||||
# we enable support material after skirt has been generated
|
# we enable support material after skirt has been generated
|
||||||
$config->set('support_material', 1);
|
$config->set('support_material', 1);
|
||||||
$print->apply_config_perl_tests_only($config);
|
$print->apply($print->print->model->clone, $config);
|
||||||
|
|
||||||
my $skirt_length = 0;
|
my $skirt_length = 0;
|
||||||
my @extrusion_points = ();
|
my @extrusion_points = ();
|
||||||
|
@ -49,7 +49,7 @@
|
|||||||
void erase(t_config_option_key opt_key);
|
void erase(t_config_option_key opt_key);
|
||||||
void normalize();
|
void normalize();
|
||||||
%name{setenv} void setenv_();
|
%name{setenv} void setenv_();
|
||||||
double min_object_distance() %code{% RETVAL = PrintConfig::min_object_distance(THIS); %};
|
double min_object_distance() %code{% PrintConfig cfg; cfg.apply(*THIS, true); RETVAL = cfg.min_object_distance(); %};
|
||||||
static DynamicPrintConfig* load(char *path)
|
static DynamicPrintConfig* load(char *path)
|
||||||
%code%{
|
%code%{
|
||||||
auto config = new DynamicPrintConfig();
|
auto config = new DynamicPrintConfig();
|
||||||
|
@ -211,6 +211,7 @@ ModelMaterial::attributes()
|
|||||||
void set_origin_translation(Vec3d* point)
|
void set_origin_translation(Vec3d* point)
|
||||||
%code%{ THIS->origin_translation = *point; %};
|
%code%{ THIS->origin_translation = *point; %};
|
||||||
|
|
||||||
|
void ensure_on_bed();
|
||||||
bool needed_repair() const;
|
bool needed_repair() const;
|
||||||
int materials_count() const;
|
int materials_count() const;
|
||||||
int facets_count();
|
int facets_count();
|
||||||
|
@ -70,6 +70,8 @@ _constant()
|
|||||||
Print();
|
Print();
|
||||||
~Print();
|
~Print();
|
||||||
|
|
||||||
|
Ref<Model> model()
|
||||||
|
%code%{ RETVAL = const_cast<Model*>(&THIS->model()); %};
|
||||||
Ref<StaticPrintConfig> config()
|
Ref<StaticPrintConfig> config()
|
||||||
%code%{ RETVAL = const_cast<GCodeConfig*>(static_cast<const GCodeConfig*>(&THIS->config())); %};
|
%code%{ RETVAL = const_cast<GCodeConfig*>(static_cast<const GCodeConfig*>(&THIS->config())); %};
|
||||||
Ref<PlaceholderParser> placeholder_parser()
|
Ref<PlaceholderParser> placeholder_parser()
|
||||||
@ -140,8 +142,8 @@ _constant()
|
|||||||
}
|
}
|
||||||
%};
|
%};
|
||||||
|
|
||||||
bool apply_config_perl_tests_only(DynamicPrintConfig* config)
|
bool apply(Model *model, DynamicPrintConfig* config)
|
||||||
%code%{ RETVAL = THIS->apply_config_perl_tests_only(*config); %};
|
%code%{ RETVAL = THIS->apply(*model, *config); %};
|
||||||
bool has_infinite_skirt();
|
bool has_infinite_skirt();
|
||||||
std::vector<unsigned int> extruders() const;
|
std::vector<unsigned int> extruders() const;
|
||||||
int validate() %code%{
|
int validate() %code%{
|
||||||
|
Loading…
Reference in New Issue
Block a user