mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 08:47:52 -06:00
WIP: Synchronization of Model / ModelObject with Print / PrintObject
This commit is contained in:
parent
7ed2752b2b
commit
bb1dfa3522
2 changed files with 228 additions and 126 deletions
|
@ -376,6 +376,16 @@ double Print::max_allowed_layer_height() const
|
||||||
return nozzle_diameter_max;
|
return nozzle_diameter_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PrintRegionConfig region_config_from_model_volume(const PrintRegionConfig &default_region_config, const ModelVolume &volume)
|
||||||
|
{
|
||||||
|
PrintRegionConfig config = default_region_config;
|
||||||
|
normalize_and_apply_config(config, volume.get_object()->config);
|
||||||
|
normalize_and_apply_config(config, volume.config);
|
||||||
|
if (! volume.material_id().empty())
|
||||||
|
normalize_and_apply_config(config, volume.material()->config);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
// Caller is responsible for supplying models whose objects don't collide
|
// Caller is responsible for supplying models whose objects don't collide
|
||||||
// and have explicit instance positions.
|
// and have explicit instance positions.
|
||||||
void Print::add_model_object(ModelObject* model_object, int idx)
|
void Print::add_model_object(ModelObject* model_object, int idx)
|
||||||
|
@ -397,7 +407,7 @@ void Print::add_model_object(ModelObject* model_object, int idx)
|
||||||
if (! volume->is_model_part() && ! volume->is_modifier())
|
if (! volume->is_model_part() && ! volume->is_modifier())
|
||||||
continue;
|
continue;
|
||||||
// Get the config applied to this volume.
|
// Get the config applied to this volume.
|
||||||
PrintRegionConfig config = this->_region_config_from_model_volume(*volume);
|
PrintRegionConfig config = region_config_from_model_volume(m_default_region_config, *volume);
|
||||||
// Find an existing print region with the same config.
|
// Find an existing print region with the same config.
|
||||||
size_t region_id = size_t(-1);
|
size_t region_id = size_t(-1);
|
||||||
for (size_t i = 0; i < m_regions.size(); ++ i)
|
for (size_t i = 0; i < m_regions.size(); ++ i)
|
||||||
|
@ -424,35 +434,7 @@ void Print::add_model_object(ModelObject* model_object, int idx)
|
||||||
object->config_apply(src_normalized, true);
|
object->config_apply(src_normalized, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update placeholders
|
this->update_object_placeholders();
|
||||||
{
|
|
||||||
// get the first input file name
|
|
||||||
std::string input_file;
|
|
||||||
std::vector<std::string> v_scale;
|
|
||||||
for (const PrintObject *object : m_objects) {
|
|
||||||
const ModelObject &mobj = *object->model_object();
|
|
||||||
#if ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
|
|
||||||
// CHECK_ME -> Is the following correct ?
|
|
||||||
v_scale.push_back("x:" + boost::lexical_cast<std::string>(mobj.instances[0]->get_scaling_factor(X) * 100) +
|
|
||||||
"% y:" + boost::lexical_cast<std::string>(mobj.instances[0]->get_scaling_factor(Y) * 100) +
|
|
||||||
"% z:" + boost::lexical_cast<std::string>(mobj.instances[0]->get_scaling_factor(Z) * 100) + "%");
|
|
||||||
#else
|
|
||||||
v_scale.push_back(boost::lexical_cast<std::string>(mobj.instances[0]->scaling_factor * 100) + "%");
|
|
||||||
#endif // ENABLE_MODELINSTANCE_3D_FULL_TRANSFORM
|
|
||||||
if (input_file.empty())
|
|
||||||
input_file = mobj.input_file;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlaceholderParser &pp = m_placeholder_parser;
|
|
||||||
pp.set("scale", v_scale);
|
|
||||||
if (! input_file.empty()) {
|
|
||||||
// get basename with and without suffix
|
|
||||||
const std::string input_basename = boost::filesystem::path(input_file).filename().string();
|
|
||||||
pp.set("input_filename", input_basename);
|
|
||||||
const std::string input_basename_base = input_basename.substr(0, input_basename.find_last_of("."));
|
|
||||||
pp.set("input_filename_base", input_basename_base);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Print::apply_config(DynamicPrintConfig config)
|
bool Print::apply_config(DynamicPrintConfig config)
|
||||||
|
@ -514,12 +496,12 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||||
// 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 (! this_region_config.equals(this->_region_config_from_model_volume(volume))) {
|
if (! this_region_config.equals(region_config_from_model_volume(m_default_region_config, volume))) {
|
||||||
rearrange_regions = true;
|
rearrange_regions = true;
|
||||||
goto exit_for_rearrange_regions;
|
goto exit_for_rearrange_regions;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this_region_config = this->_region_config_from_model_volume(volume);
|
this_region_config = region_config_from_model_volume(m_default_region_config, volume);
|
||||||
this_region_config_set = true;
|
this_region_config_set = true;
|
||||||
}
|
}
|
||||||
for (const PrintRegionConfig &cfg : other_region_configs) {
|
for (const PrintRegionConfig &cfg : other_region_configs) {
|
||||||
|
@ -681,7 +663,7 @@ static inline bool transform3d_equal(const Transform3d &lhs, const Transform3d &
|
||||||
struct PrintInstances
|
struct PrintInstances
|
||||||
{
|
{
|
||||||
Transform3d trafo;
|
Transform3d trafo;
|
||||||
Points instances;
|
Points copies;
|
||||||
bool operator<(const PrintInstances &rhs) const { return transform3d_lower(this->trafo, rhs.trafo); }
|
bool operator<(const PrintInstances &rhs) const { return transform3d_lower(this->trafo, rhs.trafo); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -690,26 +672,46 @@ static std::vector<PrintInstances> print_objects_from_model_object(const ModelOb
|
||||||
{
|
{
|
||||||
std::set<PrintInstances> trafos;
|
std::set<PrintInstances> trafos;
|
||||||
PrintInstances trafo;
|
PrintInstances trafo;
|
||||||
trafo.instances.assign(1, Point());
|
trafo.copies.assign(1, Point());
|
||||||
for (ModelInstance *model_instance : model_object.instances)
|
for (ModelInstance *model_instance : model_object.instances)
|
||||||
if (model_instance->is_printable()) {
|
if (model_instance->is_printable()) {
|
||||||
const Vec3d &offst = model_instance->get_offset();
|
const Vec3d &offst = model_instance->get_offset();
|
||||||
trafo.trafo = model_instance->world_matrix(true);
|
trafo.trafo = model_instance->world_matrix(true);
|
||||||
trafo.instances.front() = Point::new_scale(offst(0), offst(1));
|
trafo.copies.front() = Point::new_scale(offst(0), offst(1));
|
||||||
auto it = trafos.find(trafo);
|
auto it = trafos.find(trafo);
|
||||||
if (it == trafos.end())
|
if (it == trafos.end())
|
||||||
trafos.emplace(trafo);
|
trafos.emplace(trafo);
|
||||||
else
|
else
|
||||||
const_cast<PrintInstances&>(*it).instances.emplace_back(trafo.instances.front());
|
const_cast<PrintInstances&>(*it).copies.emplace_back(trafo.copies.front());
|
||||||
}
|
}
|
||||||
return std::vector<PrintInstances>(trafos.begin(), trafos.end());
|
return std::vector<PrintInstances>(trafos.begin(), trafos.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Print::apply(const Model &model, const DynamicPrintConfig &config)
|
bool Print::apply(const Model &model, const DynamicPrintConfig &config_in)
|
||||||
{
|
{
|
||||||
|
// Make a copy of the config, normalize it.
|
||||||
|
DynamicPrintConfig config(config_in);
|
||||||
|
config.normalize();
|
||||||
|
// Collect changes to print config.
|
||||||
|
t_config_option_keys print_diff = m_config.diff(config);
|
||||||
|
t_config_option_keys object_diff = m_default_object_config.diff(config);
|
||||||
|
t_config_option_keys region_diff = m_default_region_config.diff(config);
|
||||||
|
|
||||||
// Grab the lock for the Print / PrintObject milestones.
|
// Grab the lock for the Print / PrintObject milestones.
|
||||||
tbb::mutex::scoped_lock lock(m_mutex);
|
tbb::mutex::scoped_lock lock(m_mutex);
|
||||||
|
|
||||||
|
// The following call may stop the background processing.
|
||||||
|
bool invalidated = this->invalidate_state_by_config_options(print_diff);
|
||||||
|
// Apply variables to placeholder parser. The placeholder parser is used by G-code export,
|
||||||
|
// which should be stopped if print_diff is not empty.
|
||||||
|
m_placeholder_parser.apply_config(config);
|
||||||
|
// It is also safe to change m_config now after this->invalidate_state_by_config_options() call.
|
||||||
|
m_config.apply_only(config, print_diff, true);
|
||||||
|
// Handle changes to object config defaults
|
||||||
|
m_default_object_config.apply_only(config, object_diff, true);
|
||||||
|
// Handle changes to regions config defaults
|
||||||
|
m_default_region_config.apply_only(config, region_diff, true);
|
||||||
|
|
||||||
struct ModelObjectStatus {
|
struct ModelObjectStatus {
|
||||||
enum Status {
|
enum Status {
|
||||||
Unknown,
|
Unknown,
|
||||||
|
@ -719,8 +721,9 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config)
|
||||||
Deleted,
|
Deleted,
|
||||||
};
|
};
|
||||||
ModelObjectStatus(ModelID id, Status status = Unknown) : id(id), status(status) {}
|
ModelObjectStatus(ModelID id, Status status = Unknown) : id(id), status(status) {}
|
||||||
ModelID id;
|
ModelID id;
|
||||||
Status status;
|
Status status;
|
||||||
|
t_config_option_keys object_config_diff;
|
||||||
// Search by id.
|
// Search by id.
|
||||||
bool operator<(const ModelObjectStatus &rhs) const { return id < rhs.id; }
|
bool operator<(const ModelObjectStatus &rhs) const { return id < rhs.id; }
|
||||||
};
|
};
|
||||||
|
@ -729,7 +732,8 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config)
|
||||||
// 1) Synchronize model objects.
|
// 1) Synchronize model objects.
|
||||||
if (model.id() != m_model.id()) {
|
if (model.id() != m_model.id()) {
|
||||||
// Kill everything, initialize from scratch.
|
// Kill everything, initialize from scratch.
|
||||||
// The following call shall kill any computation if running.
|
// Stop background processing.
|
||||||
|
m_cancel_callback();
|
||||||
this->invalidate_all_steps();
|
this->invalidate_all_steps();
|
||||||
for (PrintObject *object : m_objects) {
|
for (PrintObject *object : m_objects) {
|
||||||
model_object_status.emplace(object->model_object()->id(), ModelObjectStatus::Deleted);
|
model_object_status.emplace(object->model_object()->id(), ModelObjectStatus::Deleted);
|
||||||
|
@ -746,6 +750,8 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config)
|
||||||
} else if (model_object_list_extended(m_model, model)) {
|
} else if (model_object_list_extended(m_model, model)) {
|
||||||
// Add new objects. Their volumes and configs will be synchronized later.
|
// Add new objects. Their volumes and configs will be synchronized later.
|
||||||
this->invalidate_step(psGCodeExport);
|
this->invalidate_step(psGCodeExport);
|
||||||
|
for (const ModelObject *model_object : m_model.objects)
|
||||||
|
model_object_status.emplace(model_object->id(), ModelObjectStatus::Old);
|
||||||
for (size_t i = m_model.objects.size(); i < model.objects.size(); ++ i) {
|
for (size_t i = m_model.objects.size(); i < model.objects.size(); ++ i) {
|
||||||
model_object_status.emplace(model.objects[i]->id(), ModelObjectStatus::New);
|
model_object_status.emplace(model.objects[i]->id(), ModelObjectStatus::New);
|
||||||
m_model.objects.emplace_back(model.objects[i]->clone(&m_model));
|
m_model.objects.emplace_back(model.objects[i]->clone(&m_model));
|
||||||
|
@ -770,7 +776,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config)
|
||||||
} else {
|
} else {
|
||||||
// Existing ModelObject re-added (possibly moved in the list).
|
// Existing ModelObject re-added (possibly moved in the list).
|
||||||
m_model.objects.emplace_back(*it);
|
m_model.objects.emplace_back(*it);
|
||||||
model_object_status.emplace(mobj->id(), ModelObjectStatus::Old);
|
model_object_status.emplace(mobj->id(), ModelObjectStatus::Moved);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool deleted_any = false;
|
bool deleted_any = false;
|
||||||
|
@ -835,7 +841,7 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config)
|
||||||
// PrintObject instances will be added in the next loop.
|
// PrintObject instances will be added in the next loop.
|
||||||
continue;
|
continue;
|
||||||
// Update the ModelObject instance, possibly invalidate the linked PrintObjects.
|
// Update the ModelObject instance, possibly invalidate the linked PrintObjects.
|
||||||
assert(it_status->status == ModelObjectStatus::Moved);
|
assert(it_status->status == ModelObjectStatus::Old || it_status->status == ModelObjectStatus::Moved);
|
||||||
const ModelObject &model_object_new = *model.objects[idx_model_object];
|
const ModelObject &model_object_new = *model.objects[idx_model_object];
|
||||||
// Check whether a model part volume was added or removed, their transformations or order changed.
|
// Check whether a model part volume was added or removed, their transformations or order changed.
|
||||||
bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::MODEL_PART);
|
bool model_parts_differ = model_volume_list_changed(model_object, model_object_new, ModelVolume::MODEL_PART);
|
||||||
|
@ -864,87 +870,187 @@ bool Print::apply(const Model &model, const DynamicPrintConfig &config)
|
||||||
}
|
}
|
||||||
if (! model_parts_differ && ! modifiers_differ) {
|
if (! model_parts_differ && ! modifiers_differ) {
|
||||||
// Synchronize the remaining data of ModelVolumes (name, config, m_type, m_material_id)
|
// Synchronize the remaining data of ModelVolumes (name, config, m_type, m_material_id)
|
||||||
|
// Synchronize Object's config.
|
||||||
|
t_config_option_keys &this_object_config_diff = const_cast<ModelObjectStatus&>(*it_status).object_config_diff;
|
||||||
|
this_object_config_diff = model_object.config.diff(model_object_new.config);
|
||||||
|
if (! this_object_config_diff.empty())
|
||||||
|
model_object.config.apply_only(model_object_new.config, this_object_config_diff, true);
|
||||||
|
if (! this_object_config_diff.empty() || ! this_object_config_diff.empty()) {
|
||||||
|
PrintObjectConfig new_config = m_default_object_config;
|
||||||
|
normalize_and_apply_config(new_config, model_object.config);
|
||||||
|
auto range = print_object_status.equal_range(PrintObjectStatus(model_object.id()));
|
||||||
|
for (auto it = range.first; it != range.second; ++ it) {
|
||||||
|
t_config_option_keys diff = it->print_object->config().diff(new_config);
|
||||||
|
invalidated |= it->print_object->invalidate_state_by_config_options(diff);
|
||||||
|
it->print_object->config_apply_only(new_config, diff, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4) Generate PrintObjects from ModelObjects and their instances.
|
// 4) Generate PrintObjects from ModelObjects and their instances.
|
||||||
std::vector<PrintObject*> print_objects_new;
|
{
|
||||||
print_objects_new.reserve(std::max(m_objects.size(), m_model.objects.size()));
|
std::vector<PrintObject*> print_objects_new;
|
||||||
// Walk over all new model objects and check, whether there are matching PrintObjects.
|
print_objects_new.reserve(std::max(m_objects.size(), m_model.objects.size()));
|
||||||
for (ModelObject *model_object : m_model.objects) {
|
// Walk over all new model objects and check, whether there are matching PrintObjects.
|
||||||
auto range = print_object_status.equal_range(PrintObjectStatus(model_object->id()));
|
for (ModelObject *model_object : m_model.objects) {
|
||||||
std::vector<const PrintObjectStatus*> old;
|
auto range = print_object_status.equal_range(PrintObjectStatus(model_object->id()));
|
||||||
if (range.first != range.second) {
|
std::vector<const PrintObjectStatus*> old;
|
||||||
old.reserve(print_object_status.count(PrintObjectStatus(model_object->id())));
|
if (range.first != range.second) {
|
||||||
for (auto it = range.first; it != range.second; ++ it)
|
old.reserve(print_object_status.count(PrintObjectStatus(model_object->id())));
|
||||||
if (it->status != PrintObjectStatus::Deleted)
|
for (auto it = range.first; it != range.second; ++ it)
|
||||||
old.emplace_back(&(*it));
|
if (it->status != PrintObjectStatus::Deleted)
|
||||||
|
old.emplace_back(&(*it));
|
||||||
|
}
|
||||||
|
// Generate a list of trafos and XY offsets for instances of a ModelObject
|
||||||
|
PrintObjectConfig config = m_default_object_config;
|
||||||
|
normalize_and_apply_config(config, model_object->config);
|
||||||
|
std::vector<PrintInstances> new_print_instances = print_objects_from_model_object(*model_object);
|
||||||
|
if (old.empty()) {
|
||||||
|
// Simple case, just generate new instances.
|
||||||
|
for (const PrintInstances &print_instances : new_print_instances) {
|
||||||
|
PrintObject *print_object = new PrintObject(this, model_object, model_object->raw_bounding_box());
|
||||||
|
print_object->set_copies(print_instances.copies);
|
||||||
|
print_object->config_apply(config);
|
||||||
|
print_objects_new.emplace_back(print_object);
|
||||||
|
print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Complex case, try to merge the two lists.
|
||||||
|
// Sort the old lexicographically by their trafos.
|
||||||
|
std::sort(old.begin(), old.end(), [](const PrintObjectStatus *lhs, const PrintObjectStatus *rhs){ return transform3d_lower(lhs->trafo, rhs->trafo); });
|
||||||
|
// Merge the old / new lists.
|
||||||
|
auto it_old = old.begin();
|
||||||
|
for (const PrintInstances &new_instances : new_print_instances) {
|
||||||
|
for (; transform3d_lower((*it_old)->trafo, new_instances.trafo); ++ it_old);
|
||||||
|
if (! transform3d_equal((*it_old)->trafo, new_instances.trafo)) {
|
||||||
|
// This is a new instance (or a set of instances with the same trafo). Just add it.
|
||||||
|
PrintObject *print_object = new PrintObject(this, model_object, model_object->raw_bounding_box());
|
||||||
|
print_object->set_copies(new_instances.copies);
|
||||||
|
print_object->config_apply(config);
|
||||||
|
print_objects_new.emplace_back(print_object);
|
||||||
|
print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New));
|
||||||
|
} else if ((*it_old)->print_object->copies() != new_instances.copies) {
|
||||||
|
// The PrintObject already exists and the copies differ. The only step currently sensitive to the order is the G-code generator.
|
||||||
|
// Stop it.
|
||||||
|
this->invalidate_step(psGCodeExport);
|
||||||
|
(*it_old)->print_object->set_copies(new_instances.copies);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Generate a list of trafos and XY offsets for instances of a ModelObject
|
if (m_objects != print_objects_new) {
|
||||||
std::vector<PrintInstances> new_print_instances = print_objects_from_model_object(*model_object);
|
m_cancel_callback();
|
||||||
if (old.empty()) {
|
m_objects = print_objects_new;
|
||||||
// Simple case, just generate new instances.
|
}
|
||||||
for (const PrintInstances &print_instances : new_print_instances) {
|
}
|
||||||
PrintObject *print_object = new PrintObject(this, model_object, model_object->raw_bounding_box());
|
|
||||||
print_objects_new.emplace_back(print_object);
|
// 5) Synchronize configs of ModelVolumes, synchronize AMF / 3MF materials (and their configs), refresh PrintRegions.
|
||||||
print_object_status.emplace(PrintObjectStatus(print_object, PrintObjectStatus::New));
|
// Update reference counts of regions from the remaining PrintObjects and their volumes.
|
||||||
|
// Regions with zero references could and should be reused.
|
||||||
|
for (PrintRegion *region : m_regions)
|
||||||
|
region->m_refcnt = 0;
|
||||||
|
for (PrintObject *print_object : m_objects) {
|
||||||
|
int idx_region = 0;
|
||||||
|
for (const auto &volumes : print_object->region_volumes) {
|
||||||
|
if (! volumes.empty())
|
||||||
|
++ m_regions[idx_region];
|
||||||
|
++ idx_region;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All regions now have distinct settings.
|
||||||
|
// Check whether applying the new region config defaults we'd get different regions.
|
||||||
|
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 *print_object : m_objects) {
|
||||||
|
if (region_id < print_object->region_volumes.size()) {
|
||||||
|
for (int volume_id : print_object->region_volumes[region_id]) {
|
||||||
|
const ModelVolume &volume = *print_object->model_object()->volumes[volume_id];
|
||||||
|
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(region_config_from_model_volume(m_default_region_config, volume)))
|
||||||
|
// Regions were split. Reset this print_object.
|
||||||
|
goto print_object_end;
|
||||||
|
} else {
|
||||||
|
this_region_config = region_config_from_model_volume(m_default_region_config, volume);
|
||||||
|
for (size_t i = 0; i < region_id; ++ i)
|
||||||
|
if (m_regions[i]->config().equals(this_region_config))
|
||||||
|
// Regions were merged. Reset this print_object.
|
||||||
|
goto print_object_end;
|
||||||
|
this_region_config_set = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
print_object_end:
|
||||||
|
print_object->invalidate_all_steps();
|
||||||
|
// Decrease the references to regions from this volume.
|
||||||
|
int ireg = 0;
|
||||||
|
for (const std::vector<int> &volumes : print_object->region_volumes) {
|
||||||
|
if (! volumes.empty())
|
||||||
|
-- m_regions[ireg];
|
||||||
|
++ ireg;
|
||||||
|
}
|
||||||
|
print_object->region_volumes.clear();
|
||||||
|
}
|
||||||
|
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 *print_object : m_objects)
|
||||||
|
if (region_id < print_object->region_volumes.size() && ! print_object->region_volumes[region_id].empty())
|
||||||
|
invalidated |= print_object->invalidate_state_by_config_options(diff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Complex case, try to merge the two lists.
|
|
||||||
// Sort the old lexicographically by their trafos.
|
|
||||||
std::sort(old.begin(), old.end(), [](const PrintObjectStatus *lhs, const PrintObjectStatus *rhs){ return transform3d_lower(lhs->trafo, rhs->trafo); });
|
|
||||||
// Merge the old / new lists.
|
|
||||||
|
|
||||||
}
|
|
||||||
if (m_objects != print_objects_new) {
|
|
||||||
m_cancel_callback();
|
|
||||||
m_objects = print_objects_new;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synchronize materials.
|
// Possibly add new regions for the newly added or resetted PrintObjects.
|
||||||
|
for (size_t idx_print_object = 0; idx_print_object < m_objects.size(); ++ idx_print_object) {
|
||||||
#if 0
|
PrintObject &print_object0 = *m_objects[idx_print_object];
|
||||||
{
|
const ModelObject &model_object = *print_object0.model_object();
|
||||||
m_model = model;
|
std::vector<int> map_volume_to_region(model_object.volumes.size(), -1);
|
||||||
for (const ModelObject *model_object : m_model.objects) {
|
for (size_t i = idx_print_object; i < m_objects.size() && m_objects[i]->model_object() == &model_object; ++ i) {
|
||||||
PrintObject *object = new PrintObject(this, model_object, model_object->raw_bounding_box());
|
PrintObject &print_object = *m_objects[i];
|
||||||
m_objects.emplace_back(object);
|
unsigned int volume_id = 0;
|
||||||
size_t volume_id = 0;
|
for (const ModelVolume *volume : model_object.volumes) {
|
||||||
for (const ModelVolume *volume : model_object->volumes) {
|
|
||||||
if (! volume->is_model_part() && ! volume->is_modifier())
|
if (! volume->is_model_part() && ! volume->is_modifier())
|
||||||
continue;
|
continue;
|
||||||
// Get the config applied to this volume.
|
int region_id = -1;
|
||||||
PrintRegionConfig config = this->_region_config_from_model_volume(*volume);
|
if (&print_object == &print_object0) {
|
||||||
// Find an existing print region with the same config.
|
// Get the config applied to this volume.
|
||||||
size_t region_id = size_t(-1);
|
PrintRegionConfig config = region_config_from_model_volume(m_default_region_config, *volume);
|
||||||
for (size_t i = 0; i < m_regions.size(); ++ i)
|
// Find an existing print region with the same config.
|
||||||
if (config.equals(m_regions[i]->config())) {
|
for (int i = 0; i < (int)m_regions.size(); ++ i)
|
||||||
region_id = i;
|
if (config.equals(m_regions[i]->config())) {
|
||||||
break;
|
region_id = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// If no region exists with the same config, create a new one.
|
||||||
|
if (region_id == size_t(-1)) {
|
||||||
|
for (region_id = 0; region_id < m_regions.size(); ++ region_id)
|
||||||
|
if (m_regions[region_id]->m_refcnt == 0) {
|
||||||
|
// An empty slot was found.
|
||||||
|
m_regions[region_id]->set_config(std::move(config));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (region_id == m_regions.size())
|
||||||
|
this->add_region(config);
|
||||||
}
|
}
|
||||||
// If no region exists with the same config, create a new one.
|
map_volume_to_region[volume_id] = region_id;
|
||||||
if (region_id == size_t(-1)) {
|
} else
|
||||||
region_id = m_regions.size();
|
region_id = map_volume_to_region[volume_id];
|
||||||
this->add_region(config);
|
|
||||||
}
|
|
||||||
// Assign volume to a region.
|
// Assign volume to a region.
|
||||||
object->add_region_volume(region_id, volume_id);
|
if (volume_id >= print_object.region_volumes.size())
|
||||||
|
print_object.add_region_volume(region_id, volume_id);
|
||||||
++ volume_id;
|
++ 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Synchronize m_model.objects with model.objects
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
this->update_object_placeholders();
|
this->update_object_placeholders();
|
||||||
}
|
}
|
||||||
|
@ -1284,16 +1390,6 @@ Flow Print::skirt_flow() const
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintRegionConfig Print::_region_config_from_model_volume(const ModelVolume &volume)
|
|
||||||
{
|
|
||||||
PrintRegionConfig config = this->default_region_config();
|
|
||||||
normalize_and_apply_config(config, volume.get_object()->config);
|
|
||||||
normalize_and_apply_config(config, volume.config);
|
|
||||||
if (! volume.material_id().empty())
|
|
||||||
normalize_and_apply_config(config, volume.material()->config);
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Print::has_support_material() const
|
bool Print::has_support_material() const
|
||||||
{
|
{
|
||||||
for (const PrintObject *object : m_objects)
|
for (const PrintObject *object : m_objects)
|
||||||
|
|
|
@ -139,19 +139,25 @@ public:
|
||||||
// Average diameter of nozzles participating on extruding this region.
|
// Average diameter of nozzles participating on extruding this region.
|
||||||
coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const;
|
coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const;
|
||||||
// Average diameter of nozzles participating on extruding this region.
|
// Average diameter of nozzles participating on extruding this region.
|
||||||
coordf_t bridging_height_avg(const PrintConfig &print_config) const;
|
coordf_t bridging_height_avg(const PrintConfig &print_config) const;
|
||||||
|
|
||||||
// Methods modifying the PrintRegion's state:
|
// Methods modifying the PrintRegion's state:
|
||||||
public:
|
public:
|
||||||
Print* print() { return m_print; }
|
Print* print() { return m_print; }
|
||||||
void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) { this->m_config.apply_only(other, keys, ignore_nonexistent); }
|
void set_config(const PrintRegionConfig &config) { m_config = config; }
|
||||||
|
void set_config(PrintRegionConfig &&config) { m_config = std::move(config); }
|
||||||
|
void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false)
|
||||||
|
{ this->m_config.apply_only(other, keys, ignore_nonexistent); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
size_t m_refcnt;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Print *m_print;
|
Print *m_print;
|
||||||
PrintRegionConfig m_config;
|
PrintRegionConfig m_config;
|
||||||
|
|
||||||
PrintRegion(Print* print) : m_print(print) {}
|
PrintRegion(Print* print) : m_refcnt(0), m_print(print) {}
|
||||||
PrintRegion(Print* print, const PrintRegionConfig &config) : m_print(print), m_config(config) {}
|
PrintRegion(Print* print, const PrintRegionConfig &config) : m_refcnt(0), m_print(print), m_config(config) {}
|
||||||
~PrintRegion() {}
|
~PrintRegion() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -196,12 +202,13 @@ public:
|
||||||
const SupportLayerPtrs& support_layers() const { return m_support_layers; }
|
const SupportLayerPtrs& support_layers() const { return m_support_layers; }
|
||||||
const Transform3d& trafo() const { return m_trafo; }
|
const Transform3d& trafo() const { return m_trafo; }
|
||||||
|
|
||||||
const Points& copies() const { return m_copies; }
|
const Points& copies() const { return m_copies; }
|
||||||
bool add_copy(const Vec2d &point);
|
bool add_copy(const Vec2d &point);
|
||||||
bool delete_last_copy();
|
bool delete_last_copy();
|
||||||
bool delete_all_copies() { return this->set_copies(Points()); }
|
bool delete_all_copies() { return this->set_copies(Points()); }
|
||||||
bool set_copies(const Points &points);
|
bool set_copies(const Points &points);
|
||||||
bool reload_model_instances();
|
bool reload_model_instances();
|
||||||
|
|
||||||
// since the object is aligned to origin, bounding box coincides with size
|
// since the object is aligned to origin, bounding box coincides with size
|
||||||
BoundingBox bounding_box() const { return BoundingBox(Point(0,0), to_2d(this->size)); }
|
BoundingBox bounding_box() const { return BoundingBox(Point(0,0), to_2d(this->size)); }
|
||||||
|
|
||||||
|
@ -486,7 +493,6 @@ private:
|
||||||
void update_object_placeholders();
|
void update_object_placeholders();
|
||||||
|
|
||||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
||||||
PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume);
|
|
||||||
|
|
||||||
// If the background processing stop was requested, throw CanceledException.
|
// If the background processing stop was requested, throw CanceledException.
|
||||||
// To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly.
|
// To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue