Further refactoring, C++11 conversion and code simplification.

This commit is contained in:
bubnikv 2017-05-30 20:09:34 +02:00
parent e1ca1a82fb
commit 102329c54d
6 changed files with 107 additions and 175 deletions

View file

@ -162,25 +162,19 @@ bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &o
} }
} }
void ConfigBase::apply(const ConfigBase &other, bool ignore_nonexistent) void ConfigBase::apply(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent)
{ {
// get list of option keys to apply
t_config_option_keys opt_keys = other.keys();
// loop through options and apply them // loop through options and apply them
for (t_config_option_keys::const_iterator it = opt_keys.begin(); it != opt_keys.end(); ++it) { for (const t_config_option_key &key : keys) {
ConfigOption* my_opt = this->option(*it, true); ConfigOption *my_opt = this->option(key, true);
if (my_opt == NULL) { if (my_opt == nullptr) {
if (ignore_nonexistent == false) throw "Attempt to apply non-existent option"; if (! ignore_nonexistent)
throw "Attempt to apply non-existent option";
continue; continue;
} }
// not the most efficient way, but easier than casting pointers to subclasses // not the most efficient way, but easier than casting pointers to subclasses
bool res = my_opt->deserialize( other.option(*it)->serialize() ); if (! my_opt->deserialize(other.option(key)->serialize()))
if (!res) { CONFESS((std::string("Unexpected failure when deserializing serialized value for ") + key).c_str());
std::string error = "Unexpected failure when deserializing serialized value for " + *it;
CONFESS(error.c_str());
}
} }
} }

View file

@ -660,7 +660,8 @@ public:
{ return this->optptr(opt_key, create); } { return this->optptr(opt_key, create); }
virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) = 0; virtual ConfigOption* optptr(const t_config_option_key &opt_key, bool create = false) = 0;
virtual t_config_option_keys keys() const = 0; virtual t_config_option_keys keys() const = 0;
void apply(const ConfigBase &other, bool ignore_nonexistent = false); void apply(const ConfigBase &other, bool ignore_nonexistent = false) { this->apply(other, other.keys(), ignore_nonexistent); }
void apply(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false);
bool equals(const ConfigBase &other) const { return this->diff(other).empty(); } bool equals(const ConfigBase &other) const { return this->diff(other).empty(); }
t_config_option_keys diff(const ConfigBase &other) const; t_config_option_keys diff(const ConfigBase &other) const;
std::string serialize(const t_config_option_key &opt_key) const; std::string serialize(const t_config_option_key &opt_key) const;

View file

@ -15,46 +15,26 @@ namespace Slic3r {
template class PrintState<PrintStep, psCount>; template class PrintState<PrintStep, psCount>;
template class PrintState<PrintObjectStep, posCount>; template class PrintState<PrintObjectStep, posCount>;
void Print::clear_objects()
Print::Print()
: total_used_filament(0),
total_extruded_volume(0)
{
}
Print::~Print()
{
clear_objects();
clear_regions();
}
void
Print::clear_objects()
{ {
for (int i = int(this->objects.size())-1; i >= 0; --i) for (int i = int(this->objects.size())-1; i >= 0; --i)
this->delete_object(i); this->delete_object(i);
this->clear_regions(); this->clear_regions();
} }
void void Print::delete_object(size_t idx)
Print::delete_object(size_t idx)
{ {
PrintObjectPtrs::iterator i = this->objects.begin() + idx; PrintObject *object = this->objects[idx];
// before deleting object, invalidate all of its steps in order to // before deleting object, invalidate all of its steps in order to
// invalidate all of the dependent ones in Print // invalidate all of the dependent ones in Print
(*i)->invalidate_all_steps(); object->invalidate_all_steps();
// destroy object and remove it from our container // destroy object and remove it from our container
delete *i; delete object;
this->objects.erase(i); this->objects.erase(this->objects.begin() + idx);
// TODO: purge unused regions // TODO: purge unused regions
} }
void void Print::reload_object(size_t idx)
Print::reload_object(size_t idx)
{ {
/* TODO: this method should check whether the per-object config and per-material configs /* TODO: this method should check whether the per-object config and per-material configs
have changed in such a way that regions need to be rearranged or we can just apply have changed in such a way that regions need to be rearranged or we can just apply
@ -64,59 +44,46 @@ Print::reload_object(size_t idx)
// collect all current model objects // collect all current model objects
ModelObjectPtrs model_objects; ModelObjectPtrs model_objects;
FOREACH_OBJECT(this, object) { model_objects.reserve(this->objects.size());
model_objects.push_back((*object)->model_object()); for (PrintObject *object : this->objects)
} model_objects.push_back(object->model_object());
// remove our print objects // remove our print objects
this->clear_objects(); this->clear_objects();
// re-add model objects // re-add model objects
for (ModelObjectPtrs::iterator it = model_objects.begin(); it != model_objects.end(); ++it) { for (ModelObject *mo : model_objects)
this->add_model_object(*it); this->add_model_object(mo);
}
} }
bool bool Print::reload_model_instances()
Print::reload_model_instances()
{ {
bool invalidated = false; bool invalidated = false;
FOREACH_OBJECT(this, object) { for (PrintObject *object : this->objects)
if ((*object)->reload_model_instances()) invalidated = true; invalidated |= object->reload_model_instances();
}
return invalidated; return invalidated;
} }
void void Print::clear_regions()
Print::clear_regions()
{ {
for (int i = this->regions.size()-1; i >= 0; --i) for (PrintRegion *region : this->regions)
this->delete_region(i); delete region;
this->regions.clear();
} }
PrintRegion* PrintRegion* Print::add_region()
Print::add_region()
{ {
PrintRegion *region = new PrintRegion(this); regions.push_back(new PrintRegion(this));
regions.push_back(region); return regions.back();
return region;
} }
void // Called by Print::apply_config().
Print::delete_region(size_t idx) // This method only accepts PrintConfig option keys.
bool Print::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys)
{ {
PrintRegionPtrs::iterator i = this->regions.begin() + idx; if (opt_keys.empty())
delete *i; return false;
this->regions.erase(i);
}
bool
Print::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys)
{
std::vector<PrintStep> steps; std::vector<PrintStep> steps;
std::vector<PrintObjectStep> osteps; std::vector<PrintObjectStep> osteps;
// this method only accepts PrintConfig option keys
for (const t_config_option_key &opt_key : opt_keys) { for (const t_config_option_key &opt_key : opt_keys) {
if ( opt_key == "skirts" if ( opt_key == "skirts"
|| opt_key == "skirt_height" || opt_key == "skirt_height"
@ -308,12 +275,11 @@ std::vector<unsigned int> Print::extruders() const
void Print::_simplify_slices(double distance) void Print::_simplify_slices(double distance)
{ {
FOREACH_OBJECT(this, object) { for (PrintObject *object : this->objects) {
FOREACH_LAYER(*object, layer) { for (Layer *layer : object->layers) {
(*layer)->slices.simplify(distance); layer->slices.simplify(distance);
FOREACH_LAYERREGION(*layer, layerm) { for (LayerRegion *layerm : layer->regions)
(*layerm)->slices.simplify(distance); layerm->slices.simplify(distance);
}
} }
} }
} }
@ -409,8 +375,7 @@ void Print::add_model_object(ModelObject* model_object, int idx)
} }
} }
bool bool Print::apply_config(DynamicPrintConfig config)
Print::apply_config(DynamicPrintConfig config)
{ {
// we get a copy of the config object so we can modify it safely // we get a copy of the config object so we can modify it safely
config.normalize(); config.normalize();
@ -422,16 +387,12 @@ Print::apply_config(DynamicPrintConfig config)
// handle changes to print config // handle changes to print config
t_config_option_keys print_diff = this->config.diff(config); t_config_option_keys print_diff = this->config.diff(config);
if (!print_diff.empty()) { this->config.apply(config, print_diff, true);
this->config.apply(config, true); invalidated |= this->invalidate_state_by_config_options(print_diff);
if (this->invalidate_state_by_config_options(print_diff))
invalidated = true;
}
// handle changes to object config defaults // handle changes to object config defaults
this->default_object_config.apply(config, true); this->default_object_config.apply(config, true);
FOREACH_OBJECT(this, obj_ptr) { for (PrintObject *object : this->objects) {
// we don't assume that config contains a full ObjectConfig, // we don't assume that config contains a full ObjectConfig,
// so we base it on the current print-wise default // so we base it on the current print-wise default
PrintObjectConfig new_config = this->default_object_config; PrintObjectConfig new_config = this->default_object_config;
@ -439,19 +400,15 @@ Print::apply_config(DynamicPrintConfig config)
// we override the new config with object-specific options // we override the new config with object-specific options
{ {
DynamicPrintConfig model_object_config = (*obj_ptr)->model_object()->config; DynamicPrintConfig model_object_config = object->model_object()->config;
model_object_config.normalize(); model_object_config.normalize();
new_config.apply(model_object_config, true); new_config.apply(model_object_config, true);
} }
// check whether the new config is different from the current one // check whether the new config is different from the current one
t_config_option_keys diff = (*obj_ptr)->config.diff(new_config); t_config_option_keys diff = object->config.diff(new_config);
if (!diff.empty()) { object->config.apply(new_config, diff, true);
(*obj_ptr)->config.apply(new_config, true); invalidated |= object->invalidate_state_by_config_options(diff);
if ((*obj_ptr)->invalidate_state_by_config_options(diff))
invalidated = true;
}
} }
// handle changes to regions config defaults // handle changes to regions config defaults
@ -461,37 +418,34 @@ Print::apply_config(DynamicPrintConfig config)
// Check whether applying the new region config defaults we'd get different regions. // Check whether applying the new region config defaults we'd get different regions.
bool rearrange_regions = false; bool rearrange_regions = false;
std::vector<PrintRegionConfig> other_region_configs; std::vector<PrintRegionConfig> other_region_configs;
FOREACH_REGION(this, it_r) { for (size_t region_id = 0; region_id < this->regions.size(); ++ region_id)
size_t region_id = it_r - this->regions.begin(); {
PrintRegion* region = *it_r; PrintRegion* region = this->regions[region_id];
std::vector<PrintRegionConfig> this_region_configs; std::vector<PrintRegionConfig> this_region_configs;
FOREACH_OBJECT(this, it_o) { for (PrintObject* object : this->objects)
PrintObject* object = *it_o; {
for (int volume_id : object->region_volumes[region_id]) {
std::vector<int> &region_volumes = object->region_volumes[region_id]; ModelVolume* volume = object->model_object()->volumes.at(volume_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.at(*volume_id);
PrintRegionConfig new_config = this->_region_config_from_model_volume(*volume); 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) { for (const PrintRegionConfig &cfg : this_region_configs) {
// if the new config for this volume differs from the other // if the new config for this volume differs from the other
// volume configs currently associated to this region, it means // volume configs currently associated to this region, it means
// the region subdivision does not make sense anymore // the region subdivision does not make sense anymore
if (!it->equals(new_config)) { if (! cfg.equals(new_config)) {
rearrange_regions = true; rearrange_regions = true;
goto NEXT_REGION; goto NEXT_REGION;
} }
} }
this_region_configs.push_back(new_config); this_region_configs.push_back(new_config);
for (std::vector<PrintRegionConfig>::iterator it = other_region_configs.begin(); it != other_region_configs.end(); ++it) { for (const PrintRegionConfig &cfg : other_region_configs) {
// if the new config for this volume equals any of the other // if the new config for this volume equals any of the other
// volume configs that are not currently associated to this // volume configs that are not currently associated to this
// region, it means the region subdivision does not make // region, it means the region subdivision does not make
// sense anymore // sense anymore
if (it->equals(new_config)) { if (cfg.equals(new_config)) {
rearrange_regions = true; rearrange_regions = true;
goto NEXT_REGION; goto NEXT_REGION;
} }
@ -500,50 +454,48 @@ Print::apply_config(DynamicPrintConfig config)
// if we're here and the new region config is different from the old // 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 // one, we need to apply the new config and invalidate all objects
// (possible optimization: only invalidate objects using this region) // (possible optimization: only invalidate objects using this region)
t_config_option_keys region_config_diff = region->config.diff(new_config); t_config_option_keys diff = region->config.diff(new_config);
if (!region_config_diff.empty()) { if (! diff.empty()) {
region->config.apply(new_config); region->config.apply(new_config, diff);
FOREACH_OBJECT(this, o) { for (PrintObject *object : this->objects)
if ((*o)->invalidate_state_by_config_options(region_config_diff)) invalidated |= object->invalidate_state_by_config_options(diff);
invalidated = true;
} }
} }
} }
} append(other_region_configs, this_region_configs);
other_region_configs.insert(other_region_configs.end(), this_region_configs.begin(), this_region_configs.end());
NEXT_REGION: NEXT_REGION:
continue; continue;
} }
if (rearrange_regions) { if (rearrange_regions) {
// the current subdivision of regions does not make sense anymore. // The current subdivision of regions does not make sense anymore.
// we need to remove all objects and re-add them // We need to remove all objects and re-add them.
ModelObjectPtrs model_objects; ModelObjectPtrs model_objects;
FOREACH_OBJECT(this, o) { model_objects.reserve(this->objects.size());
model_objects.push_back((*o)->model_object()); for (PrintObject *object : this->objects)
} model_objects.push_back(object->model_object());
this->clear_objects(); this->clear_objects();
for (ModelObjectPtrs::iterator it = model_objects.begin(); it != model_objects.end(); ++it) { for (ModelObject *mo : model_objects) {
this->add_model_object(*it); this->add_model_object(mo);
// Update layer_height_profile from the main thread as it may pull the data from the associated ModelObject. // Update layer_height_profile from the main thread as it may pull the data from the associated ModelObject.
this->objects.back()->update_layer_height_profile(); this->objects.back()->update_layer_height_profile();
} }
invalidated = true; invalidated = true;
} else { } else {
// Check validity of the layer height profiles. // Check validity of the layer height profiles.
FOREACH_OBJECT(this, o) { for (PrintObject *object : this->objects) {
if (! (*o)->layer_height_profile_valid) { if (! object->layer_height_profile_valid) {
// The layer_height_profile is not valid for some reason (updated by the user or invalidated due to some option change). // The layer_height_profile is not valid for some reason (updated by the user or invalidated due to some option change).
// Start slicing of this object from scratch. // Start slicing of this object from scratch.
(*o)->invalidate_all_steps(); object->invalidate_all_steps();
// Following line sets the layer_height_profile_valid flag. // Following line sets the layer_height_profile_valid flag.
(*o)->update_layer_height_profile(); object->update_layer_height_profile();
invalidated = true; invalidated = true;
} else if (! step_done(posSlice)) { } else if (! step_done(posSlice)) {
// Update layer_height_profile from the main thread as it may pull the data from the associated ModelObject. // Update layer_height_profile from the main thread as it may pull the data from the associated ModelObject.
// Only update if the slicing was not finished yet. // Only update if the slicing was not finished yet.
(*o)->update_layer_height_profile(); object->update_layer_height_profile();
} }
} }
} }
@ -563,8 +515,7 @@ bool Print::has_skirt() const
|| this->has_infinite_skirt(); || this->has_infinite_skirt();
} }
std::string std::string Print::validate() const
Print::validate() const
{ {
if (this->config.complete_objects) { if (this->config.complete_objects) {
// check horizontal clearance // check horizontal clearance
@ -686,8 +637,7 @@ Print::validate() const
// the bounding box of objects placed in copies position // the bounding box of objects placed in copies position
// (without taking skirt/brim/support material into account) // (without taking skirt/brim/support material into account)
BoundingBox BoundingBox Print::bounding_box() const
Print::bounding_box() const
{ {
BoundingBox bb; BoundingBox bb;
FOREACH_OBJECT(this, object) { FOREACH_OBJECT(this, object) {
@ -705,8 +655,7 @@ Print::bounding_box() const
// the total bounding box of extrusions, including skirt/brim/support material // the total bounding box of extrusions, including skirt/brim/support material
// this methods needs to be called even when no steps were processed, so it should // this methods needs to be called even when no steps were processed, so it should
// only use configuration values // only use configuration values
BoundingBox BoundingBox Print::total_bounding_box() const
Print::total_bounding_box() const
{ {
// get objects bounding box // get objects bounding box
BoundingBox bb = this->bounding_box(); BoundingBox bb = this->bounding_box();
@ -744,15 +693,13 @@ Print::total_bounding_box() const
return bb; return bb;
} }
double double Print::skirt_first_layer_height() const
Print::skirt_first_layer_height() const
{ {
if (this->objects.empty()) CONFESS("skirt_first_layer_height() can't be called without PrintObjects"); if (this->objects.empty()) CONFESS("skirt_first_layer_height() can't be called without PrintObjects");
return this->objects.front()->config.get_abs_value("first_layer_height"); return this->objects.front()->config.get_abs_value("first_layer_height");
} }
Flow Flow Print::brim_flow() const
Print::brim_flow() const
{ {
ConfigOptionFloatOrPercent width = this->config.first_layer_extrusion_width; ConfigOptionFloatOrPercent width = this->config.first_layer_extrusion_width;
if (width.value == 0) width = this->regions.front()->config.perimeter_extrusion_width; if (width.value == 0) width = this->regions.front()->config.perimeter_extrusion_width;
@ -771,8 +718,7 @@ Print::brim_flow() const
); );
} }
Flow Flow Print::skirt_flow() const
Print::skirt_flow() const
{ {
ConfigOptionFloatOrPercent width = this->config.first_layer_extrusion_width; ConfigOptionFloatOrPercent width = this->config.first_layer_extrusion_width;
if (width.value == 0) width = this->regions.front()->config.perimeter_extrusion_width; if (width.value == 0) width = this->regions.front()->config.perimeter_extrusion_width;
@ -792,8 +738,7 @@ Print::skirt_flow() const
} }
PrintRegionConfig PrintRegionConfig Print::_region_config_from_model_volume(const ModelVolume &volume)
Print::_region_config_from_model_volume(const ModelVolume &volume)
{ {
PrintRegionConfig config = this->default_region_config; PrintRegionConfig config = this->default_region_config;
{ {
@ -814,34 +759,30 @@ Print::_region_config_from_model_volume(const ModelVolume &volume)
return config; return config;
} }
bool bool Print::has_support_material() const
Print::has_support_material() const
{ {
FOREACH_OBJECT(this, object) { for (const PrintObject *object : this->objects)
if ((*object)->has_support_material()) return true; if (object->has_support_material())
} return true;
return false; return false;
} }
/* This method assigns extruders to the volumes having a material /* This method assigns extruders to the volumes having a material
but not having extruders set in the volume config. */ but not having extruders set in the volume config. */
void void Print::auto_assign_extruders(ModelObject* model_object) const
Print::auto_assign_extruders(ModelObject* model_object) const
{ {
// only assign extruders if object has more than one volume // only assign extruders if object has more than one volume
if (model_object->volumes.size() < 2) return; if (model_object->volumes.size() < 2)
return;
size_t extruders = this->config.nozzle_diameter.values.size(); // size_t extruders = this->config.nozzle_diameter.values.size();
for (ModelVolumePtrs::const_iterator v = model_object->volumes.begin(); v != model_object->volumes.end(); ++v) { for (size_t volume_id = 0; volume_id < model_object->volumes.size(); ++ volume_id) {
if (!(*v)->material_id().empty()) { ModelVolume *volume = model_object->volumes[volume_id];
//FIXME Vojtech: This assigns an extruder ID even to a modifier volume, if it has a material assigned. //FIXME Vojtech: This assigns an extruder ID even to a modifier volume, if it has a material assigned.
size_t extruder_id = (v - model_object->volumes.begin()) + 1; if (! volume->material_id().empty() && ! volume->config.has("extruder"))
if (!(*v)->config.has("extruder")) volume->config.opt<ConfigOptionInt>("extruder", true)->value = int(volume_id + 1);
(*v)->config.opt<ConfigOptionInt>("extruder", true)->value = int(extruder_id);
} }
} }
}
void Print::_make_skirt() void Print::_make_skirt()
{ {

View file

@ -232,8 +232,8 @@ public:
// ordered collections of extrusion paths to build skirt loops and brim // ordered collections of extrusion paths to build skirt loops and brim
ExtrusionEntityCollection skirt, brim; ExtrusionEntityCollection skirt, brim;
Print(); Print() : total_used_filament(0), total_extruded_volume(0) {}
~Print(); ~Print() { clear_objects(); }
// methods for handling objects // methods for handling objects
void clear_objects(); void clear_objects();
@ -293,7 +293,6 @@ public:
private: private:
void clear_regions(); void clear_regions();
void delete_region(size_t idx);
PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume); PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume);
}; };

View file

@ -128,11 +128,14 @@ SupportLayer* PrintObject::add_support_layer(int id, coordf_t height, coordf_t p
return support_layers.back(); return support_layers.back();
} }
// Called by Print::apply_config().
// This method only accepts PrintObjectConfig and PrintRegionConfig option keys.
bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys) bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys)
{ {
std::vector<PrintObjectStep> steps; if (opt_keys.empty())
return false;
// this method only accepts PrintObjectConfig and PrintRegionConfig option keys std::vector<PrintObjectStep> steps;
for (const t_config_option_key &opt_key : opt_keys) { for (const t_config_option_key &opt_key : opt_keys) {
if (opt_key == "perimeters" if (opt_key == "perimeters"
|| opt_key == "extra_perimeters" || opt_key == "extra_perimeters"

View file

@ -100,9 +100,6 @@ _constant()
Ref<SupportLayer> get_support_layer(int idx); Ref<SupportLayer> get_support_layer(int idx);
Ref<SupportLayer> add_support_layer(int id, coordf_t height, coordf_t print_z); Ref<SupportLayer> add_support_layer(int id, coordf_t height, coordf_t print_z);
bool invalidate_state_by_config_options(std::vector<std::string> opt_keys);
bool invalidate_step(PrintObjectStep step);
bool invalidate_all_steps();
bool step_done(PrintObjectStep step) bool step_done(PrintObjectStep step)
%code%{ RETVAL = THIS->state.is_done(step); %}; %code%{ RETVAL = THIS->state.is_done(step); %};
void set_step_done(PrintObjectStep step) void set_step_done(PrintObjectStep step)
@ -182,9 +179,6 @@ _constant()
size_t region_count() size_t region_count()
%code%{ RETVAL = THIS->regions.size(); %}; %code%{ RETVAL = THIS->regions.size(); %};
bool invalidate_state_by_config_options(std::vector<std::string> opt_keys);
bool invalidate_step(PrintStep step);
bool invalidate_all_steps();
bool step_done(PrintStep step) bool step_done(PrintStep step)
%code%{ RETVAL = THIS->state.is_done(step); %}; %code%{ RETVAL = THIS->state.is_done(step); %};
bool object_step_done(PrintObjectStep step) bool object_step_done(PrintObjectStep step)