Implemented custom extruder(tool) change from DoubleSlider

This commit is contained in:
YuSanka 2019-10-15 15:42:30 +02:00
parent 5c2b5a167b
commit 4b0fe7cba4
6 changed files with 95 additions and 9 deletions

View File

@ -586,6 +586,21 @@ std::string Model::propose_export_file_name_and_path(const std::string &new_exte
return boost::filesystem::path(this->propose_export_file_name_and_path()).replace_extension(new_extension).string();
}
std::vector<std::pair<double, DynamicPrintConfig>> Model:: get_custom_tool_changes(double default_layer_height) const
{
std::vector<std::pair<double, DynamicPrintConfig>> custom_tool_changes;
if (!custom_gcode_per_height.empty()) {
for (const CustomGCode& custom_gcode : custom_gcode_per_height)
if (custom_gcode.gcode == "tool_change") {
DynamicPrintConfig config;
config.set_key_value("extruder", new ConfigOptionInt(custom_gcode.extruder));
// For correct extruders(tools) changing, we should decrease custom_gcode.height value by one default layer height
custom_tool_changes.push_back({ custom_gcode.height - default_layer_height, config });
}
}
return custom_tool_changes;
}
ModelObject::~ModelObject()
{
this->clear_volumes();

View File

@ -836,6 +836,9 @@ public:
// Propose an output path, replace extension. The new_extension shall contain the initial dot.
std::string propose_export_file_name_and_path(const std::string &new_extension) const;
// from custom_gcode_per_height get just tool_change codes
std::vector<std::pair<double, DynamicPrintConfig>> get_custom_tool_changes(double default_layer_height) const;
private:
explicit Model(int) : ObjectBase(-1) { assert(this->id().invalid()); };
void assign_new_unique_ids_recursive();

View File

@ -636,11 +636,59 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
else
m_ranges.emplace_back(t_layer_height_range(m_ranges.back().first.second, DBL_MAX), nullptr);
}
// Convert input config ranges into continuous non-overlapping sorted vector of intervals and their configs,
// considering custom_tool_change values
void assign(const t_layer_config_ranges &in, const std::vector<std::pair<double, DynamicPrintConfig>> &custom_tool_changes) {
m_ranges.clear();
m_ranges.reserve(in.size());
// Input ranges are sorted lexicographically. First range trims the other ranges.
coordf_t last_z = 0;
for (const std::pair<const t_layer_height_range, DynamicPrintConfig> &range : in)
if (range.first.second > last_z) {
coordf_t min_z = std::max(range.first.first, 0.);
if (min_z > last_z + EPSILON) {
m_ranges.emplace_back(t_layer_height_range(last_z, min_z), nullptr);
last_z = min_z;
}
if (range.first.second > last_z + EPSILON) {
const DynamicPrintConfig* cfg = &range.second;
m_ranges.emplace_back(t_layer_height_range(last_z, range.first.second), cfg);
last_z = range.first.second;
}
}
// add ranges for extruder changes from custom_tool_changes
for (size_t i = 0; i < custom_tool_changes.size(); i++) {
const DynamicPrintConfig* cfg = &custom_tool_changes[i].second;
coordf_t cur_Z = custom_tool_changes[i].first;
coordf_t next_Z = i == custom_tool_changes.size()-1 ? DBL_MAX : custom_tool_changes[i+1].first;
if (cur_Z > last_z + EPSILON) {
if (i==0)
m_ranges.emplace_back(t_layer_height_range(last_z, cur_Z), nullptr);
m_ranges.emplace_back(t_layer_height_range(cur_Z, next_Z), cfg);
}
else if (next_Z > last_z + EPSILON)
m_ranges.emplace_back(t_layer_height_range(last_z, next_Z), cfg);
}
if (m_ranges.empty())
m_ranges.emplace_back(t_layer_height_range(0, DBL_MAX), nullptr);
else if (m_ranges.back().second == nullptr)
m_ranges.back().first.second = DBL_MAX;
else if (m_ranges.back().first.second != DBL_MAX)
m_ranges.emplace_back(t_layer_height_range(m_ranges.back().first.second, DBL_MAX), nullptr);
}
const DynamicPrintConfig* config(const t_layer_height_range &range) const {
auto it = std::lower_bound(m_ranges.begin(), m_ranges.end(), std::make_pair< t_layer_height_range, const DynamicPrintConfig*>(t_layer_height_range(range.first - EPSILON, range.second - EPSILON), nullptr));
assert(it != m_ranges.end());
assert(it == m_ranges.end() || std::abs(it->first.first - range.first ) < EPSILON);
assert(it == m_ranges.end() || std::abs(it->first.second - range.second) < EPSILON);
// #ys_FIXME_COLOR
// assert(it != m_ranges.end());
// assert(it == m_ranges.end() || std::abs(it->first.first - range.first ) < EPSILON);
// assert(it == m_ranges.end() || std::abs(it->first.second - range.second) < EPSILON);
if (it == m_ranges.end() ||
std::abs(it->first.first - range.first) > EPSILON ||
std::abs(it->first.second - range.second) > EPSILON )
return nullptr; // desired range doesn't found
return (it == m_ranges.end()) ? nullptr : it->second;
}
std::vector<std::pair<t_layer_height_range, const DynamicPrintConfig*>>::const_iterator begin() const { return m_ranges.cbegin(); }
@ -688,6 +736,13 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
// The object list did not change.
for (const ModelObject *model_object : m_model.objects)
model_object_status.emplace(model_object->id(), ModelObjectStatus::Old);
// But if custom gcode per layer height was changed
if (m_model.custom_gcode_per_height != model.custom_gcode_per_height) {
// we should stop background processing
update_apply_status(this->invalidate_step(psGCodeExport));
m_model.custom_gcode_per_height = model.custom_gcode_per_height;
}
} else if (model_object_list_extended(m_model, model)) {
// Add new objects. Their volumes and configs will be synchronized later.
update_apply_status(this->invalidate_step(psGCodeExport));
@ -749,11 +804,6 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
delete model_object;
}
}
if (model.custom_gcode_per_height != m_model.custom_gcode_per_height)
{
update_apply_status(this->invalidate_step(psGCodeExport));
m_model.custom_gcode_per_height = model.custom_gcode_per_height;
}
}
// 2) Map print objects including their transformation matrices.
@ -784,6 +834,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
for (PrintObject *print_object : m_objects)
print_object_status.emplace(PrintObjectStatus(print_object));
std::vector<std::pair<double, DynamicPrintConfig>> custom_tool_changes = m_model.get_custom_tool_changes(m_default_object_config.layer_height);
// 3) Synchronize ModelObjects & PrintObjects.
for (size_t idx_model_object = 0; idx_model_object < model.objects.size(); ++ idx_model_object) {
ModelObject &model_object = *m_model.objects[idx_model_object];
@ -791,7 +843,9 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
assert(it_status != model_object_status.end());
assert(it_status->status != ModelObjectStatus::Deleted);
const ModelObject& model_object_new = *model.objects[idx_model_object];
const_cast<ModelObjectStatus&>(*it_status).layer_ranges.assign(model_object_new.layer_config_ranges);
// ys_FIXME_COLOR
// const_cast<ModelObjectStatus&>(*it_status).layer_ranges.assign(model_object_new.layer_config_ranges);
const_cast<ModelObjectStatus&>(*it_status).layer_ranges.assign(model_object_new.layer_config_ranges, custom_tool_changes);
if (it_status->status == ModelObjectStatus::New)
// PrintObject instances will be added in the next loop.
continue;
@ -959,6 +1013,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
PrintRegionConfig this_region_config;
bool this_region_config_set = false;
for (PrintObject *print_object : m_objects) {
if(m_force_update_print_regions && !custom_tool_changes.empty())
goto print_object_end;
const LayerRanges *layer_ranges;
{
auto it_status = model_object_status.find(ModelObjectStatus(print_object->model_object()->id()));

View File

@ -361,6 +361,9 @@ public:
// Accessed by SupportMaterial
const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; }
// force update of PrintRegions, when custom_tool_change is not empty and (Re)Slicing is started
void set_force_update_print_regions(bool force_update_print_regions) { m_force_update_print_regions = force_update_print_regions; }
protected:
// methods for handling regions
PrintRegion* get_region(size_t idx) { return m_regions[idx]; }
@ -403,6 +406,9 @@ private:
// Estimated print time, filament consumed.
PrintStatistics m_print_statistics;
// flag used
bool m_force_update_print_regions = false;
// To allow GCode to set the Print's GCodeExport step status.
friend class GCode;
// Allow PrintObject to access m_mutex and m_cancel_callback.

View File

@ -128,6 +128,11 @@ public:
// This "finished" flag does not account for the final export of the output file (.gcode or zipped PNGs),
// and it does not account for the OctoPrint scheduling.
bool finished() const { return m_print->finished(); }
void set_force_update_print_regions(bool force_update_print_regions) {
if (m_fff_print)
m_fff_print->set_force_update_print_regions(force_update_print_regions);
}
private:
void thread_proc();

View File

@ -2922,6 +2922,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
this->update_print_volume_state();
// Apply new config to the possibly running background task.
bool was_running = this->background_process.running();
this->background_process.set_force_update_print_regions(force_validation);
Print::ApplyStatus invalidated = this->background_process.apply(this->q->model(), wxGetApp().preset_bundle->full_config());
// Just redraw the 3D canvas without reloading the scene to consume the update of the layer height profile.